
The Dynamic Price Range and RSI Divergence Trading Strategy is a comprehensive quantitative trading system that combines price range detection, RSI indicator divergence signals, and moving average trend analysis. This strategy is specifically designed for the OKX Signal Bot platform, featuring advanced functionalities such as dynamic position adjustment and partial position closing. The strategy primarily identifies price range breakout points, combines them with RSI indicator divergence signals, and filters market trends through multi-period moving averages, thereby seeking long opportunities in downtrends to achieve precise trade timing.
The uniqueness of this strategy lies in its dynamic position management system, which adjusts trading size based on the difference between the current price and the average position price. This enables the strategy to increase positions as prices continue to move favorably while gradually reducing positions when prices begin to reverse, thereby optimizing capital efficiency and risk-reward ratio.
The strategy is based on three core components working in concert:
Price Range Detection: The strategy determines the price range by calculating the highest high and lowest low within a specific period (set by the boxLength parameter). These price levels are plotted on the chart as upper and lower boundary lines, providing visual price reference ranges for trading.
RSI Divergence Detection: The strategy uses the Relative Strength Index (RSI) to calculate market momentum and detects divergence phenomena between price and RSI. Bullish divergence forms when price makes a lower low while RSI makes a higher low; bearish divergence forms when price makes a higher high while RSI makes a lower high. The strategy precisely identifies local extrema by setting left and right lookback periods (leftLookback and rightLookback).
Moving Average Trend Analysis: The strategy calculates various types of moving averages (MA20, MA50, MA100, and MA200) on a custom timeframe, determining market trends by analyzing the arrangement of these moving averages and the position of price relative to them. The strategy only triggers long signals in downtrends to ensure trades are consistent with the overall market environment.
The trading logic is as follows: - Long Signal: Triggered when price breaks through the lower boundary and RSI bullish divergence is detected, ensuring execution only under downtrend conditions. The system dynamically adjusts position size based on the difference between current price and average position price. - Position Reduction Signal: Triggered when price breaks through the upper boundary and RSI bearish divergence is detected, ensuring execution only under uptrend conditions. The system dynamically closes part of the position based on price movement relative to the average position price.
Multi-dimensional Confirmation Mechanism: Combining price range breakouts, RSI divergence signals, and moving average trend filtering creates a multi-dimensional trade confirmation system, significantly improving the reliability and precision of trading signals.
Dynamic Position Management: The strategy dynamically adjusts position size based on market conditions and price movements, rather than using fixed position allocation. This allows the strategy to maximize profit potential in favorable market environments while controlling risk under unfavorable conditions. The formula math.max(math.min(math.pow((avgPrice - close)* 1000/5,1.1), 100), minEnterPercent) ensures position adjustments are both flexible and limited.
Adaptive Market Environment: Through analysis of moving average crossovers and arrangements, the strategy can adapt to different market environments, executing trades only when technical patterns align with the overall trend.
Precise Entry and Exit Points: Divergence signals combined with price range breakouts provide precise entry and exit points, reducing the possibility of false signals. Lookback parameters (leftLookback and rightLookback) enhance the accuracy of extrema point identification.
Visual Feedback: The strategy plots price ranges, moving averages, and trade signal labels on the chart, providing intuitive visual feedback that helps traders understand and verify trading decisions.
Flexible Parameter Configuration: Multiple adjustable parameters allow the strategy to adapt to different markets and trading styles, such as RSI length, price range period, and divergence lookback period.
False Breakout Risk: Price range breakouts can sometimes be temporary rather than the start of an actual trend. This may lead to unnecessary trades and losses. Methods to reduce this risk include adding confirmation factors, such as extending lookback periods or incorporating volume confirmation.
Overtrading Risk: Dynamic position adjustment may lead to overtrading, increasing transaction costs. It is recommended to set reasonable minimum adjustment thresholds (minEnterPercent and minExitPercent) to avoid frequent trades triggered by minor price fluctuations.
Moving Average Lag Risk: Moving averages have inherent lag, especially in rapidly turning markets. This risk can be mitigated by adjusting the type of moving average used (e.g., switching from SMA to EMA) or adjusting moving average periods.
Parameter Sensitivity: The strategy relies on multiple parameters, such as RSI thresholds and moving average periods, where small changes can significantly impact strategy performance. It is recommended to backtest different parameter combinations to find robust settings and periodically re-optimize parameters to adapt to changing market conditions.
Single Market Dependency: The strategy may perform well in certain market conditions but poorly in others. It is advisable to test the strategy across different market environments and timeframes, and consider adding market state filters to pause trading during unsuitable market conditions.
Add Volume Confirmation: The current strategy relies solely on price and RSI indicators for trading decisions. Adding volume analysis can verify the validity of price range breakouts, avoiding false breakouts with insufficient volume. This can be implemented by checking whether the volume at breakout is higher than the average volume of the previous few periods.
Introduce Volatility Adjustment Mechanism: During high volatility periods, add signal filters or adjust the position sizing formula to reduce false signal risks and control maximum risk exposure. The ATR (Average True Range) indicator can be used to quantify volatility and dynamically adjust trading parameters.
Add Risk-Reward Ratio Filtering: Estimate the potential risk-reward ratio before each trade and only execute trades that meet a minimum risk-reward ratio threshold, optimizing overall strategy expected returns. This can be implemented by setting dynamic stop-loss and take-profit levels based on ATR.
Incorporate Multi-timeframe Analysis: Improve signal quality by adding trend confirmation on higher timeframes. For example, only execute trades when the daily trend aligns with the current trading timeframe trend.
Improve Dynamic Position Algorithm: The current power function may produce excessively large or small adjustments in extreme cases. Consider more complex algorithms, such as adaptive formulas based on market volatility and current profit/loss status, or introduce risk exposure limits to ensure individual trades do not excessively impact the overall portfolio.
Add Automatic Parameter Optimization: Implement automatic parameter optimization loops that periodically adjust strategy parameters based on recent market data, allowing the strategy to better adapt to changing market conditions. This can be achieved through backtesting frameworks or machine learning algorithms.
The Dynamic Price Range and RSI Divergence Trading Strategy is an advanced quantitative trading system that combines multiple technical analysis methods, integrating price ranges, RSI divergence, and moving average trends to provide a powerful trading decision framework. Its greatest advantage lies in the dynamic position management system, which automatically adjusts trading size according to market conditions, optimizing capital efficiency while maintaining risk control.
Although the strategy has some inherent risks, such as false breakouts and parameter sensitivity, through the suggested optimization directions—including adding volume confirmation, introducing volatility adjustment, and multi-timeframe analysis—the robustness and adaptability of the strategy can be further enhanced. For traders looking to deploy advanced strategies on automated trading platforms like OKX Signal Bots, this provides a flexible and powerful foundational framework that can be customized and extended according to personal trading styles and market preferences.
/*backtest
start: 2025-05-07 00:00:00
end: 2025-05-14 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=6
// Strategy: Box Range with RSI Divergence (Dynamic Adjustment - OKX Signal Format)
// © aws2333
//I'm chinese
strategy("Kaito Box with RSI Div(Dynamic Adjustment + MA + Long)", overlay=true,default_qty_type=strategy.percent_of_equity, default_qty_value=10)
rsiOverbought = 80
rsiOversold = 13
boxLength = input.int(3, title="Box Length", minval=1)
rsiLength = input.int(2, title="RSI Length", minval=1)
divergenceLookback = input.int(2, title="Divergence Lookback Period", minval=1)
leftLookback = input.int(2, title="Left Lookback", minval=1)
rightLookback = input.int(2, title="Right Lookback", minval=1)
var float avgPrice = na
//var float position_size = 0
signalToken = input.string("**********", "Signal Token")
enterOrderType = input.string("limit", "Order Type", options=["market", "limit"])
enterOrderPriceOffset = input.float(0.05, "Order Price Offset", minval=0, maxval=100, step=0.01)
enterInvestmentType = input.string("percentage_investment", "Investment Type", options=["margin", "contract", "percentage_balance", "percentage_investment"])
exitOrderType = input.string("limit", "Order Type", options=["market", "limit"])
exitOrderPriceOffset = input.float(0.05, "Order Price Offset", minval=0, maxval=100, step=0.01)
exitInvestmentType = input.string("percentage_position", "Investment Type", options=["percentage_position"])
maxLag = input.float(30, "maxLag")
minEnterPercent = 1.3
minExitPercent = 0.09
highestHigh = ta.highest(high, boxLength)
lowestLow = ta.lowest(low, boxLength)
plot(highestHigh, title="Upper Box", color=color.new(color.green, 0), linewidth=1, style=plot.style_line)
plot(lowestLow, title="Lower Box", color=color.new(color.red, 0), linewidth=1, style=plot.style_line)
rsi = ta.rsi(low, rsiLength)
isLowestLeft = low < ta.lowest(low[1], leftLookback)
isLowestRight = low <= ta.lowest(low, rightLookback)
isLowestClose = isLowestLeft and isLowestRight
isHighestLeft = low > ta.highest(low[1], leftLookback)
isHighestRight = low >= ta.highest(low, rightLookback)
isHighestClose = isHighestLeft and isHighestRight
lowestClose = ta.lowest(low, divergenceLookback)
lowestRsi = ta.lowest(rsi, divergenceLookback)
highestClose = ta.highest(low, divergenceLookback)
highestRsi = ta.highest(rsi, divergenceLookback)
lowestClosePrev = ta.lowest(low[1], leftLookback)
lowestRsiPrev = ta.lowest(rsi[1], leftLookback)
highestClosePrev = ta.highest(low[1], leftLookback)
highestRsiPrev = ta.highest(rsi[1], leftLookback)
bullishDivergence = isLowestClose and (low < lowestClosePrev) and (rsi > lowestRsiPrev) and (rsi < rsiOversold)
bearishDivergence = isHighestClose and (low > highestClosePrev) and (rsi < highestRsiPrev) and (rsi > rsiOverbought)
ma(source, length, type) =>
type == "SMA" ? ta.sma(source, length) :type == "EMA" ? ta.ema(source, length) :type == "SMMA (RMA)" ? ta.rma(source, length) :type == "WMA" ? ta.wma(source, length) :type == "VWMA" ? ta.vwma(source, length) :na
custom_timeframe = input.timeframe("3", "Custom time period (leave blank for current period)")
ma_type = input.string("SMA", "Moving average type", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"])
ma20_period = input.int(20, "MA20 ", minval=1)
ma50_period = input.int(50, "MA50 ", minval=1)
ma100_period = input.int(100, "MA100 ", minval=1)
ma200_period = input.int(200, "MA200 ", minval=1)
source_close = request.security(syminfo.tickerid, custom_timeframe, close)
ma20 = ma(source_close, ma20_period, ma_type)
ma50 = ma(source_close, ma50_period, ma_type)
ma100 = ma(source_close, ma100_period, ma_type)
ma200 = ma(source_close, ma200_period, ma_type)
up_signal_1 = ma20 > ma200
up_signal_2 = ma50 > ma200
up_signal_3 = ma100 > ma200
up_signal_4 = (high > ma20 and high > ma50 and high > ma100 and high > ma200)
up_trend = (up_signal_1 and up_signal_2 and up_signal_3 and (source_close > ma200)) or up_signal_4
down_signal_1 = ma20 < ma200
down_signal_2 = ma50 < ma200
down_signal_3 = ma100 < ma200
down_signal_4 = (low < ma20 and low < ma50 and low < ma100 and low < ma200)
down_trend = (down_signal_1 and down_signal_2 and down_signal_3 and (source_close < ma200)) or down_signal_4
plot(ma20, color=color.yellow, title="MA20")
plot(ma50, color=color.orange, title="MA50")
plot(ma100, color=color.red, title="MA100")
plot(ma200, color=color.maroon, title="MA200")
var float longAddPercent = na
var float shortAddPercent = na
roundToFourDecimals(value) => math.round(value * 10000) / 10000
if not na(avgPrice)
if close < avgPrice
longAddPercent := roundToFourDecimals(math.max(math.min(math.pow((avgPrice - close)* 1000/5,1.1) , 100), minEnterPercent))
if close > avgPrice
longAddPercent := 1
if close == avgPrice
longAddPercent := 1
if not na(avgPrice)
if close < avgPrice
shortAddPercent := 0.01
if close > avgPrice
shortAddPercent := roundToFourDecimals(math.max(math.min(math.pow((close - avgPrice)*1000,1.1), 100), minExitPercent))
if close == avgPrice
longAddPercent := 1
longSignal = (close <= lowestLow) and bullishDivergence
shortSignal = (close >= highestHigh) and bearishDivergence
plotLongSignal = down_trend and longSignal and close < avgPrice
plotShortSignal = up_trend and shortSignal and close > avgPrice
if plotLongSignal
label.new(bar_index, avgPrice, "average price: " + str.tostring(avgPrice, "#.####"), style=label.style_label_up, color=color.green, textcolor=color.white )
if plotShortSignal
label.new(bar_index, avgPrice,"average price: " + str.tostring(avgPrice, "#.####"), style=label.style_label_down, color=color.red, textcolor=color.white)
if plotLongSignal
label.new(
bar_index,
close,
"LONG :" + str.tostring(longAddPercent, "#.####") + "%, Close: " + str.tostring(close, "#.####"),
style=label.style_label_up,
color=color.new(color.green, 80),
textcolor=color.white
)
if plotShortSignal
label.new(
bar_index,
close,
"EXIT LONG :" + str.tostring(shortAddPercent, "#.####") + "%, Close: " + str.tostring(close, "#.####"),
style=label.style_label_down,
color=color.new(color.red, 80),
textcolor=color.white
)
if longSignal
avgPrice := na(avgPrice) ? close : (avgPrice + close) / 2
if down_trend and longSignal
strategy.entry("Long",strategy.long,qty=longAddPercent )
var float close_size = na
if up_trend and shortSignal
if strategy.position_size > 0
close_size := strategy.position_size * (shortAddPercent/100)
strategy.order("Partial Close Long", strategy.short, close_size)