Chiến lược này xác định các cơ hội đảo ngược sau các tình huống mua quá mức hoặc bán quá mức dựa trên chỉ số RSI. Nó sẽ theo dõi sự khác biệt giữa giá và RSI sau khi RSI bước vào các khu vực mua quá mức hoặc bán quá mức để xác định các cơ hội đảo ngược tiềm năng trong tương lai.
Chiến lược này sử dụng chỉ số RSI để xác định các tình huống mua quá nhiều và bán quá nhiều trên thị trường. Sau khi RSI bước vào khu vực mua quá nhiều hoặc bán quá nhiều đã được đặt trước, nó sẽ bắt đầu theo dõi các chênh lệch đảo ngược.
Cụ thể, nếu chỉ số RSI bước vào vùng mua quá mức, nó sẽ theo dõi xem giá có tiếp tục tăng (hình thành mức thấp hơn) trong khi chỉ số RSI hình thành mức thấp hơn - một sự khác biệt tăng thường xuyên; hoặc giá hình thành mức thấp hơn và chỉ số RSI hình thành mức thấp hơn
Tương tự như vậy, nếu chỉ số RSI bước vào vùng bán quá mức, nó sẽ theo dõi xem giá có tiếp tục giảm (hình thành mức cao thấp hơn) trong khi chỉ số RSI hình thành mức cao hơn
Khi các tín hiệu đảo ngược trên được phát hiện, các vị trí dài hoặc ngắn sẽ được thực hiện theo các thông số được cấu hình.
Lợi thế lớn nhất của chiến lược này là có thể xác định các tình huống thị trường cực đoan, nơi có khả năng đảo ngược cao và lợi nhuận cho các hoạt động đảo ngược lớn.
Ngoài ra, chiến lược bao gồm giám sát cho cả các sự khác biệt thường xuyên và ẩn để có thể xác định nhiều cơ hội đảo ngược hơn và những cơ hội tốt sẽ không bị bỏ lỡ do các tình huống một lần.
Rủi ro lớn nhất mà chiến lược này phải đối mặt là những tình huống mua quá mức hoặc bán quá mức cực đoan hơn, cái gọi là "trên thẳng, 90 độ xuống".
Ngoài ra, nếu các thông số không được thiết lập đúng cách và có sai lầm trong việc đánh giá tình huống mua quá mức và bán quá mức, sai lầm có thể dễ dàng xảy ra.
Cách để xử lý điều này là thiết lập một cách hợp lý giới hạn trên và dưới cho các vùng mua quá mức và bán quá mức để tránh các tình huống cực đoan.
Chiến lược có thể được tối ưu hóa trong các khía cạnh sau:
Tích hợp các chỉ số khác để xác định các điều kiện mua quá mức và bán quá mức để tránh chỉ dựa vào chỉ số RSI
Thêm logic để xác định hợp nhất trước khi phá vỡ khi xác suất đảo ngược cao hơn
Tối ưu hóa các thiết lập mục tiêu lợi nhuận sau khi đảo ngược để cho phép định hình vị trí khoa học hơn
Sử dụng các phương pháp học máy trên các năm gần đây của dữ liệu lịch sử để tự động tối ưu hóa các thông số
Cải thiện tối ưu hóa logic dừng lỗ, ví dụ: thu lợi nhuận kịp thời, dừng lỗ theo giai đoạn, dừng lỗ sau lưng vv.
Kết luận, đây là một chiến lược điều chỉnh thống kê điển hình. Nó cố gắng nắm bắt các cơ hội khi thị trường phục hồi từ các tình huống cực đoan trở lại cân bằng. So với các chiến lược theo xu hướng, nó có tỷ lệ thắng cao hơn và lợi nhuận nhưng cũng phải đối mặt với rủi ro lớn hơn. Với tối ưu hóa tham số và kiểm soát rủi ro, loại chiến lược này có thể kiếm lợi nhuận ổn định.
/*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)