In questo articolo descriviamo come implementare il data replay con backtrader per usare i dati storici come se fossero in tempo reale nelle strategie di trading algoritmico.
Una criticità del backtesting, per cui i trader algoritmici devono prestare molta attenzione, è la poca accuratezza con cui fornisce indicazioni delle prestazioni di una strategia quando si usano dati reali. Uno dei motivi è che nel backtesting usiamo una grande quantità di informazioni, tutte contemporaneamente, in particolare i dati di apertura, massimo, minimo e chiusura per un determinato timeframe. Pertanto, non abbiamo informazioni su cosa sia accaduto ai prezzi tra l’apertura e la chiusura. Conosciamo il prezzo massimo raggiunto ma non sappiamo come ci sia arrivato. L’azione dei prezzi era volatile? È stata una salita costante? Il prezzo ha toccato prima i minimi?
Data Replay con Backtrader
Maggiore è il timeframe dove facciamo trading, più informazioni sono mancanti. Per aggiungere un ulteriore livello di realismo possiamo usare il Data Replay, cioè usare i dati di un timeframe inferiore (supponendo di avere a disposizione i dati in un timeframe inferiore). Il replay dei dati funziona in modo simile al ricampionamento, ma con un vantaggio chiave. I dati del timeframe inferiore che stiamo usando per creare la candela del timeframe più elevato sono usati per creare un’immagine dell’andamento dei prezzi tra l’apertura e la chiusura. Ad esempio, possiamo lavorare su un timeframe giornaliero e sapere che il prezzo è sceso prima di raggiungere il massimo della giornata tramite il replay dei dati ad 1 minuto. Un altro vantaggio dei replay dei dati è la possibilità di avere maggiore accuratezza quando uno stop loss e un take profit si verificano sulla stessa barra, che di solito è causato da un un’elevata volatilità dei prezzi all’interno di una candela.
Il motore di backtesting non ha idea se i prezzi hanno raggiunto prima il take profit o lo stop loss, quindi possono essere attivati entrambi. Il motore può capire solamente che il prezzo ha attraversato entrambe le soglie durante quella barra. Quando si usa il data replay questo non accade perchè usando una risoluzione maggiore il take profit e lo stop loss non possono verificarli contemporaneamente. Il data repley non è privo di svantaggi perchè si introducono complessità aggiuntive che devono essere tenute in considerazione quando si usa questa tecnica. Pertanto, questo articolo vuole aggiungere valore descrivendo questi punti.
Documentazione ufficiale
La buona notizia è che configurare il data replay con backtrader per le strategie di trading algoritmico è molto semplice. La documentazione ufficiale descrive alcuni buoni esempi e può essere consultata in questa pagina.
Costruzione delle candele
La prima cosa che dobbiamo considerare quando usiamo il data replay è la costruzione graduale delle candele. Il data replay aggiorna il prezzi High
, Low
o Close
di una candela nel timeframe superiore ad ogni nuovo tick dei dati con timeframe inferiore.
Questo potrebbe sembrare ovvio ma è facile dimenticarsene, soprattutto se siamo abituati a lavorare con un timeframe più elevato usando i dati di self.data.close[0]
. Questo perché…
Il metodo Next() è chiamato ad ogni barra del timeframe inferiore
Il metodo next()
è chiamato ogni volta che si acquisisce una barra OHLC dai dati di input. Ad esempio, se riproduciamo i dati (data replay) con timeframe giornaliero e usiamo dati a 1 minuto, il metodo next()
è chiamato ad ogni minuto. Dato che next()
è chiamato moltissime volte, non possiamo semplicemente eseguire uno script implementato su un timeframe superiore. Dobbiamo aggiungere alcune istruzioni che impediscono di effettuare entrate/uscite man mano che si forma la candela.
La lunghezza dei dati aumenta solo quando una barra è completa
In Backtrader possiamo facilmente conoscere il numero della barra che stiamo analizzando tramite l’istruzione len(self.data)
. Di solito (quando non si usa il data replay) il numero di barre aumenta ad ogni chiamata di next()
. Tuttavia, durante il data replay, il numero aumenta solo quando si completa (chiude) la barra del timeframe superiore. In questo modo possiamo identificare quando una barra è completa e ne inizia una nuova, quindi il riferimento alla posizione dell’indice [-1]
restituirà una intera barra di dati OHLC per la candela che si è appena chiusa nel timeframe più elevato. D’altra parte, il riferimento alla posizione dell’indice [0]
restituirà solo i dati per una barra del timeframe inferiore. Come accennato in precedenza, è un valore in continua evoluzione con ogni chiamata al metodo next()
.
Identificare una nuova candela
Di seguito descriviamo un semplice esempio del metodo next()
che può essere copiato all’interno di una strategia per determinare quando intraprendere azioni nei timeframe più alti.
def __init__(self):
# Per tracciare timeframe alti
self.last_bar = len(self)
def next(self):
bar = len(self)
# Controllo se non abbiamo posizioni aperte e abbiamo una barra sul timeframe alto.
if not self.position and bar > self.last_bar:
pass
self.last_bar = bar
Come possiamo vedere è piuttosto semplice. Stiamo controllando se la barra corrente è maggiore dell’ultima barra memorizzata. Poiché self.last_bar
è memorizzato ad ogni barra del timeframe inferiore, bar
è diverso da self.last_bar
solo quando abbiamo abbiamo una nuova barra del timeframe superiore. Inoltre, possiamo usare l’indice [-1]
per ottenere l’OHLC della barra completa più recente poiché è chiamato solo una volta per ogni barra.
Lavorare sull’ultimo tick della barra
Se vogliamo lavorare dall’ultimo tick della barra, allora abbiamo bisogno di un contatore. Ad ogni chiamata di next, aumentiamo il contatore di uno. Quindi, una volta individuata una nuova barra, dobbiamo azzerare il contatore. È quindi possibile eseguire azioni if self.counter = x:
. Ad esempio, se stiamo riproducendo i dati ad 1 minuto nel timeframe orario, possiamo eseguire un’azione ogni volta che il contatore è pari a 60.
Codice completo
In questo articolo abbiamo descritto come implementare il data replay con backtrader per usare i dati storici come se fossero in tempo reale nelle strategie di trading algoritmico. Per il codice completo riportato in questo articolo, si può consultare il seguente repository di github:
https://github.com/datatrading-info/BackTrader