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 !
Quantitativetrading
Un approccio quantitativo sull'Indice Tecnologico Nasdaq 100
Ciao a tutti,
Oggi volevo presentare una idea alternativa rispetto alle precedenti introducendo dei modelli che possono essere utili per prevedere l'andamento futuro di un determinato strumento finanziario: parliamo di modelli additivi .
Molti modelli di previsione , come quello appena citato , si basano sul fatto che se ,esiste un pattern sistematico nella serie, questo possa essere separato da eventuali oscillazioni accidentali mediante dei metodi di smussamento. L'effetto dello smussamento è quello di eliminare disturbi casuali (effetto noise in una serie), cosicché una volta individuato il pattern sistematico, questo possa essere proiettato nel futuro per produrre la previsione.
Infatti quello che abbiamo fatto non è stato altro che analizzare la serie storica dei prezzi giornalieri e scomporla nelle sue fasi: Trend e ciclo . Pertanto il seguente modello è composto dalle seguenti caratteristiche:
1. Livelli ( la media dei valori della serie)
2. Trend ( per semplicità attualmente assumiamo che sia lineare)
3. Stagionalità
4. Residui ( effetto casuale in una serie)
A questo punto una volta introdotto brevemente il modello possiamo passare all'analisi (ovviamente per qualsiasi approfondimento su quanto detto potete scrivermi o commentare direttamente l'idea ).
Le immagini che ho allegato sul grafico sono la risultante di quanto spiegato: nella prima trovate le previsioni dell'indice e nella seconda le caratteriste della serie.
La prima immagine in alto rappresenta l'andamento giornaliero dell'indice dal 2008 ad oggi: i puntini neri sono le chiusure giornaliere e la linea blu la sua previsione. Il grafico segnala già alcuni spunti piuttosto interessanti:
- La linea di previsione è attrattiva per il prezzo: le oscillazioni sono sempre comprese tra le due bande e in media sull'andamento previsto
- Le fase erratiche (quelle evidenziate in giallo) sempre spesso mostrano un brusco cambiamento dell'indice per poi ritornare tra quanto il modello prevede. Le parti evidenziate in giallo effettivamente corrispondo a delle inversioni per l'indice e tanto più i prezzi si allontano dal modello previsionale e maggiore sarà l'inversione di trend.
La seconda immagine in basso mostra le caratteristiche intrinseche della serie nonché dell'indice. La parte di maggiore interesse è quella rappresentata dalla stagionalità (Seasonal): depurata dagli errori l'indice può mostrare una stagionalità sistematica. Dopo aver impostato una finestra temporale di 12 giorni (questa può essere scelta a discrezione del trader) il ciclo della serie è piuttosto esplicito e visibile anche dal grafico: la parte cerchiata figura l'inversione della serie iniziata il 13 Ottobre ( l'ultimo aggiornamento dei prezzi è del 29 Ottobre e considerato a ritroso i 12 giorni impostati come margine temporale) e di reazione anche dal prezzo ( rettangolo arancione )
Avendo fatto brevemente tutte le considerazioni passate sul nostro modello possiamo ora fare una analisi attuale dell'indice: il trend primario della serie sembrerebbe non essere concluso ma ci aspettiamo una pausa e quindi un rintracciamento. Per i prezzi mi attendo una breve scesa in media con le previsioni attuali ( linea blu ) per poi impostare un operazione in acquisto.
Appena il rintracciamento sarà concluso aggiornerò l'idea per poi impostare correttamente il trade.
Se avete dubbi o domande di qualsiasi genere o volete conoscere altri nuovi aspetti non esitate a scrivere o commentare direttamente qui sotto
A presto,
Alessio