
This strategy is a low-drawdown quantitative trading system that combines Range Filter and Average True Range (ATR). It identifies trend direction through the range filter while using ATR to dynamically adjust position size and set trailing stops, effectively controlling risk. The strategy requires price to break above or below the range filter for two consecutive periods to confirm a trend, and this dual-confirmation mechanism effectively reduces false breakouts. The system defaults to risking 1% of capital per trade, which is conservative and robust. This strategy is particularly suitable for markets with high volatility but clear trends.
The core principles of this strategy combine range filter trend identification with an ATR risk management system:
Range Filter Calculation:
Trend Confirmation Conditions:
ATR Dynamic Position Sizing:
ATR Trailing Stops:
Strong Adaptability:
Excellent Risk Control:
High Signal Quality:
Low Drawdown Characteristics:
Transparent and Customizable:
Poor Performance in Ranging Markets:
Rapid Reversal Risk:
Parameter Sensitivity:
Consecutive Loss Risk:
Slippage and Commission Impact:
Add Market Environment Filters:
Optimize Range Filter Period:
Introduce Multi-Timeframe Confirmation:
Dynamically Adjust ATR Multiplier:
Add Time-Based Exit Mechanisms:
The Dual-Confirmation Range Filter Strategy with ATR Dynamic Position Sizing and Trailing Stop System is a quantitative trading strategy focused on risk control. It identifies trend direction through the range filter, requires consecutive two-period breakouts to confirm signals, and uses ATR to dynamically adjust position size and set trailing stops, effectively controlling risk per trade within a preset percentage. The main advantages of this strategy are its strong adaptability and excellent risk control capabilities, making it particularly suitable for markets with high volatility but clear trends. The main risks come from false breakouts in ranging markets and sensitivity to parameter selection. Future optimization directions include adding market environment filters, introducing multi-timeframe analysis, and dynamically adjusting parameters. For traders pursuing a robust, low-drawdown trading style, this is a strategy framework worth considering, which can be further customized and optimized according to individual risk preferences and trading instrument characteristics.
/*backtest
start: 2025-02-01 00:00:00
end: 2025-05-25 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDT"}]
*/
//@version=5
strategy("Range Filter + ATR Strategy (Low Drawdown)", overlay=true,
pyramiding=0, default_qty_type=strategy.percent_of_equity,
default_qty_value=100, commission_type=strategy.commission.percent,
commission_value=0.1, initial_capital=10000)
// Input parameters
rangePeriod = input.int(14, title="Range Filter Period")
atrPeriod = input.int(14, title="ATR Period")
riskPercent = input.float(1.0, title="Risk % per Trade", minval=0.1, maxval=5)
useATRSizing = input(true, title="Use ATR Position Sizing")
trailATR = input(1.5, title="Trailing Stop ATR Multiple")
// Calculate Range Filter
src = close
smooth = ta.sma(src, rangePeriod)
filter = ta.sma(math.abs(src - smooth), rangePeriod)
upper = smooth + filter
lower = smooth - filter
// Calculate ATR
atr = ta.atr(atrPeriod)
// Trend direction
upTrend = src > upper and src[1] > upper[1]
downTrend = src < lower and src[1] < lower[1]
// Position sizing based on ATR
atrPositionSize = (strategy.equity * riskPercent/100) / (atr * syminfo.pointvalue)
// Strategy logic
if (upTrend)
strategy.entry("Long", strategy.long, qty=useATRSizing ? atrPositionSize : na)
if (downTrend)
strategy.entry("Short", strategy.short, qty=useATRSizing ? atrPositionSize : na)
// Corrected trailing stop using trail_offset instead of trail_points
if (strategy.position_size > 0)
strategy.exit("Long Exit", "Long", trail_price=na, trail_offset=trailATR * atr)
if (strategy.position_size < 0)
strategy.exit("Short Exit", "Short", trail_price=na, trail_offset=trailATR * atr)
// Plotting
plot(upper, color=color.green, title="Upper Range")
plot(lower, color=color.red, title="Lower Range")
plot(smooth, color=color.blue, title="Smooth Line")