Cet article explique principalement une stratégie de trading d'oscillation de momentum basée sur l'indicateur stochastique RSI. La stratégie adopte des indicateurs techniques de cycle plus court (comme 30 minutes) pour prendre des décisions de trading basées sur le fait que l'indicateur stochastique RSI entre dans la région de surachat/survente.
L'indicateur de base de la stratégie est le RSI stochastique.
L'indicateur RSI stochastique = (RSI - RSI bas) / (RSI haut - RSI bas) * 100
Lorsque le RSI est calculé à l'aide du paramètre lengthRSI (défaut 12), et le RSI stochastique est calculé à l'aide du paramètre lengthStoch (défaut 12).
Lorsque le RSI stochastique est supérieur à la zone remplie de violet, c'est la zone de surachat, puis de short; lorsque le RSI stochastique est inférieur à la zone remplie de violet, c'est la zone de survente, puis de long.
En outre, la stratégie définit également la condition de filtrage de la moyenne mobile. Seulement lorsque l'EMA rapide est supérieure à l'EMA lente, vous pouvez ouvrir une position longue; seulement lorsque l'EMA rapide est inférieure à l'EMA lente, vous pouvez ouvrir une position courte.
Comparée à une seule stratégie RSI, cette stratégie combine l'indicateur stochastique pour identifier plus clairement les zones de surachat/survente, améliorant ainsi la fiabilité des signaux.
Comparée à une stratégie stochastique unique, cette stratégie utilise le RSI comme source de données d'entrée du stochastique, ce qui peut filtrer un peu de bruit et rendre le signal plus fiable.
La condition de filtrage de la moyenne mobile est réglée de manière à éviter efficacement la formation de positions contre-trend, réduisant ainsi les pertes inutiles.
Le délai d'attente de la position est réglé pour éviter d'être arrêté par de fausses ruptures.
La stratégie utilise principalement des indicateurs à court cycle, elle n'est donc adaptée qu'aux opérations à court terme et risque de ne pas bien fonctionner à long terme.
L'indicateur stochastique RSI lui-même a un certain décalage et peut manquer des signaux après des changements de prix drastiques à court terme.
Dans les marchés oscillants, le RSI stochastique peut produire de multiples pénétrations de zones de surachat/survente, ce qui peut entraîner une survente et une augmentation des coûts de transaction.
Différentes combinaisons de paramètres peuvent être testées pour optimiser davantage la longueur, les valeurs K et D du RSI stochastique.
Différents paramètres de longueur du RSI peuvent être testés pour trouver un cycle RSI plus approprié.
Essayez de le combiner avec d'autres indicateurs pour améliorer encore la précision du signal, tels que le MACD, les bandes de Bollinger, etc.
Testez différents paramètres de retard de position pour trouver un moment de sortie plus approprié.
Cet article détaille les principes de construction, les avantages, les risques et les idées d'optimisation d'une stratégie de dynamique basée sur l'indicateur stochastique RSI.
/*backtest start: 2023-11-25 00:00:00 end: 2023-12-25 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © Drun30 (Federico Magnani) //@version=4 //STRATEGIA PRINCIPALE capitaleIniziale=10000 var sizeordineInit= 50 // → % di capitale investita per ogni trade var deltaSize = 25 // → delta% di capitale investito se trade precedente è stato in perdita var sizeLimite = 100 //il trade non userà mai questa percentuale di capitale investito var sizeordine = sizeordineInit //Parametri ottimali 30 min usiShort=false usiLong=true ipercomprato=85.29 ipervenduto=30.6 // strategy("Momentum Strategy (V7.B.4)", initial_capital=capitaleIniziale, currency="USD", default_qty_type=strategy.percent_of_equity, commission_type=strategy.commission.percent, commission_value=0.1, slippage = 5, default_qty_value=sizeordineInit, overlay=false, pyramiding=0) backtest = input(title="------------------------Backtest Period------------------------", defval = false) start = timestamp(input(2020, "start year"), input(1, "start month"), input(1, "start day"), 00, 00) end = timestamp(input(0, "end year"), input(0, "end month"), input(0, "end day"), 00, 00) siamoindata=time > start?true:false if end > 0 siamoindata:=time > start and time <= end?true:false basicParameters = input(title="------------------------Basic Parameters------------------------", defval = false) smoothK = input(3, minval=1) smoothD = input(6, minval=1) lengthRSI = input(12, minval=1) src = input(close, title="RSI Source") rsi1 = rsi(src, lengthRSI) lengthStoch = input(12, minval=1) k = ema(stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK) d = ema(k, smoothD) altezzaipercomprato= input(ipercomprato, title="Overbought Height", minval=1, type=input.float) altezzaipervenduto= input(ipervenduto, title="Oversold Height", minval=1,type=input.float) BarsDelay = input(6,title="Bars delay",minval=0) GambleSizing = input(true, title = "Gamble Sizing?",type=input.bool) gambleAdd = input(deltaSize,title="Gamble Add (%)",minval=0,type=input.integer) gambleLimit = input(sizeLimite,title="Gamble MAX (%)",minval=0,type=input.integer) if GambleSizing and strategy.closedtrades[0]>strategy.closedtrades[1] if strategy.losstrades[0]>strategy.losstrades[1] and sizeordine<gambleLimit sizeordine:=sizeordine+gambleAdd if strategy.wintrades[0]>strategy.wintrades[1] sizeordine:=sizeordineInit periodomediamobile_fast = input(1, title="Fast EMA length",minval=1) periodomediamobile_slow = input(60, title="Slow EMA length",minval=1) plot(k, color=color.blue) plot(d, color=color.orange) h0 = hline(altezzaipercomprato) h1 = hline(altezzaipervenduto) fill(h0, h1, color=color.purple, transp=80) // n=input(Vicinanzadalcentro,title="Vicinanza dal centro",minval=0) //sarebbe il livello di D in cui si acquista o si vende, maggiore è la vicinanza maggiore sarà la frequenza dei trades, SE 0 è DISABILITATO // siamoinipervenduto= d<=altezzaipervenduto and d<=d[n] and d>d[1]?true:false //and d<d[3] and d>d[1] // siamoinipercomprato= d>=altezzaipercomprato and d>=d[n] and d<d[1]?true:false //and d>d[3] and d<d[1] goldencross = crossover(k,d) deathcross = crossunder(k,d) // METTI VARIABILE IN CUI AVVIENE CROSSOVER O CROSSUNDER valoreoro = valuewhen(goldencross,d,0) valoremorte = valuewhen(deathcross,d,0) siamoinipervenduto = goldencross and valoreoro<=altezzaipervenduto?true:false//d<=altezzaipervenduto?true:false siamoinipercomprato = deathcross and valoremorte>=altezzaipercomprato?true:false//d>=altezzaipercomprato?true:false long_separator = input(title="------------------------LONG------------------------", defval = usiLong) sl_long_inp = input(10, title="Stop Loss LONG %", type=input.float) tp_long_inp = input(8, title="Take Profit LONG %",type=input.float) stop_level_long = strategy.position_avg_price * (1 - (sl_long_inp/100)) //strategy.position_avg_price corrisponde al prezzo con cui si è aperta la posizione take_level_long = strategy.position_avg_price * (1 + (tp_long_inp/100)) //BINANCE JSON_long = 'OPEN LONG: PUT THE JSON HERE FOR THE API CALL' JSON_chiusura = 'CLOSE POSITION: PUT THE JSON HERE FOR THE API CALL' webhookLong = JSON_long webhookClose= JSON_chiusura trendFilterL = input(title="TREND FILTER LONG?", defval = true) EMAfast=ema(close,periodomediamobile_fast) EMAslow=ema(close,periodomediamobile_slow) siamoinuptrend_ema=EMAfast>EMAslow?true:false //close>=EMAfast and EMAfast>EMAslow siamoinuptrend = siamoinuptrend_ema // CondizioneAperturaLong = siamoinipervenduto and siamoindata // and siamoinuptrend CondizioneAperturaLong = siamoinipervenduto and siamoindata and long_separator if trendFilterL CondizioneAperturaLong := siamoinipervenduto and siamoindata and long_separator and siamoinuptrend CondizioneChiusuraLong = siamoinipercomprato and siamoindata possiamoAprireLong=0 if trendFilterL and siamoinuptrend possiamoAprireLong:=5 plot(possiamoAprireLong,color=color.green) sonPassateLeBarreG = barssince(CondizioneAperturaLong) == BarsDelay?true:false sonPassateLeBarreD = barssince(CondizioneChiusuraLong) == BarsDelay?true:false haiUnLongAncoraAperto = false haiUnLongAncoraAperto := strategy.position_size>0?true:false // Se l'ultimo valore della serie "CondizioneAperturaLong" è TRUE, allora hai un long ancora aperto // Se l'ultimo valore della serie "CondizioneAperturaLong" è FALSE, allora: // Se l'ultimo valore della serie "CondizioneChiusuraLong" è TRUE, allora NON hai un long ancora aperto // Se l'ultimo valore della serie "CondizioneChiusuraLong" è FALSE, allora restituisce l'ultimo valore della serie "haiUnLongAncoraAperto" haiUnLongAncoraAperto_float = if(haiUnLongAncoraAperto==true) 10 else 0 plot(haiUnLongAncoraAperto_float,color=color.red) //FInché la linea rossa si trova a livello "1" allora c'è un ordine long in corso quantita = (sizeordine/100*(capitaleIniziale+strategy.netprofit))/valuewhen(haiUnLongAncoraAperto==false and CondizioneAperturaLong,close,0) plot(sizeordine,color=color.purple, linewidth=3) if strategy.position_size<=0 and CondizioneAperturaLong //and sonPassateLeBarreG and haiUnLongAncoraAperto==false strategy.opentrades==0 strategy.entry("Vamonos",strategy.long, alert_message=webhookLong, comment="OPEN LONG", qty=quantita) if strategy.position_size>0 //and sonPassateLeBarreD // and CondizioneChiusuraLong if siamoinuptrend == true and sonPassateLeBarreD strategy.close("Vamonos", alert_message=webhookClose, comment="CLOSE LONG") else if siamoinuptrend == false and CondizioneChiusuraLong strategy.close("Vamonos", alert_message=webhookClose, comment="CLOSE LONG") if strategy.position_size>0 and siamoindata strategy.exit("Vamonos", stop=stop_level_long, limit=take_level_long, comment="CLOSE LONG (LIMIT/STOP)") short_separator = input(title="------------------------SHORT------------------------", defval = usiShort) sl_short_inp = input(20, title="Stop Loss SHORT %") tp_short_inp = input(35, title="Take Profit SHORT %") stop_level_short = strategy.position_avg_price * (1 + (sl_short_inp/100)) take_level_short= strategy.position_avg_price * (1 - (tp_short_inp/100)) // BINANCE JSON_short = 'OPEN SHORT: PUT THE JSON HERE FOR THE API CALL' webhookShort = JSON_short trendFilterS = input(title="TREND FILTER SHORT?", defval = true) siamoindowntrend_ema=EMAfast<EMAslow?true:false //close<=EMAfast and EMAfast<EMAslow siamoindowntrend=siamoindowntrend_ema CondizioneAperturaShort = short_separator and siamoinipercomprato and siamoindata if trendFilterS CondizioneAperturaShort:=short_separator and siamoinipercomprato and siamoindata and siamoindowntrend CondizioneChiusuraShort = siamoinipervenduto and siamoindata sonPassateLeBarreGs = barssince(CondizioneAperturaShort) == BarsDelay?true:false sonPassateLeBarreDs = barssince(CondizioneChiusuraShort) == BarsDelay?true:false haiUnoShortAncoraAperto = false haiUnoShortAncoraAperto := strategy.position_size<0?true:false haiUnoShortAncoraAperto_float = if(haiUnoShortAncoraAperto==true) 15 else 0 plot(haiUnoShortAncoraAperto_float,color=color.purple) //FInché la linea viola si trova a livello "2" allora c'è un ordine short in corso if CondizioneAperturaShort and strategy.position_size>=0 //and haiUnoShortAncoraAperto==false strategy.entry("Andale",strategy.short,alert_message=webhookShort, comment="OPEN SHORT") if strategy.position_size<0 //and sonPassateLeBarreD // and CondizioneChiusuraLong if siamoindowntrend == true and sonPassateLeBarreDs strategy.close("Andale",alert_message=webhookClose, comment="CLOSE SHORT") else if siamoindowntrend == false and CondizioneChiusuraShort strategy.close("Andale",alert_message=webhookClose, comment="CLOSE SHORT") if strategy.position_size<0 and siamoindata strategy.exit("Andale", stop=stop_level_short, limit=take_level_short, comment="CLOSE SHORT (LIMIT/STOP)")