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.
| New high / low | UpMove | DownMove | +DM | −DM |
|---|---|---|---|---|
| 103 / 93 | 3 | 2 | 3 | 0 |
| 102 / 93 | 2 | 2 | 0 | 0 |
| 99 / 96 | −1 | −1 | 0 | 0 |
| 103 / 96 | 3 | −1 | 3 | 0 |
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)
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.
| Quantity | Calculation | New value |
|---|---|---|
| Smoothed TR | (13 × 4 + 7)/14 | 4.214286 |
| Smoothed +DM | (13 × 1.2 + 3)/14 | 1.328571 |
| Smoothed −DM | (13 × 0.8 + 0)/14 | 0.742857 |
| +DI | 100 × 18.6/59 | 31.525424 |
| −DI | 100 × 10.4/59 | 17.627119 |
| DX | 100 × (18.6 − 10.4)/(18.6 + 10.4) | 28.275862 |
| ADX | (13 × 25 + 28.275862…)/14 | 25.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.
// 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.

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