Trading Strategy
ADX Strategy
A trend strength indicator that measures the strength of a trend regardless of its direction, combined with Directional Movement indicators.
The Strength of the Trend
The Average Directional Index (ADX) quantifies trend strength, while +DI and -DI identify directional momentum. By combining ADX threshold filtering with the 200 EMA trend filter, this strategy ensures you only trade when the market has sufficient strength, avoiding whipsaws in ranging markets.
Trend Strength Type
4h Chart Timeframe
Intermediate Complexity
Trending Best Market
Signal Logic
Bullish (+DI Cross)
Triggered when +DI crosses above -DI with ADX above threshold (25), provided price is above the 200 EMA trend filter.
Bearish (-DI Cross)
Triggered when -DI crosses above +DI with ADX above threshold (25), provided price is below the 200 EMA trend filter.
Implementation
//@version=6
strategy("ADX Strategy [Fixed]", overlay=true, initial_capital=1000000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// ==========================================
// 🔹 INPUTS
// ==========================================
// Group: ADX Settings
grp_adx = "ADX Settings"
adx_len = input.int(14, "ADX Smoothing", minval=1, group=grp_adx)
adx_thresh = input.int(25, "ADX Threshold", minval=0, maxval=100, group=grp_adx)
// Group: DI Settings
grp_di = "Directional Index Settings"
di_len = input.int(14, "DI Length", minval=1, group=grp_di)
// Group: Trend Filter
grp_trend = "Trend Filter"
use_trend = input.bool(true, "Use Trend Filter (EMA 200)", group=grp_trend)
ema_len = input.int(200, "Trend EMA Length", minval=1, group=grp_trend)
// Group: Risk Management (ATR)
grp_risk = "Risk Management"
atr_len = input.int(14, "ATR Length", minval=1, group=grp_risk)
sl_mult = input.float(2.0, "Stop Loss (ATR Multiplier)", step=0.1, group=grp_risk)
tp_ratio = input.float(2.5, "Risk:Reward Ratio", step=0.1, group=grp_risk)
// ==========================================
// 🔹 CALCULATIONS
// ==========================================
// ADX, +DI, -DI calculations
// ta.dmi() returns a tuple: [diPlus, diMinus, adx]
[plus_di, minus_di, adx_val] = ta.dmi(di_len, adx_len)
// Trend EMA
ema_val = ta.ema(close, ema_len)
// ATR for risk management
atr_val = ta.atr(atr_len)
// Trend Conditions
is_uptrend = use_trend ? close > ema_val : true
is_downtrend = use_trend ? close < ema_val : true
// ==========================================
// 🔹 STRATEGY LOGIC
// ==========================================
// Long Entry:
// 1. Strong trend (ADX > threshold)
// 2. Uptrend (Price > EMA) if filter enabled
// 3. +DI crosses above -DI (momentum shifting bullish)
long_signal = is_uptrend and (adx_val > adx_thresh) and ta.crossover(plus_di, minus_di)
// Short Entry:
// 1. Strong trend (ADX > threshold)
// 2. Downtrend (Price < EMA) if filter enabled
// 3. -DI crosses above +DI (momentum shifting bearish)
short_signal = is_downtrend and (adx_val > adx_thresh) and ta.crossover(minus_di, plus_di)
// ==========================================
// 🔹 EXECUTION & RISK MANAGEMENT
// ==========================================
if long_signal
strategy.entry("Long", strategy.long, comment="L | ADX Bull")
if short_signal
strategy.entry("Short", strategy.short, comment="S | ADX Bear")
// Dynamic ATR-based exits
strategy.exit("Exit Long", "Long", stop=strategy.position_avg_price - (atr_val * sl_mult), limit=strategy.position_avg_price + (atr_val * sl_mult * tp_ratio), comment_loss="SL", comment_profit="TP")
strategy.exit("Exit Short", "Short", stop=strategy.position_avg_price + (atr_val * sl_mult), limit=strategy.position_avg_price - (atr_val * sl_mult * tp_ratio), comment_loss="SL", comment_profit="TP")
// ==========================================
// 🔹 VISUALS
// ==========================================
// Plot EMA
plot(use_trend ? ema_val : na, "Trend EMA", color=color.new(color.orange, 0), linewidth=2)
// Plot ADX level reference (For visual confirmation only, as ADX is an oscillator)
// Note: Plotting oscillator values (0-100) on the main chart (price scale) can flatten the chart.
// It is usually better to plot ADX in a separate pane, but kept here per original request.
plot(adx_thresh, "ADX Threshold", color=color.new(color.gray, 70), linewidth=1, linestyle = plot.linestyle_dashed)
// Plot Signals
plotshape(long_signal, title="Long Signal", location=location.belowbar, color=color.green, style=shape.labelup, text="BUY", textcolor=color.white)
plotshape(short_signal, title="Short Signal", location=location.abovebar, color=color.red, style=shape.labeldown, text="SELL", textcolor=color.white)
// Background color for strong trends
strong_trend = adx_val > adx_thresh
bgcolor(strong_trend ? (plus_di > minus_di ? color.new(color.green, 95) : color.new(color.red, 95)) : na)