Backtest of the week: Ethereum Interessante backtesting su Ethereum ( BINANCE:ETHUSDT ).
Il backtesting è stato effettuato utilizzando il nostro algoritmo open source iMoku
La strategia utilizzata è una Kumo Twist .
Parametri utilizzati:
Tenkan Sen Lenght: 10
Kijun Sen Lenght: 10
Leading Span B Lenght: 60
Lagging Span: 13
Timeframe di analisi: 4H
Costi di transazione: 0.10%
I risultati offerti dal backtesting sono quantitativamente migliori rispetto al rendimento dell'asset, possiamo infatti notare 89 trades effettuati all'interno del periodo di analisi (20 Settembre 2017 - Oggi). Il ritorno in termini di performance percentuale si attesta a 404.38%, con un drawdown massimo del 22% circa. Analizzando il backtesting con il rendimento buy and hold possiamo notare una minore volatilità e una maggiore solidità dell'equity da parte della strategia, rispetto all'asset di riferimento. Un approccio buy and hold avrebbe generato il 60% in più in termini di rendimento, surplus che non giustifica in ogni modo il rischio derivante dall'alta volatilità e dalla mancata stabilità dell'equity line. In conclusione, possiamo ritenere quantitativamente migliore il trading workflow basato sulla strategia rispetto all'approccio buy and hold di questo asset.
Quant
Utilizzare la statistica con Pine Script Ciao a tutti !
Oggi vogliamo offrire un contenuto di alto valore alla comunità italiana di Trading View motivandola nell' utilizzare Pine Script, un potente linguaggio di programmazione proprietario progettato per essere il migliore in termini di elaborazione dati finanziari e trading.
Andremo a commentare il codice rilasciato nella nostra sezione script 'Reinforced RSI':
La strategia proposta è una strategia long che utilizza l'indicatore RSI con un rinforzo matematico statistico, rilevabile integrando il nostro modulo 'Probabilities'.
Il modulo Probabilities, calcola le probabilità passate di ciascuna operazione e permette di estrapolare le probabilità di operazioni profittevoli in termini quantitativi.
Logica della strategia: si acquista long, utilizzando l'indicatore RSI, su un determinato valore di iper venduto chiudendo l'operazione su un determinato livello di iper comprato. Ogni operazione è regolata da stop loss e take profit, offrendo maggiore dinamicità alla strategia. Infine viene integrato il modulo 'Probabilities' che filtra le operazioni, evitando di scambiare in periodi poco profittevoli. Utilizzando questo modulo infatti, le operazioni vengono aperte e eseguite a mercato solo ed esclusivamente se le probabilità passate di scambiare in profitto sono maggiori al 51%.
Commentiamo quindi il codice sorgente di Reinforced RSI, rendendolo il più fruibile e chiaro possibile.
//@version=5
strategy("RSI with reinforcement",
overlay = true,
default_qty_type = strategy.percent_of_equity,
default_qty_value = 100,
pyramiding = 1,
currency = currency.EUR,
initial_capital = 1000,
commission_type = strategy.commission.percent,
commission_value = 0.07)
Questo primo blocco di codice descrive la tipologia di script, popolando la strategia con tutte le informazioni necessarie al suo corretto funzionamento.
lenght_rsi = input.int(defval = 14, minval = 1, title = "RSI lenght: ")
rsi = ta.rsi(close, length = lenght_rsi)
Si crea una variabile integrata e modificabile dall' interfaccia utente per regolare la lunghezza di calcolo dell'indicatore RSI.
Si chiama l' indicatore RSI, calcolando la formula sul prezzo 'close' che verrà calcolata sulla lunghezza impostata.
rsi_value_check_entry = input.int(defval = 35, minval = 1, title = "Oversold: ")
rsi_value_check_exit = input.int(defval = 75, minval = 1, title = "Overbought: ")
Si creano due variabili integrate e modificabili dall' interfaccia utente per regolare i valori di iper venduto e iper comprato.
trigger = ta.crossunder(rsi, rsi_value_check_entry)
exit = ta.crossover(rsi, rsi_value_check_exit)
Si definiscono le condizioni di ingresso e uscita. Si aprirà una operazione long se il prezzo è sul livello di iper venduto e si chiuderà la posizione al livello di iper comprato.
entry_condition = trigger
TPcondition_exit = exit
look = input.int(defval = 30, minval = 0, maxval = 500, title = "Lookback period: ")
Probabilities(lookback) =>
isActiveLong = false
isActiveLong := nz(isActiveLong , false)
isSellLong = false
isSellLong := nz(isSellLong , false)
int positive_results = 0
int negative_results = 0
float positive_percentage_probabilities = 0
float negative_percentage_probabilities = 0
LONG = not isActiveLong and entry_condition == true
CLOSE_LONG_TP = not isSellLong and TPcondition_exit == true
p = ta.valuewhen(LONG, close, 0)
p2 = ta.valuewhen(CLOSE_LONG_TP, close, 0)
for i = 1 to lookback
if (LONG )
isActiveLong := true
isSellLong := false
if (CLOSE_LONG_TP )
isActiveLong := false
isSellLong := true
if p > p2
positive_results += 1
else
negative_results -= 1
positive_relative_probabilities = positive_results / lookback
negative_relative_probabilities = negative_results / lookback
positive_percentage_probabilities := positive_relative_probabilities * 100
negative_percentage_probabilities := negative_relative_probabilities * 100
positive_percentage_probabilities
probabilities = Probabilities(look)
Si integra il modulo delle probabilità, aggiustando il codice sorgente al nostro use case.
In particolare assegnamo le condizioni di ingresso e uscita con:
entry_condition = trigger
TPcondition_exit = exit
Assegnamo poi al contenitore di trade positivi +1 se il prezzo di chiusura dell'operazione è maggiore rispetto a quello di chiusura.
Facciamo lo stesso per le operazioni negative in cui il prezzo di chiusura è inferiore a quello di apertura.
Automaticamente il modulo calcolerà le probabilità passate della strategia.
if p > p2
positive_results += 1
else
negative_results += 1
Concluso l'aggiustamento del modulo al nostro use case, passiamo a concludere la strategia.
lots = strategy.equity/close
var float e = 0
var float c = 0
Calcoliamo la quantità da scambiare per ogni singola posizione (100% dell'equity depositato sulla strategia).
tp = input.float(defval = 1.00, minval = 0, title = "Take profit: ")
sl = input.float(defval = 1.00, minval = 0, title = "Stop loss: ")
Creiamo due variabili integrate all' interno dell'interfaccia utente. Una per regolare il take profit, l'altra per regolare lo stop loss.
if trigger==true and strategy.opentrades==0 and probabilities >= 51
e := close
strategy.entry(id = "e", direction = strategy.long, qty = lots, limit = e)
takeprofit = e + ((e * tp)/100)
stoploss = e - ((e * sl)/100)
if exit==true
c := close
strategy.exit(id = "c", from_entry = "e", limit = c)
if takeprofit and stoploss
strategy.exit(id = "c", from_entry = "e", stop = stoploss, limit = takeprofit)
Infine si descrive la logica di trading, specificando che ogni trade viene effettuato solo ed esclusivamente se le probabilità sono uguali o maggiori a 51%.
Puoi trovare il codice completo qui sotto, oppure nella nostra sezione script :
// This source code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org
// © thequantscience
//@version=5
strategy("RSI with reinforcement",
overlay = true,
default_qty_type = strategy.percent_of_equity,
default_qty_value = 100,
pyramiding = 1,
currency = currency.EUR,
initial_capital = 1000,
commission_type = strategy.commission.percent,
commission_value = 0.07)
lenght_rsi = input.int(defval = 14, minval = 1, title = "RSI lenght: ")
rsi = ta.rsi(close, length = lenght_rsi)
rsi_value_check_entry = input.int(defval = 35, minval = 1, title = "RSI value check entry: ")
rsi_value_check_exit = input.int(defval = 75, minval = 1, title = "RSI value check exit: ")
trigger = ta.crossunder(rsi, rsi_value_check_entry)
exit = ta.crossover(rsi, rsi_value_check_exit)
entry_condition = trigger
TPcondition_exit = exit
look = input.int(defval = 30, minval = 0, maxval = 500, title = "Lookback period: ")
Probabilities(lookback) =>
isActiveLong = false
isActiveLong := nz(isActiveLong , false)
isSellLong = false
isSellLong := nz(isSellLong , false)
int positive_results = 0
int negative_results = 0
float positive_percentage_probabilities = 0
float negative_percentage_probabilities = 0
LONG = not isActiveLong and entry_condition == true
CLOSE_LONG_TP = not isSellLong and TPcondition_exit == true
p = ta.valuewhen(LONG, close, 0)
p2 = ta.valuewhen(CLOSE_LONG_TP, close, 0)
for i = 1 to lookback
if (LONG )
isActiveLong := true
isSellLong := false
if (CLOSE_LONG_TP )
isActiveLong := false
isSellLong := true
if p > p2
positive_results += 1
else
negative_results += 1
positive_relative_probabilities = positive_results / lookback
negative_relative_probabilities = negative_results / lookback
positive_percentage_probabilities := positive_relative_probabilities * 100
negative_percentage_probabilities := negative_relative_probabilities * 100
positive_percentage_probabilities
probabilities = Probabilities(look)
lots = strategy.equity/close
var float e = 0
var float c = 0
tp = input.float(defval = 1.00, minval = 0, title = "Take profit: ")
sl = input.float(defval = 1.00, minval = 0, title = "Stop loss: ")
if trigger==true and strategy.opentrades==0 and probabilities >= 51
e := close
strategy.entry(id = "e", direction = strategy.long, qty = lots, limit = e)
takeprofit = e + ((e * tp)/100)
stoploss = e - ((e * sl)/100)
if exit==true
c := close
strategy.exit(id = "c", from_entry = "e", limit = c)
if takeprofit and stoploss
strategy.exit(id = "c", from_entry = "e", stop = stoploss, limit = takeprofit)
Il backtesting dell'esempio è effettuato su NASDAQ:TSLA , timeframe 15 minuti.
I parametri impostati dall'interfaccia utente sono:
1. Lenght: 13
2. Oversold: 40
3. Overbought: 70
4. Lookback: 50
5. Take profit: 3%
6. Stop loss: 3%
Il nostro modulo 'Probabilites':
Per noi è importante il tuo feedback, facci sapere se questo contenuto ti è stato di aiuto !