forex-python-trading-algoritmico-003

DTForex #3 – Open Sourcing del Sistema di Trading sul Forex

Sommario

In questo articolo della serie sul trading Forex descriviamo il piano a lungo termine per il sistema di trading forex. Inoltre, approfondiamo l’uso del tipo di dati Decimal di Python per rendere i calcoli più accurati.

Ad oggi, abbiamo sperimentato l’API Rest di OANDA per verificarne il confronto con l’API fornita da Interactive Brokers. Abbiamo anche visto come aggiungere un elemento base di replica del portafoglio come primo passo verso un adeguato sistema di backtesting basato sugli eventi. Ho anche ricevuto alcune email con suggerimenti relativi agli articoli precedenti ( n.1 e n.2 ), il che suggerisce che molti di voi desiderano modificare ed estendere il codice da soli.

Codice Open Source per il Sistema di Trading sul Forex

Per i motivi sopra esposti ho deciso di rendere open source il sistema di trading sul forex. Cosa significa questo? Significa che tutto il codice attuale e futuro sarà disponibile gratuitamente, con una licenza open source MIT , sul sito Web di Github al seguente repository: datatrading-info/DTForex.

Per chi ha familiarità con git e Github, è sicuramente in grado di eseguire il git clone del repository ed iniziare a modificarlo per i propri scopi.

Il sistema di trading automatico sul Forex di DataTrading è ora open source con una licenza MIT. Puoi trovare il codice più recente su Github nel repository DTForex su datatrading-info/DTForex.

Per chi non conosce il controllo di versione del codice sorgente, è sicuramente utile leggere come funziona git (e il controllo della versione in generale) con questo ebook gratuito Pro Git . Vale la pena dedicare un po’ di tempo per capire il controllo del codice sorgente in quanto farà risparmiare un’enorme quantità di problemi futuri se si trascorre tempo a programmare e ad aggiornare i progetti!

In Ubuntu si può installare git in modo rapido con il seguente comando:

            sudo apt-get install git-core
        

Si crea una directory per il progetto DTForex e “clonare” il repository dal sito Github, come segue:

            mkdir -p ~/progetti/ 
cd ~/progetti/ 
git clone 
https://github.com/datatrading-info/DTForex.git
        

A questo punto si deve creare un ambiente virtuale in cui eseguire il codice:

            mkdir -p ~/venv/dtforex
cd ~/venv/dtforex
virtualenv .
source ~/venv/dtforex/bin/activate
        

Successivamente è necessario installare le librerie python richieste dal progetto (ci vorrà qualche minuto!):

            pip install -r ~/progetti/dtforex/requirements.txt
        

Come accennato negli articoli precedenti, si deve inoltre creare le variabili di ambiente necessarie per le credenziali di autenticazione OANDA. Si prega di consultare l’articolo DTForex #2 per le istruzioni su come farlo.

Si prega di prestare attenzione al README associato al repository, poiché contiene le istruzioni di installazione, un disclaimer e una garanzia sull’utilizzo del codice.

Poiché il software è in modalità “alpha”, queste istruzioni diventeranno più semplici con il passare del tempo. In particolare cercherò di includere il progetto in un pacchetto Python in modo che possa essere facilmente installato tramite pip.

In caso di domande sulla procedura di installazione, non esitare a scrivermi a [email protected] .

Piano a lungo termine

La “filosofia” del sistema di trading per il forex, come per tutti i progetti del sito DataTrading, è costruire un motore di backtesting che possa imitare il più possibile il trading reale. Ciò significa includere dettagli che sono spesso esclusi da scenari di backtesting più “orientate alla ricerca”. Latenza, interruzioni del server, automazione, monitoraggio e costi di transazione realistici saranno tutti inclusi nei modelli di DataTrading per darci una buona idea della profittabilità di una strategia.

Dato che abbiamo ai dati del tick (timestamp bid/ask) possiamo incorporare lo spread nei costi di transazione. Possiamo anche modellare lo slippage. È invece meno immediato modellare l’impatto del mercato, sebbene ciò sia meno preoccupante per trade con piccoli importi (come per i trader retail) o quando si opera su strumenti molti liquidi.

Oltre ai costi di transazione, vogliamo modellare una solida gestione del portafoglio utilizzando la gestione del rischio e dimensionamento della posizione.

Quindi, cosa è attualmente incluso nel nostro Forex Trading System fino ad oggi?

  • Architettura guidata dagli eventi – Il sistema di trading forex è stato progettato da zero come un sistema guidato dagli eventi, poiché è così che un sistema di trading intraday verrà implementato in un ambiente live.
  • Streaming dei prezzi : abbiamo un oggetto base di streaming dei prezzi di mercato. Questo attualmente gestisce lo streaming di una sola coppia, ma possiamo facilmente modificarlo per gestire più coppie di valute.
  • Generazione del segnale – Possiamo incorporare strategie di trading (basate direttamente sui prezzi tick passati e attuali) utilizzando l’oggetto Strategy, che crea oggetto SignalEvent.
  • Esecuzione degli ordini : disponiamo di un ingenuo sistema di esecuzione degli ordini che invia gli ordini alla cieca da Portfolio averso OANDA. Con “alla cieca” si intende che non viene effettuata alcuna gestione del rischio o dimensionamento della posizione, né alcuna esecuzione algoritmica che potrebbe portare a costi di transazione ridotti.
  • Valuta di base EUR – Per semplificare le cose, abbiamo implementato il sistema solo per la valuta di base EUR. Questo è forse l’aspetto più importante da modificare visto che il mercato forex offre strumenti  denominati in USD, GBP, CAD, JPY, AUD e NZD!
  • Trading EUR / USD – Abbiamo scelto EUR/USD come coppia di valute iniziale con cui testare gli oggetti Position Portfolio. La gestione di più coppie di valute è un importante passaggio successivo. Ciò comporterà modifiche alla posizione e ai calcoli del portafoglio.
  • Gestione dei decimali : qualsiasi sistema di trading live deve gestire correttamente i calcoli di valuta. In particolare, i valori di valuta non dovrebbero essere memorizzati come tipi di dati in virgola mobile, poiché gli errori di arrotondamento si accumulano. Per maggiori dettagli si può consultare questo fantastico articolo sulle rappresentazioni in virgola mobile.
  • Trading Long / Short – Tra l’articolo #2 della serie e l’articolo #3 abbiamo aggiunto la possibilità di shortare una coppia di valute (invece di poter solo andare long). Fondamentalmente, anche questo è oggetto di unit test.
  • Gestione del portafoglio locale – A mio parere, eseguire un backtest che gonfia le prestazioni della strategia a causa di ipotesi non realistiche è inutile nella migliore delle ipotesi ed estremamente poco redditizio nel peggiore dei casi! L’introduzione di un oggetto di portafoglio locale che replica i calcoli di OANDA significa che possiamo controllare i nostri calcoli interni mentre eseguiamo il paper trading, il che ci dà maggiore fiducia quando in seguito utilizzeremo lo stesso oggetto di portafoglio per il backtest sui dati storici.
  • Unit test per Position/Portfolio – Anche se è stato direttamente menzionato direttamente negli articoli #1 e #2, ho effettivamente scritto alcuni unit test per gli  oggetti Portfolio  e Position. Poiché questi sono così cruciali per i calcoli della strategia, bisogna essere estremamente sicuri che funzionino come previsto. Un ulteriore vantaggio di tali test è la possibilità di modificare il calcolo sottostante, in modo tale che se tutti i test continuano ad essere superati, possiamo essere certi che il sistema continuerà a comportarsi come previsto.

In questa fase il Forex Trading System manca delle seguenti funzionalità:

  • Gestione dello slippage – Il sistema sta attualmente generando molti slippage a causa della natura ad alta frequenza dei dati tick forniti da OANDA. Ciò significa che il saldo del portafoglio calcolato localmente non riflette il saldo calcolato da OANDA. Fino a quando non viene eseguita la corretta gestione degli eventi e la regolazione dello slippage, il backtest non rifletterà correttamente la realtà.
  • Valute di base multiple – Attualmente siamo limitati a EUR. Per lo meno dobbiamo includere le principali denominazioni di valuta: USD, GBP, CAD, AUD, JPY e NZD.
  • Coppie di valute multiple – Allo stesso modo dobbiamo supportare le principali coppie di valute oltre EUR / USD). Ci sono due aspetti da considerare. Il primo è gestire correttamente i calcoli quando né la base né la quotazione di una coppia di valute è uguale alla valuta di denominazione del conto. Il secondo aspetto è supportare più posizioni in modo da poter negoziare un portafoglio di coppie di valute.
  • Gestione del rischio – Molti backtest di “ricerca” ignorano completamente la gestione del rischio. Purtroppo questo è generalmente necessario per brevità nel descrivere le regole di una strategia. In realtà dobbiamo prevedere una gestione del rischio durante il trading, altrimenti è estremamente probabile che prima o poi subiremo una pesante perdita. Questo non vuol dire che la gestione del rischio possa prevenirla del tutto, ma certamente la rende meno probabile!
  • Ottimizzazione del portafoglio – In un contesto istituzionale avremo un mandato di investimento, che determinerà un solido sistema di gestione del portafoglio con varie regole di allocazione. In un contesto di trading retail / personale potremmo voler utilizzare un approccio di dimensionamento della posizione come il criterio di Kelly per massimizzare il nostro tasso di crescita composto nel lungo termine.
  • Strategie robuste – Finora abbiamo dimostrato solo alcune semplici strategie “giocattolo” che generano segnali casuali. Ora che stiamo iniziando a creare un sistema di trading forex intraday affidabile, dovremmo iniziare a mettere in atto alcune strategie più interessanti. I prossimi articoli di questa serie si concentreranno su strategie tratte da una combinazione di indicatori / filtri “tecnici”, modelli di serie temporali e tecniche di apprendimento automatico.
  • Distribuzione remota : Dato che siamo potenzialmente interessati al trading 24 ore su 24 (almeno durante la settimana!), Abbiamo bisogno di una configurazione più sofisticata rispetto all’esecuzione del backtest su un computer desktop / laptop locale a casa. È fondamentale creare una solida distribuzione del nostro sistema in un server remoto, con specifici tool di ridondanza e monitoraggio.
  • Backtest storico : Abbiamo costruito l’oggetto Portfolio per poter eseguire un backtest realistico. In questa fase ci manca un sistema di archiviazione dei dati storici dei tick. Negli articoli successivi esamineremo come ottenere i dati storici dei tick e archiviarli in un database appropriato, come HDF5 .
  • Database dei Trade – Inoltre è opportuno memorizzare i nostri trade in tempo reale in un database. Ciò ci consentirà di eseguire le nostre analisi sui dati di live trading. Una buona raccomandazione per un database relazionale è PostgreSQL o MySQL .
  • Monitoraggio e alta disponibilità : Dato che stiamo costruendo un sistema intraday ad alta frequenza, dobbiamo mettere in atto un monitoraggio completo e una ridondanza ad alta disponibilità. Ciò significa generare rapporti sull’utilizzo della CPU, utilizzo del disco, I/O di rete, latenza e verificare che gli script periodici siano impostati per continuare a funzionare. Inoltre abbiamo bisogno di una strategia di backup e ripristino. Chiediti quali piani di backup avresti in atto se avessi grandi posizioni aperte, in un mercato volatile e il tuo server morisse improvvisamente. Credimi, succede!
  • Integrazione Multiple Broker / FIX – Al momento siamo fortemente legati al broker OANDA. Come ho detto in precedenza, perché semplicemente mi sono imbattuto nella loro API e ho trovato che fosse un’ottima infrastruttura per i test. Ci sono molti altri broker là fuori, molti dei quali supportano il protocollo FIX. L’aggiunta di una funzionalità FIX aumenterebbe il numero di broker che potrebbero essere utilizzati nel sistema.
  • Controllo e reportistica GUI – In questo momento il sistema è completamente basato su console / riga di comando. Per lo meno avremo bisogno di alcuni grafici di base per visualizzare i risultati del backtest. Un sistema più sofisticato incorporerà statistiche riassuntive delle operazioni, metriche delle prestazioni a livello di strategia e prestazioni complessive del portafoglio. Questa GUI potrebbe essere implementata utilizzando un sistema di finestre multipiattaforma come Qt o Tkinter . Potrebbe anche essere implementato un front-end basato sul web, utilizzando un framework web come Django .

Come si può vedere, sono rimaste molte funzionalità sulla roadmap! Detto questo, ogni nuovo articolo della serie farà avanzare il progetto.

Tipi di dati decimali

Dopo aver discusso il piano a lungo termine, descriviamo alcune delle modifiche apportate al codice presentato nell’articolo #2 di questa serie. In particolare, descriviamo le modifiche al codice necessarie per gestire il tipo di dati Decimal invece di utilizzare le variabili a virgola mobile. Si tratta di un cambiamento estremamente importante poiché le rappresentazioni in virgola mobile sono una primaria fonte di errori a lungo termine nei sistemi di gestione del portafoglio e degli ordini.

Python supporta nativamente le rappresentazioni decimali con una precisione arbitraria. La funzionalità è contenuta nella libreria decimal.

In particolare abbiamo bisogno di modificare -ogni- valore che appare nei calcoli implementati in Position in un tipo di dato Decimal. Ciò include le unità, l’esposizione, i pip, il profitto e il profitto percentuale. Ciò garantisce che abbiamo il pieno controllo di come vengono gestiti i problemi di arrotondamento quando si tratta di rappresentazioni di valute con una precisione a due cifre decimali. In particolare dobbiamo scegliere il metodo di arrotondamento. Python supporta alcuni tipi diversi, in questo caso usiamo ROUND_HALF_DOWN, che arrotonda all’intero più vicino con legami che vanno verso lo zero.

Ecco un esempio delle modifiche al codice per gestire i tipi di dati Decimal rispetto alle loro precedenti rappresentazioni in virgola mobile. Di seguito è riportato il codice di position.py:

            from decimal import Decimal, getcontext, ROUND_HALF_DOWN

class Position(object):
    def __init__(
        self, side, market, units, 
        exposure, avg_price, cur_price
    ):
        self.side = side
        self.market = market
        self.units = units
        self.exposure = Decimal(str(exposure))
        self.avg_price = Decimal(str(avg_price))
        self.cur_price = Decimal(str(cur_price))
        self.profit_base = self.calculate_profit_base(self.exposure)
        self.profit_perc = self.calculate_profit_perc(self.exposure)

    def calculate_pips(self):
        getcontext.prec = 6
        mult = Decimal("1")
        if self.side == "SHORT":
            mult = Decimal("-1")
        return (mult * (self.cur_price - self.avg_price)).quantize(
            Decimal("0.00001"), ROUND_HALF_DOWN
        )

    def calculate_profit_base(self, exposure):
        pips = self.calculate_pips()        
        return (pips * exposure / self.cur_price).quantize(
            Decimal("0.00001"), ROUND_HALF_DOWN
        )

    def calculate_profit_perc(self, exposure):
        return (self.profit_base / exposure * Decimal("100.00")).quantize(
            Decimal("0.00001"), ROUND_HALF_DOWN
        )

    def update_position_price(self, cur_price, exposure):
        self.cur_price = cur_price
        self.profit_base = self.calculate_profit_base(exposure)
        self.profit_perc = self.calculate_profit_perc(exposure)
        

Da notare come dobbiamo l’argomento di Decimal è una stringa, piuttosto che un argomento in virgola mobile. Questo perché una stringa specifica con esattezza la precisione del valore, mentre non è possibile con un argomento a virgola mobile.

Inoltre bisogna tenere presente che la memorizzazione delle operazioni in un database relazionale (come descritto nella roadmap al paragrafo precedente) prevede di utilizzare il corretto tipo di dati. PostgreSQL e MySQL supportano una rappresentazione decimale. È fondamentale utilizzare questi tipi di dati quando si crea lo schema del database, altrimenti si avranno errori di arrotondamento estremamente difficili da diagnosticare!

Per coloro che sono interessati a una discussione più approfondita di questi problemi, in matematica e informatica, il tema dell’analisi numerica copre i problemi di archiviazione in virgola mobile, tra molti altri argomenti interessanti.

Nei prossimi articoli del diario descriveremo come applicare gli unit test al codice e come estendere il sistema per gestire più coppie di valute, modificando i calcoli di posizione.

Per il codice completo riportato in questo articolo, utilizzando il modulo di backtesting event-driven per il forex (DTForex) si può consultare il seguente repository di github:
https://github.com/datatrading-info/DTForex

Benvenuto su DataTrading!

Sono Gianluca, ingegnere software e data scientist. Sono appassionato di coding, finanza e trading. Leggi la mia storia.

Ho creato DataTrading per aiutare le altre persone ad utilizzare nuovi approcci e nuovi strumenti, ed applicarli correttamente al mondo del trading.

DataTrading vuole essere un punto di ritrovo per scambiare esperienze, opinioni ed idee.

SCRIVIMI SU TELEGRAM

Per informazioni, suggerimenti, collaborazioni...

Torna in alto
Scroll to Top