Эта стратегия определяет возможности реверсии после ситуации перекупления или перепродажи на основе индикатора RSI. Она будет отслеживать расхождение между ценой и RSI после того, как RSI входит в зоны перекупления или перепродажи, чтобы определить потенциальные будущие шансы на реверсию.
Эта стратегия использует индикатор RSI для определения ситуации с перекуплением и перепродажей на рынке. После того, как RSI войдет в заранее установленную зону перекупления или перепродажи, он начнет отслеживать дивергенции реверсии.
В частности, если RSI входит в зону перекупленности, он будет отслеживать, продолжает ли цена расти (образуя более высокие минимумы), в то время как RSI формирует более низкие минимумы - регулярное бычье расхождение; или цена формирует более низкие минимумы и RSI формирует более высокие минимумы
Аналогичным образом, если RSI входит в зону перепроданности, он будет контролировать, продолжает ли цена падать (образуя более низкие максимумы), в то время как RSI формирует более высокие максимумы
После обнаружения вышеперечисленных сигналов обратного движения будут заняты длинные или короткие позиции в соответствии с настроенными параметрами.
Наибольшее преимущество этой стратегии заключается в том, что она позволяет выявлять экстремальные рыночные ситуации, когда вероятность обратного движения высока, а прибыль от обратных операций большая.
Кроме того, стратегия включает мониторинг как регулярных, так и скрытых расхождений, чтобы было возможно выявление большего количества возможностей для обращения и не упустить хорошие возможности из-за разовых ситуаций.
Наибольший риск, с которым эта стратегия сталкивается, заключается в еще более экстремальных ситуациях перекупки или перепродажи, так называемых "прямо вверх, 90 градусов вниз".
Кроме того, если параметры не установлены должным образом и есть ошибки в оценке ситуаций перекупки и перепродажи, ошибки могут легко произойти.
Способ решения этой проблемы заключается в разумном установлении верхних и нижних пределов для зон перекупления и перепродажи, чтобы избежать чрезмерных экстремальных ситуаций.
Стратегия может быть оптимизирована в следующих аспектах:
Включить другие показатели для определения условий перекупления и перепродажи, чтобы избежать полагаться исключительно на RSI
Добавить логику для выявления консолидации до вырыва, когда вероятность отмены выше
Оптимизировать настройки целевых показателей прибыли после отмены, чтобы обеспечить более научное определение размеров позиций
Использование методов машинного обучения на последних годах исторических данных для автоматической оптимизации параметров
Улучшить оптимизацию логики стоп-лосса, например, своевременное получение прибыли, отсроченный стоп-лосс, отсроченный стоп-лосс и т.д.
В заключение, это типичная стратегия статистического арбитража. Она пытается поймать возможности, когда рынок восстанавливается из экстремальных ситуаций обратно в равновесие. По сравнению со стратегиями, следующими за трендом, она имеет более высокие показатели выигрыша и рентабельность, но также сталкивается с большими рисками. С оптимизацией параметров и контролем рисков этот тип стратегий может приносить стабильную прибыль.
/*backtest start: 2023-01-01 00:00:00 end: 2024-01-07 00:00:00 period: 1d basePeriod: 1h 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/ // made by Imal_Max // thanks to neo the crypto trader's idea // // thanks to JayTradingCharts RSI Divergence /w Alerts indicator for the base code. // we modified this to detect the divergence only if price was oversold or overbought recently and a few more settings // also now you can backtest the settings easy //@version=5 // 🔥 comment out the line below to disable the alerts and enable the backtester //indicator(title="RSI Divergence Indicator with Alerts Overbought Oversold", shorttitle="RSI OB/OS Divergence", format=format.price, timeframe="") // 🔥 uncomment the line below to enable the backtester + uncomment the lines slightly below and at the bottom of the script strategy(title="RSI Divergence Indicator with Alerts Overbought Oversold", shorttitle="RSI OB/OS Divergence", overlay=true) len = input.int(title='RSI Period', minval=1, defval=14, group='regular RSI settings') src = input.source(title='RSI Source', defval=close, group='regular RSI settings') lbR = input.int(title='Pivot Lookback Right', defval=5, group='regular RSI settings') lbL = input.int(title='Pivot Lookback Left', defval=5, group='regular RSI settings') rangeUpper = input.int(title='Max of Lookback Range', defval=60, group='regular RSI settings') rangeLower = input.int(title='Min of Lookback Range', defval=5, group='regular RSI settings') plotBull = input.bool(title='Plot Bullish', defval=true, group='regular RSI settings') plotHiddenBull = input.bool(title='Plot Hidden Bullish', defval=true, group='regular RSI settings') plotBear = input.bool(title='Plot Bearish', defval=true, group='regular RSI settings') plotHiddenBear = input.bool(title='Plot Hidden Bearish', defval=true, group='regular RSI settings') // ob/os divergence settings obvalue = input.int(title='OB RSI Value', defval=70, group='look for RSI divergence after OverBought/OverSold', inline='Input 0', tooltip="min RSI Level needed within lookback period to look for bullish divergences") oblookback = input.int(title='OB lookback period', defval=30, group='look for RSI divergence after OverBought/OverSold', inline='Input 0') osvalue = input.int(title='OS RSI Value', defval=35, group='look for RSI divergence after OverBought/OverSold', inline='Input 1', tooltip="max RSI Level needed within lookback period to look for bearish divergences") oslookback = input.int(title='OS lookback period', defval=30, group='look for RSI divergence after OverBought/OverSold', inline='Input 1') minBearRSI = input.int(title='min RSI for bear Alerts', defval=60, group='look for RSI divergence after OverBought/OverSold', tooltip="min RSI needed at the time where bearish divergence gets detected") maxBullRSI = input.int(title='max RSI for Bull Alerts', defval=50, group='look for RSI divergence after OverBought/OverSold', tooltip="max RSI needed at the time where bullish divergence gets detected") // Backtesteer Info enableBacktesterInfo = input(true, title="to enable the Backtester, uncomment/comment the 🔥 lines in the source code", group='enable Backtester') // Backtester input stuff // long settings - 🔥 uncomment the 3 lines below to disable the alerts and enable the backtester longTrading = input(true, title="enable Long Backtester (to disable uncheck 'plot Bullish' and 'plot hidden Bullish as well')", group='Long Backtester') longStopLoss = input.float(0.5, title='Stop Loss %', group='Long Backtester') / 100 longTakeProfit = input.float(2.0, title='Take Profit %', group='Long Backtester') / 100 // short settings - 🔥 uncomment the 3 lines below to disable the alerts and enable the backtester shortTrading = input(true, title="enable Short Backtester (to disable uncheck 'plot Bearish' and 'plot hidden Bearish as well'", group='Short Backtester') shortStopLoss = input.float(0.5, title='Stop Loss %', group='Short Backtester') / 100 shortTakeProfit = input.float(2.0, title='Take Profit %', group='Short Backtester') / 100 // Backtesting Range settings - 🔥 uncomment the 6 lines below to disable the alerts and enable the backtester startDate = input.int(title='Start Date', defval=1, minval=1, maxval=31, group='Backtesting range') startMonth = input.int(title='Start Month', defval=1, minval=1, maxval=12, group='Backtesting range') startYear = input.int(title='Start Year', defval=2016, minval=1800, maxval=2100, group='Backtesting range') endDate = input.int(title='End Date', defval=1, minval=1, maxval=31, group='Backtesting range') endMonth = input.int(title='End Month', defval=1, minval=1, maxval=12, group='Backtesting range') endYear = input.int(title='End Year', defval=2040, minval=1800, maxval=2100, group='Backtesting range') bearColor = color.red bullColor = color.green hiddenBullColor = color.new(color.green, 80) hiddenBearColor = color.new(color.red, 80) textColor = color.white noneColor = color.new(color.white, 100) osc = ta.rsi(src, len) plot(osc, title='RSI', linewidth=2, color=color.new(#00bcd4, 0)) obLevel = hline(obvalue, title='Overbought', linestyle=hline.style_dotted) osLevel = hline(osvalue, title='Oversold', linestyle=hline.style_dotted) minRSIline = hline(minBearRSI, title='max RSI for Bull divergence', linestyle=hline.style_dotted) maxRSIline = hline(maxBullRSI, title='max RSI for Bull divergence', linestyle=hline.style_dotted) fill(obLevel, minRSIline, title='Bear Zone Background', color=color.new(#f44336, 90)) fill(osLevel, maxRSIline, title='Bull Zone Background', color=color.new(#4caf50, 90)) RSI0line = hline(0, title='RSI 0 Line', linestyle=hline.style_dotted) RSI100line = hline(100, title='RSI 100 Line', linestyle=hline.style_dotted) fill(obLevel, RSI100line, title='Overbought Zone Background', color=color.new(#e91e63, 75)) fill(osLevel, RSI0line, title='Oversold Zone Background', color=color.new(#4caf50, 75)) plFound = na(ta.pivotlow(osc, lbL, lbR)) ? false : true phFound = na(ta.pivothigh(osc, lbL, lbR)) ? false : true _inRange(cond) => bars = ta.barssince(cond == true) rangeLower <= bars and bars <= rangeUpper // check if RSI was OS or OB recently obHighestRsi = ta.highest(osc, oblookback) osLowestRsi = ta.lowest(osc, oslookback) //------------------------------------------------------------------------------ // Regular Bullish // Osc: Higher Low oscHL = osc[lbR] > ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1]) // Price: Lower Low priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1) bullCond = plotBull and priceLL and oscHL and plFound and osLowestRsi < osvalue and osc < maxBullRSI plot(plFound ? osc[lbR] : na, offset=-lbR, title='Regular Bullish', linewidth=2, color=bullCond ? bullColor : noneColor, transp=0) plotshape(bullCond ? osc[lbR] : na, offset=-lbR, title='Regular Bullish Label', text=' Bull ', style=shape.labelup, location=location.absolute, color=bullColor, textcolor=textColor, transp=0) //------------------------------------------------------------------------------ // Hidden Bullish // Osc: Lower Low oscLL = osc[lbR] < ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1]) // Price: Higher Low priceHL = low[lbR] > ta.valuewhen(plFound, low[lbR], 1) hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound and osLowestRsi < osvalue and osc < maxBullRSI plot(plFound ? osc[lbR] : na, offset=-lbR, title='Hidden Bullish', linewidth=2, color=hiddenBullCond ? hiddenBullColor : noneColor, transp=0) plotshape(hiddenBullCond ? osc[lbR] : na, offset=-lbR, title='Hidden Bullish Label', text=' H Bull ', style=shape.labelup, location=location.absolute, color=bullColor, textcolor=textColor, transp=0) //------------------------------------------------------------------------------ // Regular Bearish // Osc: Lower High oscLH = osc[lbR] < ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1]) // Price: Higher High priceHH = high[lbR] > ta.valuewhen(phFound, high[lbR], 1) bearCond = plotBear and priceHH and oscLH and phFound and obHighestRsi > obvalue and osc > minBearRSI plot(phFound ? osc[lbR] : na, offset=-lbR, title='Regular Bearish', linewidth=2, color=bearCond ? bearColor : noneColor, transp=0) plotshape(bearCond ? osc[lbR] : na, offset=-lbR, title='Regular Bearish Label', text=' Bear ', style=shape.labeldown, location=location.absolute, color=bearColor, textcolor=textColor, transp=0) //------------------------------------------------------------------------------ // Hidden Bearish // Osc: Higher High oscHH = osc[lbR] > ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1]) // Price: Lower High priceLH = high[lbR] < ta.valuewhen(phFound, high[lbR], 1) hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound and obHighestRsi > obvalue and osc > minBearRSI plot(phFound ? osc[lbR] : na, offset=-lbR, title='Hidden Bearish', linewidth=2, color=hiddenBearCond ? hiddenBearColor : noneColor, transp=0) plotshape(hiddenBearCond ? osc[lbR] : na, offset=-lbR, title='Hidden Bearish Label', text=' H Bear ', style=shape.labeldown, location=location.absolute, color=bearColor, textcolor=textColor, transp=0) alertcondition(bullCond, title='Bullish divergence', message='Regular Bull Div {{ticker}} XXmin') alertcondition(bearCond, title='Bearish divergence', message='Regular Bear Div {{ticker}} XXmin') alertcondition(hiddenBullCond, title='Hidden Bullish divergence', message='Hidden Bull Div {{ticker}} XXmin') alertcondition(hiddenBearCond, title='Hidden Bearish divergence', message='Hidden Bear Div {{ticker}} XXmin') // 🔥 uncomment the all lines below for the backtester and revert for alerts longTP = strategy.position_size > 0 ? strategy.position_avg_price * (1 + longTakeProfit) : strategy.position_size < 0 ? strategy.position_avg_price * (1 - longTakeProfit) : na longSL = strategy.position_size > 0 ? strategy.position_avg_price * (1 - longStopLoss) : strategy.position_size < 0 ? strategy.position_avg_price * (1 + longStopLoss) : na shortTP = strategy.position_size > 0 ? strategy.position_avg_price * (1 + shortTakeProfit) : strategy.position_size < 0 ? strategy.position_avg_price * (1 - shortTakeProfit) : na shortSL = strategy.position_size > 0 ? strategy.position_avg_price * (1 - shortStopLoss) : strategy.position_size < 0 ? strategy.position_avg_price * (1 + shortStopLoss) : na strategy.risk.allow_entry_in(longTrading == true and shortTrading == true ? strategy.direction.all : longTrading == true ? strategy.direction.long : shortTrading == true ? strategy.direction.short : na) strategy.entry('Bull', strategy.long, comment='Long', when=bullCond) strategy.entry('Bull', strategy.long, comment='Long', when=hiddenBullCond) strategy.entry('Bear', strategy.short, comment='Short', when=bearCond) strategy.entry('Bear', strategy.short, comment='Short', when=hiddenBearCond) strategy.exit(id='longTP-SL', from_entry='Bull', limit=longTP, stop=longSL) strategy.exit(id='shortTP-SL', from_entry='Bear', limit=shortTP, stop=shortSL)