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):
    """Gestione per la cattura dei messagi di errori"""
    print("Server Error: %s" % msg)

def reply_handler(msg):
    """Gestione delle risposte dal server"""
    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):
    """
    Crea un oggetto Contract definendo cosa sarà
    acquistato, in quale exchange e in quale valuta.

    symbol - Il simbolo del ticker per il contratto
    sec_type - Il tipo di asset per il contratto ("STK" è "stock")
    exch - La borsa su cui eseguire il contratto
    prim_exch - Lo scambio principale su cui eseguire il contratto
    curr - La valuta in cui acquistare il contratto
    """
    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):
    """
    Crea un oggetto Ordine (Market/Limit) per andare long/short.

    order_type - "MKT", "LMT" per ordini a mercato o limite
    quantity - Numero intero di asset dell'ordine
    action - 'BUY' o '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__":
    # Collegarsi alla Trader Workstation (TWS) in esecuzione
    # sulla solita porta 7496, con un clientId di 100
    # (Il clientId è scelto da noi e avremo bisogno di
    # ID separati sia per la connessione di esecuzione che per
    # connessione dati di mercato)
    tws_conn = Connection.create(port=7496, clientId=100)
    tws_conn.connect()

    # Assegna la funzione di gestione degli errori definita
    # sopra alla connessione TWS
    tws_conn.register(error_handler, 'Error')

    # Assegna tutti i messaggi di risposta del server alla
    # funzione reply_handler definita sopra
    tws_conn.registerAll(reply_handler)

    # Crea un ordine ID che sia "globale" per questa sessione. Questo
    # dovrà essere incrementato una volta inviati nuovi ordini.
    order_id = 1

    # Crea un contratto in stock GOOG tramite il routing degli ordini SMART
    goog_contract = create_contract('GOOG', 'STK', 'SMART', 'SMART', 'USD')

    # si va long di 100 azioni di Google
    goog_order = create_order('MKT', 100, 'BUY')

    # Uso della connessione per inviare l'ordine a IB
    tws_conn.placeOrder(order_id, goog_contract, goog_order)

    # Disconnessione da 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

 

Per il codice completo riportato in questo articolo utilizzando il modulo di backtesting vettoriale VectorBacktest si può consultare il seguente repository di github:
https://github.com/datatrading-info/VectorBacktest

Recommended Posts