Interactive Brokers è uno dei principali broker utilizzati dai trader algoritmici retail a causa dei suoi relativamente bassi requisiti minimi di capitale sul conto (10.000 USD) e la robusta API. In questo articolo faremo uso di un account demo per automatizzare gli ordini con l’API di Interactive Brokers, tramite Python e il package IBPy.

Nota: non ho alcuna affiliazione con Interactive Brokers. Ho avuto modo di usarlo in molti contesti e quindi ho familiarità con il loro software.

L' API di Interactive Brokers

Interactive Brokers è una grande azienda e in quanto tale si rivolge a una vasta gamma di operatori, che vanno dai trader retail discrezionali agli istituzionali automatizzati. Questo a fatto in modo che questo broker abbia sviluppato un’interfaccia GUI completa e robusta, la Trader Workstation (TWS).

Oltre a TWS c’è anche un semplice componente chiamato IB Gateway, che fornisce lo stesso accesso ai server di IB ma senza le funzionalità extra della GUI. Per i nostri scopi di trading automatico non avremo realmente bisogno della GUI TWS, ma penso che possa essere utile utilizzarla per questo tutorial dimostrativo.

L’architettura sottostante si basa su un modello client / server che offre sia feed di dati di esecuzione e di mercato (storici e in tempo reale) tramite un’API. Utilizzeremo questa API  per inviare ordini automatici, tramite IBPy.

IBPy è stato scritto per “avvolgere” l’API Java nativa e renderla semplice da essere chiamata tramite Python. Le due principali librerie a cui siamo interessati all’interno di IBPy sono ib.extib.opt. Quest’ultimo è di livello superiore e fa uso della funzionalità nel primo.

Nella seguente implementazione creeremo un esempio estremamente semplice, che invierà semplicemente un singolo ordine di mercato per acquistare 100 unità di azioni Google, utilizzando il routing intelligente degli ordini. Quest’ultimo è progettato per ottenere il miglior prezzo, anche se in determinate situazioni può non essere ottimale. Tuttavia, sarà sufficiente per gli scopi di questo tutorial.

Implementazione in Python

Prima di iniziare è necessario aver attivato un account su Interactive Brokers. Inoltre è necessario disporre di uno ambiente di lavoro in in modo da poter installare IBPy, che ti consentirà di legare insieme altri aspetti del tuo codice. Per creare un ambiente Python puoi leggere il mio precedente articolo su come installare di un ambiente di backtesting in Python.

Installare IBPy

IBPy è un wrapper Python sviluppato attorno all’API Interactive Brokers basata su Java. Rende un po ‘meno problematico lo sviluppo dei sistemi di trading algoritmico in Python. Sarà utilizzato come base per tutte le successive comunicazioni con Interactive Brokers finché non considereremo il protocollo FIX in un secondo momento. Poiché IBPy è gestito su GitHub come repository git, sarà necessario installare git. Su un sistema Ubuntu questo è effettuato con il comando:
sudo apt-get install git-core
Una volta installato git, è possibile creare una sottodirectory per memorizzare IBPy. Sul mio sistema l’ho semplicemente collocato sotto la mia home directory:
mkdir ~/ibapi
Lo step successivo è scaricare IBPy tramite git clone
Assicurarsi di entrare nella directory IbPy ed effettuare l’installazione con l’ambiente virtuale Python preferito:
cd ~/ibapi/IbPy
python setup.py.in install
Questo completa l’installazione di IBPy. Il prossimo passo è aprire TWS
Schermata del TWS Portfolio

Trading Automatico

Il seguente codice implementa una semplice gestione degli ordine basato sulle API. Il codice è lontano dall’essere usato in produzione, ma dimostra la funzionalità essenziale dell’API di Interactive Brokers e come utilizzarla per l’esecuzione degli ordini. Tutto il seguente codice è contenuto nel file ib_api_demo.py. Il primo passaggio consiste nell’importare gli oggetti Contract e Order dalla libreria ib.ext. Inoltre importiamo gli oggetti Connection e message dalla libreria ib.opt.
# ib_api_demo.py

from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.opt import Connection, message
IB ci offre la possibilità di gestire gli errori e le risposte del server tramite un meccanismo di callback. Le seguenti due funzioni non fanno altro che stampare il contenuto dei messaggi restituiti dal server. Un sistema di produzione più sofisticato dovrebbe implementare la logica per assicurare il funzionamento continuo del sistema nel caso di generazione di eccezioni:
# ib_api_demo.py

def error_handler(msg):
    """Handles the capturing of error messages"""
    print "Server Error: %s" % msg

def reply_handler(msg):
    """Handles of server replies"""
    print "Server Response: %s, %s" % (msg.typeName, msg)
Le seguenti due funzioni completano la creazione degli oggetti ContractOrder, impostando i rispettivi parametri:
# ib_api_demo.py

def create_contract(symbol, sec_type, exch, prim_exch, curr):
    """Create a Contract object defining what will
    be purchased, at which exchange and in which currency.

    symbol - The ticker symbol for the contract
    sec_type - The security type for the contract ('STK' is 'stock')
    exch - The exchange to carry out the contract on
    prim_exch - The primary exchange to carry out the contract on
    curr - The currency in which to purchase the contract"""
    contract = Contract()
    contract.m_symbol = symbol
    contract.m_secType = sec_type
    contract.m_exchange = exch
    contract.m_primaryExch = prim_exch
    contract.m_currency = curr
    return contract

def create_order(order_type, quantity, action):
    """Create an Order object (Market/Limit) to go long/short.

    order_type - 'MKT', 'LMT' for Market or Limit orders
    quantity - Integral number of assets to order
    action - 'BUY' or 'SELL'"""
    order = Order()
    order.m_orderType = order_type
    order.m_totalQuantity = quantity
    order.m_action = action
    return order
La funzione __main__ inizialmente crea un oggetto Connection verso Trader Workstation, che deve essere in esecuzione affinché il codice funzioni. Le funzioni di gestione degli errori e di risposta vengono quindi registrate con l’oggetto di connessione. Successivamente viene definita una variabile order_id. In un sistema di produzione questo deve essere incrementato per ogni ordine. I passi successivi sono la creazione di un Contract e di un Order che rappresenta un market-order per acquistare 100 unità di azioni Google. L’ultimo compito è quello di piazzare quell’ordine tramite il metodo placeOrder dell’oggetto Connection. Quindi ci disconnettiamo da TWS:
# ib_api_demo.py

if __name__ == "__main__":
    # Connect to the Trader Workstation (TWS) running on the
    # usual port of 7496, with a clientId of 100
    # (The clientId is chosen by us and we will need 
    # separate IDs for both the execution connection and
    # market data connection)
    tws_conn = Connection.create(port=7496, clientId=100)
    tws_conn.connect()

    # Assign the error handling function defined above
    # to the TWS connection
    tws_conn.register(error_handler, 'Error')

    # Assign all of the server reply messages to the
    # reply_handler function defined above
    tws_conn.registerAll(reply_handler)

    # Create an order ID which is 'global' for this session. This
    # will need incrementing once new orders are submitted.
    order_id = 1

    # Create a contract in GOOG stock via SMART order routing
    goog_contract = create_contract('GOOG', 'STK', 'SMART', 'SMART', 'USD')

    # Go long 100 shares of Google
    goog_order = create_order('MKT', 100, 'BUY')

    # Use the connection to the send the order to IB
    tws_conn.placeOrder(order_id, goog_contract, goog_order)

    # Disconnect from TWS
    tws_conn.disconnect()
Infine è sufficiente lanciare lo script Python:
python ib_api_demo.py

Immediatamente si può vedere che si apre un tab “API” su Trader Workstation, mostrando il market order per andare long di 100 azioni su Google

Schermata del Tab API di TWS dopo l'ordine su Google

Recommended Posts