La strategia restituisce risultati troppo positivi e non realistici guardando al futuro

Uno dei nostri obiettivi principali con lo sviluppo di Pine è quello di fornire una serie di strumenti che possano adattarsi alle esigenze dei vari utenti. Questi strumenti si prestano ad una varietà di scopi e, tramite alcune manipolazioni, possono "sbirciare" ai dati dal futuro (rispetto alla barra corrente). Dato che in condizioni normali un trader non ha accesso a certe informazioni, le strategie costruite con tali meccanismi possono restituire risultati eccessivamente ottimistici durante la fase di backtesting, in modo fuorviante rispetto a quello che si sarebbe ottenuto operando in tempo reale. Ciò è dovuto al cosiddetto look-ahead bias.

Alcuni autori di TradingView, talvolta per malizia, talvolta per semplice ignoranza, pubblicano idee o script che sfruttano tale problematica. TradingView non può rimuovere la funzionalità perché in alcune circostanze può tornare utile, ma al tempo stesso si impegna a mettere in guardia gli ignari utenti.

Strategie con grafici alternativi giapponesi

Una delle ragioni più comuni dietro il manifestarsi del look-ahead bias è l'utilizzo di grafici giapponesi alternativi (Renko, Kagi, ecc.). Ciò perché il motore di esecuzione del backtesting considera ogni barra in 4 momenti salienti: apertura, chiusura, massimo e minimo (come normale per le candele classiche). Ne consegue che, per la natura di un grafico Renko, l'esecuzione degli ordini può avvenire a prezzi mai raggiunti realmente dal mercato. Inoltre, laddove la dimensione del mattone sia inferiore al tick minimo, è possibile che la strategia controlli se il prezzo successivo risulti maggiore o minore di quello corrente e, sulla base di questo entri od esca in anticipo (ovvero prima che il motore del backtesting processi il prezzo reale):

//@version=4
strategy("My Strategy", overlay=true)
if close < close[1]
strategy.entry("ShortEntryId", strategy.short)
strategy.close("ShortEntryId", when = close > close[1])

if close > close[1]
strategy.entry("LongEntryId", strategy.long)
strategy.close("LongEntryId", when = close < close[1])
Come si può vedere dallo screenshot, questa semplice strategia può effettuare operazioni a prezzi molto vicini a quelli di massimo e minimo.

Strategie con il parametro calc_on_order_fills = true

Quando il parametro calc_on_order_fills è impostato su true nella funzione strategy, il motore di backtesting esegue un calcolo aggiuntivo all'interno della barra dopo che l'ordine è stato eseguito (in contrastro con il metodo classico per cui la strategia prende sempre in considerazione una barra dopo che si è chiusa). Durante questo calcolo, la strategia ha accesso a molti più parametri sulla barra, come ad esempio i valori di massimo e minimo. Se sfruttato, questo difetto può portare a risultati eccellenti in fase di backtesting:
//@version=4
strategy("CalcOnOrderFillsStrategy", overlay=true, calc_on_order_fills=true)

// a variable is used to prevent double entry on the same bar
var lastTimeEntry = 0

longCondition = close > sma(close, 14) and lastTimeEntry != time
if longCondition
strategy.entry("LongEntryId", strategy.long)

strategy.exit("exitId", "LongEntryId", limit=high)
lastTimeEntry := time

Nello screenshot, è possibile notare come le entrare avvengano al prezzo di apertura della barra mentre le uscite al prezzo di chiusura. Ciò perché il codice stabilisce che dopo l'esecuzione dell'ordine di entrata si ponga come ordine limite di uscita il massimo raggiunto dalla barra corrente, una cosa ovviamente impossibile durante il trading in tempo reale.

Il parametro lookahead = barmerge.lookahead_on nella funzione security, e qualsiasi security su versioni di Pine precedenti alla v3

All'interno di Pine, la funzione security permette di richiedere i dati da altri simboli e/o timeframe. A seconda dell'implementazione, questo può consentire alla strategia di ricevere informazioni dal futuro: per esempio, se viene richiesto il prezzo di chiusura o di massimo di una barra giornaliera, in fase di backtesting la strategia potrebbe recepire i dati in fase di apertura della barra corrente.

Nelle versioni precedenti alla 3, la funzione security restituiva il valore di un timeframe superiore ancor prima che questo fosse realmente accessibile. Nella versione 3, questo comportamento è stato aggiustato, ma per garantire compatibilità il parametro lookahead è stato aggiunto alla funzione security. Di default, questo sarà disattivato, ma l'utene può abilitarlo semplicemente impostandolo su barmerge.lookahead_on.

Di seguito un esempio concreto:

//@version=4
strategy("My Strategy", overlay=true)
dayStart = security(syminfo.tickerid, "1D", time, lookahead=barmerge.lookahead_on)
dayHigh = security(syminfo.tickerid, "1D", high, lookahead=barmerge.lookahead_on)
dayLow = security(syminfo.tickerid, "1D", low, lookahead=barmerge.lookahead_on)

// entry at first bar of a day
if time == dayStart
// distance to daily high is further, so we can earn more
if abs(open - dayHigh) > abs(open - dayLow)
strategy.entry("LongEntryId", strategy.long)
strategy.exit("exitLongId", "LongEntryId", limit=dayHigh)
else
strategy.entry("ShortEntryId", strategy.short)
strategy.exit("exitShortId", "ShortEntryId", limit=dayLow)

plot(dayHigh)
plot(dayLow)

Nella prima barra, viene analizzato se il prezzo si muoverà al rialzo o al ribasso rispetto all'apertura gioranliera, e di conseguenza si apre una posizione long/short che massimizzi il profitto giornaliero.

Tieni a mente che la mera presenza dell'argomento barmerge.ookahead_on all'interno di security() non è di per sé garanzia che lo script "sbirci" nel futuro: ad esempio, se nel codice qui sopra rimpiazzassimo time/high/low utilizzati all'interno di security() con time[1]/high[1]/low[1], riceveremmo informazioni su barre già chiuse e definite, come accade in condizioni normali. Gli sviluppatori più esperti utilizzano questo metodo per evitare l'insorgenza di risultati sballati.

Al momento, queste sono tutte le modalità conosciute con cui è possibile guardare nel futuro. Speriamo che queste descrizioni possano aiutarti a creare strategie realistiche e ad evitare di essere ingannato dagli script degli altri utenti.