Pine Script indicator reference

DMI: separate directional movement from ADX smoothing

The Directional Movement Index supplies three series: +DI, −DI and ADX. The first two compare smoothed upward and downward range expansion. ADX smooths their relative imbalance without preserving its direction. Understanding that ratio matters more than treating an ADX threshold as a trade instruction.

ta.dmi(diLength, adxSmoothing)
Returns: +DI, −DI, ADX
Example: 14, 14; three plots; no orders
Inspect the existing Pine Script

Directional movement is not a close-to-close return

Define UpMove as current high minus previous high, and DownMove as previous low minus current low. +DM takes UpMove only when it is positive and strictly greater than DownMove. −DM takes DownMove only when it is positive and strictly greater than UpMove. Otherwise the respective component is zero. A positive tie makes both zero; the two raw components cannot both be positive on the same bar.

Independent hypothetical bars after H = 100, L = 95
New high / lowUpMoveDownMove+DM−DM
103 / 933230
102 / 932200
99 / 96−1−100
103 / 963−130

In the last row, a previous close of 99 and a new close of 97 produce a falling close even though +DM is 3. DMI does not count buyer-initiated trades or use volume. Its upward and downward labels describe high-low movement, not the direction of every latest close.

TradingView attributes DMI to Welles Wilder's 1978 book, New Concepts in Technical Trading Systems. Its DMI reference supplies the strict movement comparisons and treats thresholds as instrument-dependent conventions.

Smooth the components before dividing

True Range is max(high − low, |high − previous close|, |low − previous close|). Let N be DI Length and M be ADX Smoothing. After initialization, a Wilder average of a series x follows RMA(x,N) = ((N − 1) × prior average + current x)/N.

+DI = 100 × RMA(+DM,N) / RMA(TR,N)
−DI = 100 × RMA(−DM,N) / RMA(TR,N)
DX = 100 × |+DI − −DI| / (+DI + −DI)
ADX = RMA(DX,M)

This is a ratio of smoothed components. Smoothing each bar's +DM/TR ratio instead generally gives a different value. ADX is not a rolling SMA of DX. TradingView's ADX calculation describes the recursive update; a sum-based Wilder smoother gives the same DI ratio when numerator and denominator use the same length and scaling.

The algebra assumes valid history and nonzero denominators. On flat or missing data, inspect the built-in output instead of manufacturing a ratio by dividing by zero or replacing unavailable values with a tradeable zero. Initialization and loaded history can affect early recursive values.

Reproduce one 14-period update

Assume prior smoothed values TR = 4, +DM = 1.2 and −DM = 0.8, with prior ADX = 25. These are invented starting states, not a backtest or a complete initialization history. Use the last hypothetical bar above: previous H/L/C = 100/95/99 and current H/L/C = 103/96/97. Its raw TR is 7, +DM is 3 and −DM is 0.

N = M = 14; rounded only for display
QuantityCalculationNew value
Smoothed TR(13 × 4 + 7)/144.214286
Smoothed +DM(13 × 1.2 + 3)/141.328571
Smoothed −DM(13 × 0.8 + 0)/140.742857
+DI100 × 18.6/5931.525424
−DI100 × 10.4/5917.627119
DX100 × (18.6 − 10.4)/(18.6 + 10.4)28.275862
ADX(13 × 25 + 28.275862…)/1425.233990

The previous +DI is 30. Smoothing the new raw ratio 100 × 3/7 with that old value would instead give 30.918367. That disagrees with 31.525424 because dividing first changes the calculation. Keep full precision until the display step.

Why a narrower DI gap can produce higher DX

For +DI = 30 and −DI = 10, DX is 50. For +DI = 3 and −DI = 1, DX is also 50, although the absolute gap shrank from 20 to 2. Swapping +DI and −DI leaves DX unchanged. This is why ADX alone cannot select a direction.

Now compare +DI/−DI of 30/10 with 20/5. The gap falls from 20 to 15, but DX rises from 50 to 60 because the sum falls too. If prior ADX is 70, the new 14-period ADX is (13 × 70 + 60)/14 = 69.285714: ADX falls even while DX rises.

More generally, current ADX minus prior ADX equals (current DX minus prior ADX)/M. Falling ADX does not by itself prove a reversal, shrinking raw DI separation, or declining price momentum. A high reading can persist in either direction.

The displayed three-line script

The current example calls ta.dmi(14, 14) once, then plots ADX in pink, +DI in blue and −DI in orange. It declares no input controls, horizontal threshold line, custom alert conditions or strategy orders. Change the source if you need those features; they are not supplied by copying this example.

Pine Script v6
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify

//@version=6
indicator(title="Directional Movement Index", overlay=false, max_labels_count=500)

[p_ind_1_plusDi, p_ind_1_minusDi, p_ind_1_adx]      =      ta.dmi(14, 14) // DMI

// ADX line — measures trend strength
plot(p_ind_1_adx, "DMI - ADX", color.rgb(245, 0, 87, 0), 1)
// +DI line — measures upward directional movement
plot(p_ind_1_plusDi, "DMI - +DI", color.rgb(41, 98, 255, 0), 1)
// -DI line — measures downward directional movement
plot(p_ind_1_minusDi, "DMI - -DI", color.rgb(255, 109, 0, 0), 1)

Open the Pine Editor through the Pine icon on TradingView's right toolbar, paste the full source and add it to the chart. The tuple order is +DI, −DI, ADX; the order of the three plot statements does not change that return order. Inspect values in the Data Window and compare with a built-in DMI using the same lengths and chart context.

Existing Directional Movement Index chart illustration with three colored lines

The retained illustration is not evidence of the hypothetical arithmetic or a tested strategy. Any reference line in an illustration is not created by this source.

Define a crossing rule without moving the decision time

One possible research rule is: on a completed bar, +DI crosses strictly above −DI, ADX is strictly above 20, and ADX exceeds its previous value. The preceding DI comparison must be +DI less than or equal to −DI. Require available current and prior values. A cross with ADX exactly 20 fails this particular threshold.

Under this same-bar rule, a crossing that fails the filter does not become an entry two bars later merely because ADX rises. Allowing a three-bar confirmation window would require a separately defined armed state, expiry and cancellation rule. Neither rule is implemented by the plotting script, and neither has an established win rate here.

Indicators recalculate as the open bar changes. New highs, lows and closes can alter DMI before confirmation. Specify the closed-bar observation and order timing independently: a decision at a completed close is not evidence that an order filled at that close. An opposite crossing, an ADX exit and a timed exit are different systems, not interchangeable descriptions.

A hypothetical long fill at 450 with ATR = 2 and a stop 1.5 ATR below entry gives a stop price of 447. A later gap to 444 can produce a loss larger than the planned 3 per unit. A ten-bar exit can realize a loss; a time limit cannot promise a small profit or breakeven.

Compare settings and indicators on the same question

DI Length and ADX Smoothing are independent. Changing the first alters the components entering DX; changing the second alters the filtering of DX. Recursive 14-period smoothing does not discard all observations older than 14 bars, so a 5-minute chart does not confine DMI history to precisely 70 minutes.

No best timeframe, stock, currency or crypto setting is demonstrated here. Choose a baseline and a fixed sample, change one parameter at a time, then evaluate on separate observations. Keep the event definition, exits, fees, slippage and session consistent. A filter can remove winning trades as well as losing ones; fewer entries alone do not establish improvement.

RSI compares smoothed positive and negative close changes. MACD compares moving averages of a chosen source. DMI instead starts from competing high-low movements and True Range. These mechanisms do not imply a universal ranking of lag, reliability or daily signal frequency.

Specify additions before generating a variant

The Pine Script AI Coding Agent can help draft a variant. Check the account's current access and inspect the resulting source. A useful request separates display settings from a closed-bar signal:

Keep ta.dmi with separate DI Length and ADX Smoothing inputs, both defaulting to 14. Plot all three returned series. Add an optional ADX reference level without calling it a trading guarantee. Create a custom alert only for a confirmed bullish DI crossing with ADX strictly above the selected threshold and rising. Do not place strategy orders.

Validate syntax, compare numerical values and verify alert timing before adding execution rules. Passing a syntax check does not establish forecasting accuracy.

Open Pine Script AI Coding Agent

DMI questions

ta.dmi(diLength, adxSmoothing) returns +DI, −DI and ADX in that order. The first length smooths directional movement and True Range; the second smooths DX into ADX. The displayed script fixes both lengths at 14 and plots the three results in a separate pane.

After initialization, Wilder smoothing updates ADX as ((M − 1) × prior ADX + current DX)/M. With M = 14, the new DX receives weight 1/14. A rolling 14-value SMA of DX is a different calculation.

No. Directional movement compares successive highs and lows. A bar can make a higher high and still close below the previous close. The smoothed DI relationship also includes earlier observations.

No. Levels such as 20 and 25 are interpretation conventions. ADX describes smoothed directional imbalance, without selecting a long or short direction or predicting a trade outcome. Test a specified threshold against the same entry, exit and execution model.

Not in this exact example: it calls ta.dmi(14, 14) with literal values and declares no inputs. It also has no horizontal threshold line, alertcondition or orders. Adding those features requires a separate code change and validation.

No best market-specific setting is established here. Lengths are measured in chart bars and recursive smoothing retains older history. Specify a baseline, change one length at a time, and evaluate results on separate data with trading costs.

No. Under the recursive update, ADX falls when the current DX is below the previous ADX. That does not require the price direction to reverse, the raw DI gap to shrink, or DX itself to fall from its previous value.

Sources and further checks