Questo articolo descrive come implementare uno schema di commissioni forex con backtrader, framework di trading algoritmico open-source implementato in python. Come noto, la maggior parte dei broker forex nasconde le proprie commissioni all’interno dello spread. Questo può generare risultati di backtest imprecisi dato che Backtrader non tiene traccia dello spread denaro/lettera. Il codice di questo articolo tenta di fare un primo passo verso una soluzione a questo problema (con alcune limitazioni).
Schema delle commissioni per Forex
class forexSpreadCommisionScheme(bt.CommInfoBase):
'''
Questo schema di commissioni tenta di calcolare la commissione nascosta
nello spread dalla maggior parte dei broker forex.
Presuppone che vengano utilizzati i dati del punto medio tra bid e ask.
*Nuovi parametri*
spread: Float, lo spread in pips dello strumento
JPY_pair: Bool, indica se la coppia scambiata è una coppia JPY
acc_counter_currency: Bool, indica se la valuta del conto è la stessa della
valuta del contatore. Se falso, si presume che sia la valuta di base
'''
params = (
('spread', 2.0),
('stocklike', False),
('JPY_pair', False),
('acc_counter_currency', True),
('commtype', bt.CommInfoBase.COMM_FIXED),
)
def _getcommission(self, size, price, pseudoexec):
'''
Questo schema applicherà metà della commissione all'acquisto e metà alla vendita.
Per le coppie JPY il moltiplicatore viene modificato di conseguenza.
Se la valuta del conto è la stessa della valuta di base, modificare il calcolo del valore in pip.
'''
if self.p.JPY_pair == True:
multiplier = 0.01
else:
multiplier = 0.0001
if self.p.acc_counter_currency == True:
comm = abs((self.p.spread * (size * multiplier) / 2))
else:
comm = abs((self.p.spread * ((size / price) * multiplier) / 2))
return comm
Commento al codice
Prima di tutto, il codice cerca di essere abbastanza flessibile per gestire anche le coppie con yen giapponesi. Se stiamo negoziando una coppia JPY, dobbiamo specificarla come parametro quando inizializziamo lo schema. Per quelli di voi che non lo sapessero, le coppie JPY richiedono un calcolo diverso dato che le quotazioni dei prezzi hanno solo a due cifre decimali invece delle solite quattro.
D’altra parte, lo schema ha alcune limitazioni. Il primo è che la valuta del conto deve essere la stessa della valuta di base o della controvaluta. Non supporta il conto detenuto in una terza valuta (ad esempio un conto in EUR che scambia USDJPY). Se supportasse una terza valuta, per il calcolo sarebbe necessario l’ultimo tasso di cambio dell’account. La seconda limitazione è che lo schema presuppone uno spread fisso. Con questi vincoli, se abbiamo una strategia che opera attorno a eventi macroeconomici (quando gli spread tendono ad allargarsi), allora questo schema potrebbe non essere adatto.
Infine dobbiamo sottolineare che lo schema applica metà della commissione all’acquisto e metà alla vendita. In alternativa, si potrebbe applicare lo schema completo solo in una direzione (vale a dire all’acquisto o alla vendita).
Usare lo schema delle commissioni forex con backtrader
Per utilizzare lo schema delle commissioni in una strategia di trading algoritmico, possiamo caricarlo in cerebro con le seguenti righe di codice
#Aggiungere lo schema commissionale
comminfo = forexSpreadCommisionScheme(spread=10)
cerebro.broker.addcommissioninfo(comminfo)
Da notare che le impostazioni predefinite per lo schema prevedono che la valuta del conto corrisponda alla controvaluta. Se la valuta dell’account è la stessa della valuta di base, dovremmo inizializzarla in questo modo:
comminfo = forexSpreadCommisionScheme(spread=10, acc_counter_currency=False)
Risultati
Per testare e controllare la commissione risultante, possiamo utilizzare un semplice esempio come:
- Utilizzando un conto denominato in USD
- Scambiare una coppia in cui l’USD è una controvaluta (ad es. EURUSD)
- Eseguire un solo trade
- Apre una posizione di 10.000, quindi 1 pip = $1
Oltre a questo, possiamo anche inserire nella strategia di trading algoritmico un metodo che permetta di stampare il profitto/perdita del trade. Di seguito è una strategia super semplice che implementa quanto sopra. Apre una posizione sulla prima barra (candela) e chiude la posizione sulla decima barra.
class testStrategy(bt.Strategy):
'''
Strategia super semplice per verificare se lo schema delle commissioni viene applicato correttamente
'''
def __init__(self):
self.count = 0
def next(self):
self.count = len(self)
if self.count == 1:
self.buy(size=10000)
elif self.count == 10:
self.close()
else:
pass
def notify_trade(self, trade):
if not trade.isclosed:
return
print(('OPERATION PROFIT, GROSS {}, NET {}'.format(trade.pnl, trade.pnlcomm)))
L’esecuzione dello script precedente produce un output simile all’immagine sottostante. Naturalmente il profitto e la perdita effettivi cambieranno a seconda dei dati che stai utilizzando. Giusto per essere chiari, ho eseguito lo script con uno spread di 10 pip e ho impostato la valuta del conto come controvaluta.
Aspetta … ma il mio broker non addebita una commissione ….
Come accennato in precedenza, le commissioni dei broker sono nascoste nello spread. Questo è il motivo per cui amano i trader retail che operano con timeframe bassi. Più trade piazzati == più commissioni perché bisogna applicare il loro spread ogni volta che si fa un trade.
Se non sei ancora convinto, pensala in questo modo. In Backtrader generalmente utilizziamo un prezzo medio. Quando chiudiamo una posizione, la chiudiamo anche al prezzo medio e calcoliamo il profitto e la perdita tra questi due livelli di prezzo medio. Tuttavia, nel mondo reale, la tua operazione avrebbe x pip di profitto in meno a causa della differenza tra bid e ask. In altre parole, se andiamo long, avremmo comprato a un prezzo leggermente più alto e venduto a un prezzo leggermente più basso. Questo schema correggerà il profitto e la perdita con quella differenza. Si spera che lo troverai per ottenere risultati di backtest più accurati.
Codice completo
In questo articolo abbiamo descritto come implementare uno schema di commissioni forex con backtrader per le 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