Foward Test e correzione del Repainting

Foward Test e correzione del Repainting con Tradingview

Nel precedere articolo sul repainting degli indicatori, abbiamo descritto le cause del repainting e le conseguenze sul backtest delle strategie. Nella maggior parte dei casi il repainting non influenza il backtesting. Tuttavia, c’è un caso che può presentare un problema. Le strategie che  usano dati con timeframe multipli possono essere soggette a problemi di repainting durante i foward test con Tradingview. In questo articolo descriviamo il foward test e la correzione del repainting con Tradingviev con un semplice codice di esempio che possiamo usare nei nostri script di trading algoritmico.

Contesto e riepilogo

Nella sua forma più semplice, il repainting dell’indicatore avviene per tutti gli indicatori che si basano sul prezzo di chiusura di una candela per il loro calcolo. Durante il trading dal vivo o i foward test, il valore di chiusura della barra corrente cambia costantemente dal momento in cui la barra si apre fino al momento in cui si chiude. Il prezzo di chiusura finale non è noto fino alla fine della barra. Questo significa che l’indicatore viene costantemente “repainting” durante la barra. Vediamo che gli indicatori si muovono costantemente ad ogni tick ricevuto.

Questa citazione è tratta dall’articolo il Repainting degli Indicatori con Tradingview. Per avere un’introduzione al concetto del repainting degli indicatori, è necessario leggere l’articolo precedente e poi contuare la lettura di questo articolo!

Foward Test e correzione del repainting

Repainting del timeframe superiore: il problema

Per prima cosa, diamo un’occhiata al problema in questione. Copiamo il seguente codice di esempio e posizioniamolo su un grafico di 1 minuto a scelta:

				
					//@version=3
strategy("Dual RSI - RPB Strat")

// Altri time frame
otf = input(defval="15", title="Second Momentum Timeframe", type=resolution)
otf_period = input(defval=14, title="Look Back Period (2nd Timeframe)", type=integer)
ctf_period = input(defval=14, title="Look Back Period (Chart Timeframe)", type=integer)
ob = input(defval=70, title="Overbought Area", type=integer)
os = input(defval=30, title="Oversold Area", type=integer)

// Ottenere i data
otf_rsi = security(tickerid, otf, rsi(close, otf_period))

// Calcolare i valori RSI
ctf_rsi = rsi(close, ctf_period)

// Grafico
hline(ob, title='Overbought Line', color=black, linestyle=dashed, linewidth=1)
hline(os, title='Oversold Line', color=black, linestyle=dashed, linewidth=1)
plot(otf_rsi, title='OTF RSI', color=blue, style=line, linewidth=3)
plot(ctf_rsi, title='CTF RSI', color=green, style=line, linewidth=3)
				
			

Dopo avere caricato lo script, notiamo che le linee si muovono a blocchi di 15 minuti. Ora dobbiamo aspettare circa 30 minuti. Al termine otteniamo un grafico che assomiglia al seguente:

Tradingview-repainting-live-data-timeframe-superiore1

Nell’articolo precedente abbiamo  descritto un parametro di tradingview che, per default, permette ad una strategia di aggiornarsi solo alla fine di ogni barra in modo da evitare i problemi di repainting. Se premiamo “Aggiorna” sul browser, vediamo il repainting del timeframe superiore.

Tradingview-repainting-live-data-timeframe-superiore-aggiornato

Quando effettuiamo un foward test con Tradingview, il motore effettua il repainting dei dati nel timeframe superiore perché stiamo prendendo campioni/snapshot di 1 minuto per ciascuna barra del timeframe sul nostro grafico. Quando usiamo dati in tempo reale e prendiamo un campione, la  candela nel timeframe superiore non è stata ancora completata. Pertanto, Tradingview fornisce l’ultimo valore disponibile per quella candela. Questo valore non è il valore di chiusura della candela ma è il valore di chiusura corrente . Di conseguenza, possiamo ottenere una linea sinuosa invece della linea retta che vediamo con i dati storici.

Inoltre, notiamo come il timeframe del grafico (la linea verde) NON è stato ridisegnato. Questo mostra che il problema è limitato solo ai timeframe superiori.

Se desideriamo vedere come funziona il campionamento, è possibile affiancare un altro timeframe e fare un confronto dei valori finali in ciascun periodo. Nota: La seguente immagine mostra un esempio dove usiamo un grafico a 1 minuto rispetto a un grafico a 10 minuti.

Foward test con Tradingview-10-minute-chart-side-by-side-with-Dual-Indicator

Come possiamo vedere, alla fine del periodo di 10 minuti, abbiamo lo stesso valore dell’indicatore posizionato direttamente sul grafico del timeframe superiore. Qui possiamo vedere che anche se la linea si sposta, i due valori si incontrano alla fine del periodo.

Tutto questo ha la sua logica. Tuttavia, se abbiamo eseguito i backtest sui dati storici (dove i dati campionati non sono disponibili), possiamo ottenere prestazioni impreviste della strategia. Inoltre, se abbiamo una logica di entrata che si basa sull’osservazione di un valore nel timeframe superiore, allora la strategia potrebbe entrare a metà della barra dei 10 minuti. In questo caso, se aggiorniamo il browser i dati diventano storici e il trade scompare. Il classico problema di repainting!

La soluzione

				
					//@version=3
strategy("Dual RSI - RPB Study")

// Altro timeframe
otf = input(defval="15", title="Second Momentum Timeframe", type=resolution)
otf_period = input(defval=14, title="Look Back Period (2nd Timeframe)", type=integer)
ctf_period = input(defval=14, title="Look Back Period (Chart Timeframe)", type=integer)
ob = input(defval=70, title="Overbought Area", type=integer)
os = input(defval=30, title="Oversold Area", type=integer)

// Funzione per verificare una nuova barra
is_newbar(res) =>
    t = time(res)
    change(t) != 0 ? true : false

// Controllo quante barre sono nel timeframe superiore
since_new_bar = barssince(is_newbar(otf))
otf_total_bars = na
otf_total_bars := since_new_bar == 0 ? since_new_bar[1] : otf_total_bars[1]

// Otteniamo i dati
otf_rsi = security(tickerid, otf, rsi(close, otf_period))

// Calculare i valori RSI
ctf_rsi = rsi(close, ctf_period)

final_otf_rsi = na
final_otf_rsi := barstate.isrealtime ? since_new_bar == otf_total_bars ? otf_rsi : final_otf_rsi[1] : otf_rsi

// Grafico
hline(ob, title='Overbought Line', color=black, linestyle=dashed, linewidth=1)
hline(os, title='Oversold Line', color=black, linestyle=dashed, linewidth=1)
plot(final_otf_rsi, title='OTF RSI', color=blue, style=line, linewidth=3)
plot(ctf_rsi, title='CTF RSI', color=green, style=line, linewidth=3)
//plot(otf_rsi, title='Non Adjusted OTF', color=blue, linewidth=3)
				
			

Commento

La soluzione proposta in questo esempio è determinare quante barre sono nel nostro timeframe superiore e quindi aggiornare il valore RSI del timeframe solo durante l’ultima barra. A questo punto otteniamo il prezzo di chiusura dell’ultima barra per l’intero del timeframe superiore. Come descritto in precedenza, questa è la chiusura corretta e finale per il timeframe superiore.

Una volta che abbiamo l’ultima chiusura, per tutte le altre barre da 1 minuto, possiamo semplicemente fare riferimento al valore precedente della stessa linea. Lo facciamo finché non è il momento di aggiornare nuovamente il valore finale. In questo modo ignoriamo il timeframe superiore fino a quando non si chiude realmente.

Questo si ottiene con la seguente istruzione:

final_otf_rsi := barstate.isrealtime ? since_new_bar == otf_total_bars ? otf_rsi : final_otf_rsi[1] : otf_rsi

Da notare che questa soluzione funziona solo per gli script STRATEGY perché prendiamo il valore corrente sull’ultima barra  del timeframe. Come descritto nell’ultimo articolo, gli script study si aggiornano continuamente durante una barra quindi se usiamo questa soluzione negli script study l’ultima barra di ogni timeframe superiore avrebbe il repainting durante la barra.

Test

Dopo aver posizionato il codice sul grafico, otteniamo qualcosa simile a quanto segue:

Foward test con Tradingview-Upper-Timeframe-Reapiting-Time-Test

Come possiamo vedere, con i dati storici la linea arancione (la linea senza correzione) e la linea blu (la linea con la correzione) sono identiche, e la sovrapposizione  delle due crea la linea marrone. Con i dati reali vediamo che la linea gialla si interrompe e inizia ad aggiornarsi ad ogni barra mentre la linea blu continua a comportarsi nello stesso modo che con i dati storici.

Per ulteriore verifica, possiamo commentare la linea arancione, quindi possiamo verificare che la linea blu si aggiorni agli stessi intervalli. Alcune soluzioni sono effettivamente tracciate con un ritardo di una barra. Qui possiamo vedere che i tempi di aggiornamento sono esattamente gli stessi.

Foward test con Tradingview-Upper-Timeframe-Reapiting-Time-Checks

Le linee verticali arancioni mostrano gli orari in cui il grafico è stato aggiornato. Possiamo vedere che il grafico si aggiorna negli stessi intervalli.

Codice completo

In questo articolo abbiamo descritto come fare il foward test e correzione del repainting con Tradingview. Per il codice completo riportato in questo articolo, si può consultare il seguente repository di github:
https://github.com/datatrading-info/TradingView

Scroll to Top