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