Expand description
§Average Directional Index (ADX) / +DI / −DI / DX
Wilder directional movement system (period (N), classic 14):
+DM = up-move if up > down and up > 0 else 0
−DM = down-move if down > up and down > 0 else 0
TR = true range
Smooth TR, +DM, −DM with Wilder (seed = SMA of first N, then Wilder)
+DI = 100 * smooth(+DM) / smooth(TR)
−DI = 100 * smooth(−DM) / smooth(TR)
DX = 100 * |+DI − −DI| / (+DI + −DI)
ADX = Wilder smooth of DX (first ADX = SMA of first N DX values)Warm-up: first bar has no prior close (TR = H−L; DM from first change needs bar 1).
First DI/DX at index N−1 after N TR/DM samples; first ADX after N DX values
(index roughly 2N−2 on a continuous path).
§Trading perspective
| Signal | Habit (classic, not a rule) |
|---|---|
| ADX rising / > ~25 | Trend strength — trend systems “allowed” |
| ADX low / falling | Range — oscillators / mean-reversion more natural |
| +DI > −DI | Bullish directional bias |
| −DI > +DI | Bearish directional bias |
| DI cross | Direction change screen (filter with ADX level) |
ADX is not direction — only strength. Always read +DI / −DI (or price structure) for side.
§vs ATR / Supertrend / MACD
| ADX/DI | ATR | Supertrend | MACD | |
|---|---|---|---|---|
| Measures | Trend strength + DI direction | Volatility size | Trail stop / side | Momentum of closes |
| Good at | Regime filter | Stops / size | In/out of trend | Timing / hist flips |
§Pairs well with
- Supertrend / SAR / Donchian — take breakouts only if ADX confirms trend.
- RSI / WillR / CCI — fade extremes only if ADX is weak (range regime).
- Moving averages — DI side + MA slope agreement.
§Engineering
AdxParams → adx / AdxState → adx_solution.
Batch uses AdxState end-to-end. After seeds, each push is O(1).
Smoothing uses the same average-seed then Wilder style as this crate’s ATR
(SMA of first N samples, then ((prev·(N−1)+x)/N)).
§Word problem
Can ADX be defined on a series shorter than (2N−1) bars?
Usually no for a full ADX value (need N DM/TR seeds then N DX for ADX seed).
use finance_solution::stocks::ta::{adx, AdxParams};
let n = 40usize;
let h: Vec<_> = (0..n).map(|i| 101.0 + i as f64 * 0.2).collect();
let l: Vec<_> = (0..n).map(|i| 99.0 + i as f64 * 0.2).collect();
let c: Vec<_> = (0..n).map(|i| 100.0 + i as f64 * 0.2).collect();
let s = adx(&h, &l, &c, AdxParams::period_14()).unwrap();
assert!(s.adx.iter().any(|x| x.is_some()));
assert!(s.plus_di.iter().any(|x| x.is_some()));Structs§
- AdxBar
Output - One-bar ADX pack (any field may still be warming up).
- AdxParams
- ADX / DI Wilder period.
- AdxSeries
- AdxSolution
- AdxState
- Incremental ADX / DI / DX.
- Validated
Adx
Functions§
- adx
- adx_
solution - Examples