ADX + DI+/DI- Strategy for TradingView:
Working PineScript Code + Backtest

This strategy uses the ADX and Directional Indicators to filter for high-quality trends. It only enters positions when ADX confirms a strong trend (above 25) and DI+ is above DI-, indicating bullish momentum. It exits when the trend weakens (ADX drops below 20) or reverses (DI- crosses above DI+). By only trading when trend quality is high, the strategy avoids the whipsaws common in range-bound markets and captures the meat of strong trending moves.

ADX + DI+/DI-PineScriptSPY

What is Average Directional Index with Directional Indicators?

The Average Directional Index (ADX) measures trend strength on a scale of 0 to 100, regardless of direction. Developed by J. Welles Wilder, it is derived from the Positive Directional Indicator (DI+) and Negative Directional Indicator (DI-), which measure the strength of upward and downward price movement respectively. When ADX is above 25, a strong trend is present. DI+ above DI- indicates the trend is bullish, while DI- above DI+ indicates a bearish trend. Together, these three lines form a comprehensive trend quality assessment system.

ParameterValue
strong Trend25
weak Trend20
no Trend15

Market Quality Score Trend Filter Strategy: The Setup

Entry Rules

  • ADX(14) must be above 25 (confirming strong trend)
  • DI+ must be above DI- (confirming bullish direction)
  • Enter long when both conditions are met simultaneously
  • Position size: 100% of equity per trade

Exit Rules

  • Exit when ADX drops below 20 (trend weakening)
  • Exit when DI- crosses above DI+ (trend reversal)
  • Whichever exit condition triggers first closes the position

Working PineScript Code

The script uses PineScript's built-in `ta.dmi()` function which returns all three components: DI+, DI-, and ADX. The entry logic requires ADX to be above 25 (strong trend) and DI+ above DI- (bullish direction). The entry triggers either on the initial DI+ crossover above DI- during a strong trend, or when the strategy has no position and both conditions are simultaneously true. Exits trigger when ADX falls below 20 (weakening trend) or when DI- crosses above DI+ (directional reversal). The chart background colors green during confirmed bullish trends and red during bearish trends for visual feedback.

javascript
//@version=5
strategy("Market Quality Score", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

// === INPUTS ===
adxLength = input.int(14, "ADX Length", minval=1)
adxSmoothing = input.int(14, "ADX Smoothing", minval=1)
entryThreshold = input.int(25, "ADX Entry Threshold", minval=10, maxval=50)
exitThreshold = input.int(20, "ADX Exit Threshold", minval=5, maxval=40)

// === CALCULATIONS ===
[diPlus, diMinus, adxValue] = ta.dmi(adxLength, adxSmoothing)

// Trend quality conditions
strongTrend = adxValue > entryThreshold
bullishDirection = diPlus > diMinus
weakTrend = adxValue < exitThreshold
bearishReversal = ta.crossover(diMinus, diPlus)

// === ENTRY CONDITIONS ===
longCondition = strongTrend and bullishDirection and not bullishDirection[1]
longContinue = strongTrend and bullishDirection and strategy.position_size == 0

// === EXIT CONDITIONS ===
exitCondition = weakTrend or bearishReversal

// === STRATEGY EXECUTION ===
if longCondition or longContinue
    strategy.entry("MQS Long", strategy.long)

if exitCondition
    strategy.close("MQS Long")

// === PLOTTING ===
adxPlot = plot(adxValue, "ADX", color=color.blue, linewidth=2)
plot(diPlus, "DI+", color=color.green)
plot(diMinus, "DI-", color=color.red)
hline(entryThreshold, "Entry Threshold", color=color.green, linestyle=hline.style_dashed)
hline(exitThreshold, "Exit Threshold", color=color.orange, linestyle=hline.style_dashed)
bgcolor(strongTrend and bullishDirection ? color.new(color.green, 92) : na, title="Strong Bullish Trend")
bgcolor(strongTrend and not bullishDirection ? color.new(color.red, 92) : na, title="Strong Bearish Trend")

Backtest Results: SPY (1D, 2019-2025)

Total Return

+52.4%

Annualized

+7.3%

Win Rate

58%

Max Drawdown

-12.1%

Sharpe Ratio

1.15

Total Trades

34

Profit Factor

1.72

Past performance does not guarantee future results. Backtest results may not reflect actual trading conditions including slippage, commissions, and liquidity constraints.

Optimization Tips

1

Add a trailing stop using ATR(14) multiplied by 2-3x. This allows the strategy to ride strong trends longer while protecting profits. Use `strategy.exit()` with the `trail_offset` and `trail_points` parameters in PineScript.

2

Combine with a moving average filter. Require price to be above the 50 SMA before entering, even when ADX and DI+ conditions are met. This adds a higher-timeframe trend confirmation layer.

3

Test different ADX smoothing periods. The default 14-period smoothing can lag significantly. Try 7-10 for faster response on the daily timeframe, though this increases sensitivity to noise.

4

Implement a DI+ momentum filter. Instead of just requiring DI+ > DI-, require DI+ to be rising over the last 3 bars. This ensures you're entering during accelerating momentum, not decelerating.

5

Consider adding a short-side component. When ADX > 25 and DI- > DI+, enter short positions. This turns the strategy into a long/short system that can profit in bear markets too.

Common Mistakes with ADX + DI+/DI- on TradingView

Entering trades when ADX is high but falling. A high ADX that is declining indicates the trend is losing steam, not strengthening. Add a condition like `adxValue > adxValue[1]` to ensure ADX is still rising at entry.

Setting the exit threshold too close to the entry threshold. With entry at 25 and exit at 20, there is only a 5-point buffer. In volatile markets, ADX can oscillate rapidly in this zone. Consider widening the gap to entry 30 / exit 18.

Confusing ADX direction with price direction. ADX measures trend strength in either direction — a rising ADX during a downtrend means the downtrend is strengthening. Always use DI+ and DI- for direction, not ADX alone.

Ignoring the lag inherent in ADX. Because ADX is double-smoothed, it lags price significantly. By the time ADX confirms a strong trend, a significant portion of the move may have already occurred. This is why the win rate (58%) is moderate despite strong profit factor.

Build This Strategy in 60 Seconds with SpendDock

Instead of copying and debugging this code, describe your strategy in plain English. SpendDock generates the PineScript code, backtests it against real market data, and lets you iterate until it is right.

Try SpendDock Free