
The RSI and Stochastic RSI Divergence Trading Strategy is an advanced technical analysis approach designed to identify key reversal points in markets. This strategy combines the power of the Relative Strength Index (RSI) and Stochastic Relative Strength Index (SRSI) by monitoring divergences between price and these momentum indicators to predict potential trend changes. Additionally, the strategy incorporates an Exponential Moving Average (EMA) as a trend filter and applies precise swing distance filters to ensure it captures meaningful market structure changes rather than market noise.
The core principle of this strategy is based on the concept of divergence in technical analysis. Divergence occurs when price movement is inconsistent with technical indicator movement, typically suggesting that the current trend may be about to reverse. The strategy focuses on four types of divergences:
The strategy employs strict filtering conditions to ensure the quality of divergence signals: - Uses a lookback period (default 40 periods) to find significant swing points - Requires a minimum swing distance percentage (default 1.5%) to filter out minor fluctuations - Requires a minimum price move percentage from the last swing (default 0.5%)
When a divergence is detected, the strategy plots labels and connecting lines on the chart, allowing traders to visually identify these key signals. And the strategy automatically generates long and short entry signals based on the divergence signals.
To mitigate these risks, it is recommended to: - Combine divergence signals with other technical indicators or analysis methods, such as support/resistance levels, candlestick patterns, or volume analysis - Test and optimize parameter settings in different market conditions - Implement appropriate money management and stop-loss strategies - Consider the significance of divergence signals in the context of the overall market trend
The RSI and Stochastic RSI Divergence Trading Strategy is a sophisticated and powerful technical analysis tool capable of capturing potential market reversals and trend continuation signals by identifying discrepancies between price and momentum indicators. By integrating both regular and hidden divergence detection and applying carefully designed filters, the strategy provides a comprehensive approach to identifying high-probability trading opportunities.
However, like all technical analysis methods, this strategy has limitations and risks. By implementing the suggested optimizations, such as adding risk management mechanisms, improving signal confirmation, and incorporating dynamic parameter adjustments, the strategy’s robustness and performance can be significantly enhanced.
Ultimately, this strategy is best suited as part of a broader trading system, combined with other analytical tools and proper money management principles. For traders who understand technical analysis and market structure, this divergence strategy can be a valuable tool for discovering high-quality trade setups.
/*backtest
start: 2024-06-26 00:00:00
end: 2025-06-24 08:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("RSI Divergence Strategy", overlay=true)
//strategy("RSI & SRSI Divergence Strategy with EMA & Min Swing Filter + Price Chart Lines", overlay=true)
rsiLength = input.int(14, title="RSI Length")
srsiLength = input.int(14, title="Stochastic RSI Length")
kLength = input.int(3, title="%K Length")
dLength = input.int(3, title="%D Length")
emaLength = input.int(200, title="EMA Length")
lookback = input.int(40, title="Lookback Period for Divergence")
minSwingDistPercent = input.float(1.5, title="Minimum Swing Distance (%)")
minPriceMovePercent = input.float(0.5, title="Minimum Price Move from Last Swing (%)")
rsi = ta.rsi(close, rsiLength)
srsi = ta.stoch(rsi, rsi, rsi, srsiLength)
k = ta.sma(srsi, kLength)
d = ta.sma(k, dLength)
ema200 = ta.ema(close, emaLength)
// === Bullish Regular Divergence ===
var float lastLowPrice = na
var float lastLowRsi = na
var float lastLowSrsi = na
var int lastLowIndex = na
bullishDiv = false
if ta.lowestbars(low, lookback) == 0
if not na(lastLowPrice) and not na(lastLowRsi) and not na(lastLowSrsi)
swingDistLow = math.abs(low - lastLowPrice) / lastLowPrice * 100
priceMoveLow = math.abs(low - lastLowPrice) / lastLowPrice * 100
if swingDistLow >= minSwingDistPercent and priceMoveLow >= minPriceMovePercent
if (low < lastLowPrice and rsi > lastLowRsi) or (low < lastLowPrice and k > lastLowSrsi)
bullishDiv := true
lastLowPrice := low
lastLowRsi := rsi
lastLowSrsi := k
lastLowIndex := bar_index
else
lastLowPrice := low
lastLowRsi := rsi
lastLowSrsi := k
lastLowIndex := bar_index
// === Bearish Regular Divergence ===
var float lastHighPrice = na
var float lastHighRsi = na
var float lastHighSrsi = na
var int lastHighIndex = na
bearishDiv = false
if ta.highestbars(high, lookback) == 0
if not na(lastHighPrice) and not na(lastHighRsi) and not na(lastHighSrsi)
swingDistHigh = math.abs(high - lastHighPrice) / lastHighPrice * 100
priceMoveHigh = math.abs(high - lastHighPrice) / lastHighPrice * 100
if swingDistHigh >= minSwingDistPercent and priceMoveHigh >= minPriceMovePercent
if (high > lastHighPrice and rsi < lastHighRsi) or (high > lastHighPrice and k < lastHighSrsi)
bearishDiv := true
lastHighPrice := high
lastHighRsi := rsi
lastHighSrsi := k
lastHighIndex := bar_index
else
lastHighPrice := high
lastHighRsi := rsi
lastHighSrsi := k
lastHighIndex := bar_index
// === Bullish Hidden Divergence ===
bullishHiddenDiv = false
if ta.lowestbars(low, lookback) == 0
if not na(lastLowPrice) and not na(lastLowRsi) and not na(lastLowSrsi)
swingDistLowHidden = math.abs(low - lastLowPrice) / lastLowPrice * 100
priceMoveLowHidden = math.abs(low - lastLowPrice) / lastLowPrice * 100
if swingDistLowHidden >= minSwingDistPercent and priceMoveLowHidden >= minPriceMovePercent
if (low > lastLowPrice and rsi < lastLowRsi) or (low > lastLowPrice and k < lastLowSrsi)
bullishHiddenDiv := true
// === Bearish Hidden Divergence ===
bearishHiddenDiv = false
if ta.highestbars(high, lookback) == 0
if not na(lastHighPrice) and not na(lastHighRsi) and not na(lastHighSrsi)
swingDistHighHidden = math.abs(high - lastHighPrice) / lastHighPrice * 100
priceMoveHighHidden = math.abs(high - lastHighPrice) / lastHighPrice * 100
if swingDistHighHidden >= minSwingDistPercent and priceMoveHighHidden >= minPriceMovePercent
if (high < lastHighPrice and rsi > lastHighRsi) or (high < lastHighPrice and k > lastHighSrsi)
bearishHiddenDiv := true
// === PLOTS ===
plot(ema200, title="EMA 200", color=color.purple, linewidth=2)
// === STRATEGY ENTRIES ===
if bullishDiv or bullishHiddenDiv
strategy.entry("Long", strategy.long)
if bearishDiv or bearishHiddenDiv
strategy.entry("Short", strategy.short)