In questo corso impariamo a effettuare trading automatico sul forex utilizzando il software TQsystem, sviluppato durante il corso Trading System Event Driven con Python. In questa prima lezione, spieghiamo come effettuare trading sul forex con OANDA tramite i servizi Rest API.
Vediamo insieme come creare un nuovo account DEMO con il broker OANDA e come costruire un motore di trading event-driven multithreading, capace di eseguire automaticamente operazioni sia in modalità demo sia live. Inoltre, introduciamo un motore di backtest orientato al forex, utile sia per il paper-trading che per il live-trading.
Le istruzioni operative si riferiscono all’ambiente Ubuntu 18.04, ma possiamo adattarle facilmente anche a Windows o Mac OS X utilizzando una distribuzione Python come Anaconda. Per il nostro motore di trading in Python usiamo solo una libreria aggiuntiva, requests, fondamentale per comunicare tramite HTTP con l’API di OANDA.
Creazione di un account con OANDA
La prima domanda che ci poniamo è: “Perché scegliere OANDA?”. Dopo una ricerca su Google sui broker forex che offrono API, abbiamo scoperto che OANDA mette a disposizione una REST API moderna, facilmente accessibile con quasi tutti i linguaggi di programmazione. Consultando la loro documentazione API per sviluppatori, abbiamo deciso di provarla almeno con un account demo.
Precisiamo che non abbiamo alcun rapporto precedente o attuale con OANDA; consigliamo questa soluzione soltanto in base alla nostra esperienza diretta, testando nella pratica la loro API e scaricando alcuni dati di mercato. Se conosci altri broker forex che offrono API moderne, saremo felici di esplorarli.
Per iniziare a fare trading sul forex con OANDA dobbiamo registrare un account di pratica. Per registrarci, seguiamo il link di registrazione. Apparirà una schermata simile alla seguente:

Possiamo quindi loggarsi con le proprie credenziali di accesso. Assicuriamoci di selezionare la scheda “fxTradePractice” dalla schermata di accesso:

Generare il token API
Una volta entrati, dobbiamo prendere nota del proprio ID account. È elencato sotto l’intestazione nera “My Funds” accanto a “Primary” e dovrebbe essere un numero di 7 cifre. Inoltre dobbiamo generare anche un token API personale. A tale scopo, dobbiamo fare clic su “Manage API Access” nella scheda “Other Actions”:

A questo punto generiamo un token API, indispensabile per utilizzare l’applicazione in seguito. Annulliamo il rischio di perderlo annotandolo con attenzione.
Ora lanciamo l’applicazione FXTrade Practice, che ci consente di consultare gli ordini eseguiti e monitorare profitti e perdite (in modalità paper trading!).
Se lavoriamo su un sistema Ubuntu, dobbiamo installare una versione specifica di Java: la versione Oracle di Java 8. Solo così riusciamo a caricare correttamente il simulatore di pratica all’interno del browser.
Su Ubuntu eseguiamo questi comandi:
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
Ora possiamo avviare l’ambiente di trading demo. Torniamo alla dashboard di OANDA e clicchiamo sul link evidenziato in verde “Launch FXTrade Practice”. Una finestra di dialogo Java ci chiederà se vogliamo eseguire l’applicazione.
Clicchiamo su “Run” per caricare fxTrade Practice. Ad esempio, possiamo visualizzare un grafico a candele di 15 minuti di EUR/USD con il pannello delle quotazioni posizionato a sinistra:

A questo punto siamo pronti per progettare e codificare il nostro sistema di trading sul forex con Oanda.
Panoramica dell’Architettura di Trading
Nel corso dedicato alla progettazione di un sistema di trading basato sugli eventi per azioni ed ETF, abbiamo descritto il funzionamento del motore di backtest. In sostanza, eseguiamo l’intero software all’interno di un ciclo continuo che si interrompe solo quando decidiamo di spegnere il sistema di trading. Usiamo una coda di eventi come meccanismo di comunicazione centrale.
Interroghiamo costantemente la coda per verificare la presenza di nuovi eventi. Quando rimuoviamo un evento dalla cima della coda, il componente appropriato del sistema si occupa immediatamente di gestirlo. Ad esempio, un feed di dati di mercato può generare TickEvents
che inseriamo in coda ogni volta che riceviamo un nuovo prezzo di mercato. Allo stesso modo, un oggetto Strategy che genera segnali può creare OrderEvents
da inviare al broker o all’intermediario.
Questo approccio ci offre una grande flessibilità, perché il sistema rimane indipendente dal tipo di ordine o evento: gestiamo sempre ogni evento con il componente corretto del programma.
Inoltre, possiamo eseguire diverse parti del programma in thread separati, senza dover attendere che un componente completi la sua attività prima di avviare l’elaborazione di un altro. Questa caratteristica si rivela estremamente utile nel trading algoritmico, dove i feed dei dati di mercato e i generatori di segnali strategici presentano requisiti di performance molto differenti.
Il ciclo principale del nostro sistema di trading può essere rappresentato con il seguente pseudo-codice Python:
while True:
try:
event = events_queue.get(False)
except Queue.Empty:
pass
else:
if event is not None:
if event.type == 'TICK':
strategy.calculate_signals(event)
elif event.type == 'ORDER':
execution.execute_order(event)
time.sleep(heartbeat)
Come abbiamo detto in precedenza, il codice si esegue in un ciclo infinito. Iniziamo effettuando il polling della coda per recuperare un nuovo evento. Se la coda è vuota, il ciclo riparte dopo un breve intervallo di sospensione, noto come “battito cardiaco”. Quando troviamo un evento, analizziamo il suo tipo e chiamiamo il relativo modulo (strategy
o execution
) per gestirlo e, se necessario, generare nuovi eventi da inserire nuovamente in coda.
Sistema di Trading Sul Forex con OANDA
I componenti principali del nostro motore di trading sul forex con OANDA comprendono:
- Streaming Price Handler – Manteniamo una connessione di lunga durata ai server di OANDA per ricevere dati tick (ad esempio, bid/ask) relativi agli strumenti che ci interessano.
- Strategy Signal Generator – Usiamo una sequenza di eventi tick per generare ordini di trading che il gestore dell’esecuzione dovrà eseguire.
- Execution Handler – Gestiamo l’esecuzione degli ordini inviandoli direttamente a OANDA senza ulteriori controlli.
- Events – Questi oggetti rappresentano i “messaggi” che passiamo nella coda degli eventi. Per questa implementazione ci servono solo due tipi: TickEvent e OrderEvent.
- Main Entry Point – Questo punto di ingresso include il ciclo “trading”, che effettua continuamente il polling della coda dei messaggi e indirizza i messaggi al componente corretto. Viene spesso chiamato “ciclo di eventi” o “gestore di eventi”.
Ora analizziamo in dettaglio l’implementazione del codice. Alla fine della lezione troverai l’elenco completo dei file sorgente. Inserendoli nella stessa directory ed eseguendo python trading.py
, inizieremo a generare ordini, a condizione di aver inserito l’account ID e il token di autenticazione di OANDA.
Implementazione Python
Preferiamo non memorizzare password o chiavi di autenticazione direttamente nel codice, per evitare rischi legati all’accesso non autorizzato ai progetti. In un sistema di produzione salviamo queste credenziali come variabili di ambiente del sistema, interrogandole ogni volta che distribuiamo il codice. Così facendo, evitiamo che password e token finiscano nei sistemi di controllo versione.
Tuttavia, poiché il nostro obiettivo è costruire un sistema di trading “paper” e in questa lezione non trattiamo i dettagli di deploy, memorizziamo i token di autenticazione in un file di impostazioni.
Nel file di configurazione settings.py
definiamo un dizionario chiamato ENVIRONMENTS
che contiene gli endpoint API per lo streaming dei prezzi di OANDA e per il trading. Ogni dizionario secondario include tre endpoint distinti: real
, practice
e sandbox
.
Utilizziamo l’API sandbox
per testare il codice e individuare eventuali errori o bug, anche se non offre le stesse garanzie di uptime delle API real
o practice
. L’API practice
ci consente di effettuare paper trading, simulando l’esperienza del trading reale su un account DEMO. L’API real
è destinata al trading con denaro reale: se utilizziamo questo endpoint, effettueremo operazioni reali su un conto live. Dobbiamo prestare la massima attenzione!
IMPORTANTE: quando operiamo con l’API practice, dobbiamo ricordare che i costi di transazione, come l’impatto sul mercato, non vengono simulati. Nessuna operazione viene effettivamente eseguita nell’ambiente practice, quindi dobbiamo contabilizzare questi costi in un altro modo, magari tramite un modello di impatto sul mercato, per ottenere una valutazione più realistica delle performance.
In questa lezione utilizziamo l’account practice
configurato tramite il parametro DOMAIN
. Abbiamo bisogno di due dizionari separati: uno per i domini dello streaming dei prezzi e uno per i domini del trading. Infine, definiamo le variabili ACCESS_TOKEN
e ACCOUNT_ID
. Per motivi di sicurezza, assegniamo valori fittizi a questi ID: ognuno di noi dovrà utilizzare i propri, ottenibili dalla pagina dell’account OANDA.
ENVIRONMENTS = {
"streaming": {
"real": "stream-fxtrade.oanda.com",
"practice": "stream-fxpractice.oanda.com",
"sandbox": "stream-sandbox.oanda.com"
},
"api": {
"real": "api-fxtrade.oanda.com",
"practice": "api-fxpractice.oanda.com",
"sandbox": "api-sandbox.oanda.com"
}
}
DOMAIN = "practice"
STREAM_DOMAIN = ENVIRONMENTS["streaming"][DOMAIN]
API_DOMAIN = ENVIRONMENTS["api"][DOMAIN]
ACCESS_TOKEN = 'abcdef0123456abcdef0123456-abcdef0123456abcdef0123456'
ACCOUNT_ID = '12345678'
Gestione degli eventi
Procediamo definendo gli events che la coda utilizzerà per gestire la comunicazione tra i vari componenti del sistema. Abbiamo bisogno di due eventi fondamentali: TickEvent
e OrderEvent
. Il primo memorizza le informazioni sui dati di mercato di uno strumento, come il miglior prezzo bid/ask e il tempo di negoziazione. Il secondo trasmette gli ordini all’executive handler e contiene i dettagli relativi allo strumento, al numero di unità da negoziare, al tipo di ordine (“mercato” o “limite”) e al “lato” (cioè “long” o “short”).
Per rendere il codice flessibile, creiamo una classe base chiamata Event
da cui tutti gli eventi derivano. Di seguito presentiamo il codice della classe events.py
:
class Event(object):
pass
class TickEvent(Event):
def __init__(self, instrument, time, bid, ask):
self.type = 'TICK'
self.instrument = instrument
self.time = time
self.bid = bid
self.ask = ask
class OrderEvent(Event):
def __init__(self, instrument, units, order_type, side):
self.type = 'ORDER'
self.instrument = instrument
self.units = units
self.order_type = order_type
self.side = side
Gestione della strategia
La prossima classe è quella per gestire la strategia di trading sul forex su Oanda. Per la demo creiamo una strategia molto semplice che riceve tutti i tick di mercato e, ogni 5 tick, acquista o vende casualmente 10.000 unità di EUR/USD. Chiaramente, si tratta di una “strategia” ridicola! Tuttavia, risulta perfetta per scopi didattici perché è facile da codificare e da comprendere. Nei prossimi articoli vedremo come sostituire questa logica con qualcosa di più sofisticato che, si spera, genererà profitti reali!
Il file strategy.py
contiene il codice della strategia. Analizziamolo insieme per capire come funziona. Per prima cosa importiamo la libreria random
e l’oggetto OrderEvent
da events.py
. La libreria random
ci permette di scegliere casualmente se acquistare o vendere, mentre OrderEvent
rappresenta l’evento con cui la strategia invia gli ordini alla coda degli eventi, che il gestore di esecuzione eseguirà successivamente.
La classe TestRandomStrategy
prende come parametri lo strumento finanziario (in questo caso EUR/USD), il numero di unità da negoziare e la coda degli eventi. All’interno della classe creiamo un contatore ticks
che registra quante istanze di TickEvent
abbiamo ricevuto.
Il cuore della strategia risiede nel metodo calculate_signals
. Questo metodo riceve un evento, controlla se si tratta di un TickEvent
(ignorando altrimenti l’evento), e incrementa il contatore ticks
. Se il conteggio dei tick è divisibile per 5, la strategia decide casualmente se acquistare o vendere, generando un ordine di mercato per il numero di unità specificato. Pur non essendo certo una strategia da utilizzare nei mercati reali, risulta più che sufficiente per testare le API di intermediazione di OANDA!
import random
from event import OrderEvent
class TestRandomStrategy(object):
def __init__(self, instrument, units, events):
self.instrument = instrument
self.units = units
self.events = events
self.ticks = 0
def calculate_signals(self, event):
if event.type == 'TICK':
self.ticks += 1
if self.ticks % 5 == 0:
side = random.choice(["buy", "sell"])
order = OrderEvent(
self.instrument, self.units, "market", side
)
self.events.put(order)
Esecuzione degli Ordini
Il componente successivo del sistema di trading sul forex con Oanda che dobbiamo sviluppare è l’execution handler. Questa classe si occupa di ricevere le istanze di OrderEvent
ed eseguire direttamente le richieste al broker, in questo caso OANDA. Operiamo in modo “stupido”, cioè senza integrare alcuna gestione del rischio o costruzione sofisticata del portafoglio. Il gestore dell’esecuzione esegue ogni ordine che riceve, senza ulteriori controlli.
Passiamo alla classe Execution
tutte le informazioni di autenticazione necessarie, come il “dominio” (practice, real o sandbox), il token di accesso e l’ID account. Poi, creiamo una connessione sicura utilizzando http.client
, una delle librerie standard di Python.
La maggior parte del lavoro si concentra nel metodo execute_order
. Questo metodo richiede un evento come parametro e costruisce due dizionari: headers
e params
. Successivamente, codifichiamo questi dizionari tramite urllib
per prepararli come richiesta HTTP POST verso l’API di OANDA.
Includiamo nei parametri di intestazione il Content-Type
e il Authorization
, che contengono le nostre credenziali di autenticazione. Codifichiamo anche i parametri dell’ordine, specificando lo strumento (ad esempio EUR/USD), il numero di unità, il tipo di ordine e il lato (acquisto o vendita). Infine, inviamo la richiesta al broker e salviamo la risposta ricevuta.
import http.client
import urllib
class Execution(object):
def __init__(self, domain, access_token, account_id):
self.domain = domain
self.access_token = access_token
self.account_id = account_id
self.conn = self.obtain_connection()
def obtain_connection(self):
return http.client.HTTPSConnection(self.domain)
def execute_order(self, event):
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + self.access_token
}
params = urllib.urlencode({
"instrument" : event.instrument,
"units" : event.units,
"type" : event.order_type,
"side" : event.side
})
self.conn.request(
"POST",
"/v1/accounts/%s/orders" % str(self.account_id),
params, headers
)
response = self.conn.getresponse().read()
print(response)
Flusso dei dati in tempo reale
Il componente più complesso del sistema di trading sul Forex con Oanda è l’oggetto StreamingForexPrices
, che gestisce gli aggiornamenti dei prezzi di mercato da OANDA. Esistono due metodi: connect_to_stream
e stream_to_queue
.
Il primo metodo utilizza la libreria requests di Python per connettersi a un socket di streaming con le intestazioni e i parametri appropriati. I parametri includono l’ID account e l’elenco degli strumenti che devono essere monitorati per ricevere gli aggiornamenti (in questo caso è solo EUR/USD).
Da notare la seguente riga:
resp = s.send(pre, stream=True, verify=False)
Questo indica che la connessione deve essere trasmessa in streaming e quindi mantenuta costantemente aperta per un periodo molto prolungato.
Il secondo metodo, stream_to_queue
, tenta effettivamente di connettersi allo stream. Se la risposta non ha esito positivo (ovvero il codice di risposta non è HTTP 200), si esce e cede il controllo alla chiamante. Se ha successo si prova a caricare il pacchetto JSON ricevuto in un dizionario Python. Infine, converte il dizionario Python con lo strumento, bid / ask e timestamp in un TickEvent
che viene inviato alla coda degli eventi:
import requests
import json
from event import TickEvent
class StreamingForexPrices(object):
def __init__(
self, domain, access_token,
account_id, instruments, events_queue
):
self.domain = domain
self.access_token = access_token
self.account_id = account_id
self.instruments = instruments
self.events_queue = events_queue
def connect_to_stream(self):
try:
s = requests.Session()
url = "https://" + self.domain + "/v1/prices"
headers = {'Authorization' : 'Bearer ' + self.access_token}
params = {'instruments' : self.instruments, 'accountId' : self.account_id}
req = requests.Request('GET', url, headers=headers, params=params)
pre = req.prepare()
resp = s.send(pre, stream=True, verify=False)
return resp
except Exception as e:
s.close()
print("Caught exception when connecting to stream\n" + str(e))
def stream_to_queue(self):
response = self.connect_to_stream()
if response.status_code != 200:
return
for line in response.iter_lines(1):
if line:
try:
msg = json.loads(line)
except Exception as e:
print("Caught exception when converting message into json\n" + str(e))
return
if msg.has_key("instrument") or msg.has_key("tick"):
print(msg)
instrument = msg["tick"]["instrument"]
time = msg["tick"]["time"]
bid = msg["tick"]["bid"]
ask = msg["tick"]["ask"]
tev = TickEvent(instrument, time, bid, ask)
self.events_queue.put(tev)
Il Backtest di una Strategia
Abbiamo ora a disposizione tutti i componenti principali del sistema di trading sul forex con Oanda. Il passaggio finale consiste nel racchiudere tutto ciò che abbiamo sviluppato finora all’interno di un programma principale. Questo file, che chiamiamo trading.py
, ha l’obiettivo di creare due thread separati: uno dedicato al gestore dei prezzi e l’altro al gestore del trading.
Perché servono due thread separati? In parole semplici, stiamo eseguendo due blocchi di codice indipendenti, entrambi in esecuzione continua. Se realizzassimo un programma senza thread, il socket di streaming utilizzato per gli aggiornamenti dei prezzi rimarrebbe bloccato, impedendo il ritorno al codice principale e quindi l’esecuzione delle operazioni di trading. Allo stesso modo, se eseguissimo il ciclo trade
(descritto qui sotto), non restituiremmo mai il controllo del flusso di esecuzione al socket di streaming dei prezzi. Per questo motivo, creiamo più thread: uno per ciascun componente, permettendo loro di funzionare in modo indipendente. Entrambi i thread comunicheranno attraverso la coda degli eventi.
Vediamo ora più nel dettaglio come procedere. Creiamo due thread separati utilizzando le seguenti istruzioni:
trade_thread = threading.Thread(target=trade, args=(events, strategy, execution))
price_thread = threading.Thread(target=prices.stream_to_queue, args=[])
Passiamo la funzione o il nome del metodo all’argomento della parola chiave target
e quindi passiamo un iterabile (un elenco o una tupla) come argomento della parola chiave args
, che corrispondo ai parametri d’ingresso del metodo / funzione specificato in “target”.
Infine iniziamo entrambi i thread con le seguenti righe:
trade_thread.start()
price_thread.start()
In questo modo possiamo eseguire in modo indipendente e separato due segmenti di codice a ciclo infinito, facendo comunicare entrambi attraverso la coda degli eventi. Dobbiamo però considerare che la libreria threading
di Python non consente un vero ambiente multi-core multithread, a causa dell’implementazione di CPython e del Global Interpreter Lock (GIL).
Esecuzione dello script
Analizziamo ora nel dettaglio il resto del codice che implementa un sistema di trading sul forex con Oanda. Per prima cosa importiamo tutte le librerie necessarie, tra cui queue
, threading
e time
. Poi importiamo tutti i file di codice che abbiamo descritto in precedenza. Personalmente preferiamo capitalizzare tutte le impostazioni di configurazione, un’abitudine che abbiamo acquisito lavorando con Django!
Successivamente definiamo la funzione trade
, che abbiamo già illustrato con lo pseudo-codice Python. All’interno della funzione, eseguiamo un ciclo infinito (while True:
) che effettua continuamente il polling dalla coda degli eventi, saltando il ciclo solo se la coda risulta vuota (cioè senza eventi). Quando rileviamo un evento, che può essere un TickEvent
o un OrderEvent
, chiamiamo il componente appropriato per gestirlo, come una strategia o un gestore di esecuzione. Dopo ogni ciclo, introduciamo una pausa (heartbeat) di 0,5 secondi prima di ricominciare.
Infine definiamo il punto di ingresso principale del codice all’interno della funzione __main__
. In particolare, istanziamo la coda degli eventi e definiamo gli strumenti o le unità operative. Procediamo quindi con la creazione della classe di streaming dei prezzi, StreamingForexPrices
, e successivamente del gestore di esecuzione, Execution
. Entrambi ricevono i parametri di autenticazione forniti da OANDA al momento della creazione dell’account.
Creiamo poi l’istanza della strategia TestRandomStrategy
. Infine definiamo i due thread principali e li avviamo per far partire il nostro sistema di trading.
import queue
import threading
import time
from execution import Execution
from settings import STREAM_DOMAIN, API_DOMAIN, ACCESS_TOKEN, ACCOUNT_ID
from strategy import TestRandomStrategy
from data import StreamingForexPrices
def trade(events, strategy, execution):
"""
Esegue un ciclo while infinito che effettua il polling
della coda degli eventi e indirizza ogni evento al
componente strategia del gestore di esecuzione.
Il ciclo si fermerà per "heartbeat" di alcuni secondi
e continuerà.
"""
while True:
try:
event = events.get(False)
except queue.Empty:
pass
else:
if event is not None:
if event.type == 'TICK':
strategy.calculate_signals(event)
elif event.type == 'ORDER':
print("Executing order!")
execution.execute_order(event)
time.sleep(heartbeat)
if __name__ == "__main__":
heartbeat = 0.5 # Pausa di mezzo secondo
events = queue.Queue()
# Trading di 10000 unità di EUR/USD
instrument = "EUR_USD"
units = 10000
# Creazione di una classe di streaming di prezzi da
# OANDA, assicurandosi di fornire le credenziali
# di autenticazione
prices = StreamingForexPrices(
STREAM_DOMAIN, ACCESS_TOKEN, ACCOUNT_ID,
instrument, events
)
# Creazione di un gestore di esecuzione con parametri
# di autenticazioni di OANDA
execution = Execution(API_DOMAIN, ACCESS_TOKEN, ACCOUNT_ID)
# Creazione del generatore di strategia/segnali, utilizzando
# lo strumento, la quantità di unità e la coda di eventi come
# parametri
strategy = TestRandomStrategy(instrument, units, events)
# Creazione di due thread separati: uno per il ciclo di trading
# e uno per lo streaming dei prezzi di mercato
trade_thread = threading.Thread(target=trade, args=(events, strategy, execution))
price_thread = threading.Thread(target=prices.stream_to_queue, args=[])
# Avvio di entrambi i thread
trade_thread.start()
price_thread.start()
python trading.py
Visualizzazione dei risultati
Per fermare il codice in questa fase, dobbiamo eseguire un hard kill del processo Python, utilizzando “Ctrl-Z” o un comando equivalente. Non abbiamo implementato un thread aggiuntivo per gestire correttamente l’uscita tramite sys.exit()
, che risulterebbe necessario per interrompere il codice in modo sicuro. Un metodo pratico per fermare il codice su una macchina Ubuntu o Linux consiste nel digitare:
pgrep python
kill -9 PROCESS_ID
Dove PROCESS_ID deve essere sostituito con l’output di pgrep. Da notare che questa NON è una pratica particolarmente corretta!
Nelle lezioni successive creeremo un meccanismo di avvio / arresto più sofisticato che utilizza la supervisione del processo di Ubuntu per far funzionare il sistema di trading 24 ore su 24, 7 giorni su 7.
L’output dopo circa 30 secondi, a seconda dell’ora del giorno relativa ai principali orari di negoziazione per EUR / USD, per il codice descritto in precedenza, è il seguente:
{u'tick': {u'ask': 1.16283, u'instrument': u'EUR_USD', u'bid': 1.1627, u'time': u'2018-01-19T15:28:19.563256Z'}}
{u'tick': {u'ask': 1.16287, u'instrument': u'EUR_USD', u'bid': 1.16274, u'time': u'2018-01-19T15:28:28.021045Z'}}
{u'tick': {u'ask': 1.16287, u'instrument': u'EUR_USD', u'bid': 1.16273, u'time': u'2018-01-19T15:28:30.982725Z'}}
{u'tick': {u'ask': 1.16285, u'instrument': u'EUR_USD', u'bid': 1.16272, u'time': u'2018-01-19T15:28:52.493297Z'}}
{u'tick': {u'ask': 1.16283, u'instrument': u'EUR_USD', u'bid': 1.16272, u'time': u'2018-01-19T15:29:12.854066Z'}}
Executing order!
{
"instrument" : "EUR_USD",
"time" : "2018-01-19T15:29:14.000000Z",
"price" : 1.16283,
"tradeOpened" : {
"id" : 821102691,
"units" : 10000,
"side" : "buy",
"takeProfit" : 0,
"stopLoss" : 0,
"trailingStop" : 0
},
"tradesClosed" : [],
"tradeReduced" : {}
}
{u'tick': {u'ask': 1.16284, u'instrument': u'EUR_USD', u'bid': 1.1627, u'time': u'2018-01-19T15:29:17.817401Z'}}
{u'tick': {u'ask': 1.16283, u'instrument': u'EUR_USD', u'bid': 1.1627, u'time': u'2018-01-19T15:29:17.920900Z'}}
Le prime cinque righe mostrano i dati del tick JSON restituiti da OANDA con prezzi bid / ask. Successivamente puoi vedere l’ordine di esecuzione! così come la risposta JSON restituita da OANDA confermando l’apertura di un’operazione di acquisto per 10.000 unità di EUR / USD e il prezzo a cui è stata raggiunta.
Questo continuerà a funzionare all’infinito fino a quando non si ucciderà il programma con un comando “Ctrl-Z” o simile.
Conclusione
Abbiamo descritto l’implementazione base del sistema di trading sul forex con Oanda. Nelle prossime lezioni apportiamo alcuni miglioramenti, tra cui:
- Strategie reali – Strategie forex corrette che generano segnali redditizi.
- Infrastruttura per il live trading – Implementazione del server remoto e sistema di trading monitorato 24 ore su 24, 7 giorni su 7, con funzionalità di avvio / arresto.
- Portafoglio e gestione del rischio – Portafoglio e sovrapposizioni di rischio per tutti gli ordini suggeriti dalla strategia.
- Strategie multiple – costruzione di un portafoglio di strategie che si integrano nella copertura della gestione del rischio
Come con il trading system basato sugli eventi per il mercato azionario, dobbiamo anche creare un modulo di backtest forex. Ciò ci consentirà di effettuare ricerche rapide e semplificare l’implementazione delle strategie.
Il codice completo presentato in questa lezione, basato sul sistema di trading automatico sul Forex TQforex, è disponibile nel seguente repository GitHub: https://github.com/tradingquant-it/TQforex.”