Directional Movement Index (DX)
period = 14 Overview
The Directional Movement Index (DX), created by J. Welles Wilder Jr., measures the strength of price movement regardless of direction by analyzing the relationship between positive and negative directional indicators. DX forms the raw foundation for the more commonly used Average Directional Index (ADX). The calculation involves first determining Plus DI and Minus DI from smoothed directional movements and true range. DX then quantifies how far apart these directional indicators are, expressing the difference as a percentage of their sum. This produces values between 0 and 100 that represent the degree of directional movement present in the market.
DX values indicate the presence and strength of trending behavior without specifying direction. Low DX readings near 0 occur when Plus DI and Minus DI are nearly equal, signaling directionless, choppy markets where neither bulls nor bears maintain control. High DX values approaching 100 indicate strong directional movement where one side dominates completely. Values above 25 generally suggest trending conditions suitable for trend following strategies. Because DX measures raw directional strength at each point, it can be quite volatile, jumping dramatically as directional dominance shifts between buyers and sellers.
While DX provides valuable insights into market structure, most traders use its smoothed version, ADX, for practical applications due to DX's erratic nature. However, understanding DX helps interpret ADX more effectively by revealing the underlying directional dynamics. Some advanced traders monitor DX directly for early warning of trend changes, as spikes or drops in DX often precede similar moves in ADX by several periods. DX also proves useful in system development for identifying optimal smoothing parameters. The indicator serves as a building block for custom indicators that require raw directional strength measurements before applying proprietary smoothing or filtering techniques.
Implementation Examples
Compute DX from H/L/C slices or candles:
use vectorta::indicators::dx::{dx, DxInput, DxParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with H/L/C slices
let high = vec![/* ... */];
let low = vec![/* ... */];
let close = vec![/* ... */];
let params = DxParams { period: Some(14) }; // default
let input = DxInput::from_hlc_slices(&high, &low, &close, params);
let result = dx(&input)?;
// Using with Candles (auto-selects high/low/close), default period=14
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = DxInput::with_default_candles(&candles);
let result = dx(&input)?;
// Access DX values
for value in result.values {
println!("DX: {}", value);
} API Reference
Input Methods ▼
// From high/low/close slices
DxInput::from_hlc_slices(&[f64], &[f64], &[f64], DxParams) -> DxInput
// From candles (uses high/low/close fields)
DxInput::from_candles(&Candles, DxParams) -> DxInput
// From candles with default params (period=14)
DxInput::with_default_candles(&Candles) -> DxInput Parameters Structure ▼
pub struct DxParams {
pub period: Option<usize>, // Default: 14
} Output Structure ▼
pub struct DxOutput {
pub values: Vec<f64>, // DX values in [0, 100]
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len; otherwiseDxError::InvalidPeriod { period, data_len }.- Data source: candles require
high/low/close; selection failures surface asDxError::SelectCandleFieldError(String). - First valid index is the first bar where all H/L/C are finite. If none:
DxError::AllValuesNaN. - There must be at least
periodvalid bars after the first finite bar; elseDxError::NotEnoughValidData { needed, valid }. - Warmup: indices
[0 .. first + period − 1)areNaN. The first DX value is written atfirst + period − 1. - Runtime NaNs: if any of H/L/C are
NaNat an index, that output carries the previous DX value forward. - Edge case: when
+DI + −DI == 0, the first value becomes0.0; later values fall back to the last DX.
Error Handling ▼
#[derive(Debug, Error)]
pub enum DxError {
#[error("dx: Empty data provided for DX.")]
EmptyData,
#[error("dx: Could not select candle field: {0}")]
SelectCandleFieldError(String),
#[error("dx: Invalid period: period = {period}, data length = {data_len}")]
InvalidPeriod { period: usize, data_len: usize },
#[error("dx: Not enough valid data: needed = {needed}, valid = {valid}")]
NotEnoughValidData { needed: usize, valid: usize },
#[error("dx: All high, low, and close values are NaN.")]
AllValuesNaN,
}
// Example handling
match dx(&input) {
Ok(out) => {/* use out.values */},
Err(e) => match e {
DxError::EmptyData => {/* handle */},
DxError::SelectCandleFieldError(msg) => {/* log msg */},
DxError::InvalidPeriod { .. } => {/* fix params */},
DxError::NotEnoughValidData { .. } => {/* supply more data */},
DxError::AllValuesNaN => {/* clean inputs */},
}
} Python Bindings
Basic Usage ▼
Calculate DX from NumPy arrays of H/L/C (default period=14):
import numpy as np
from vectorta import dx
# Prepare H/L/C as NumPy arrays
high = np.array([...], dtype=float)
low = np.array([...], dtype=float)
close = np.array([...], dtype=float)
# Default period
values = dx(high, low, close, period=14)
# Or specify kernel ("auto", "scalar", "avx2", "avx512")
values = dx(high, low, close, period=20, kernel="avx2")
print(values) Streaming Real-time Updates ▼
Process H/L/C streams with O(1) updates (first value after warmup):
from vectorta import DxStream
stream = DxStream(period=14)
for h, l, c in hlc_feed:
dx_val = stream.update(h, l, c)
if dx_val is not None:
print("DX:", dx_val) Batch Parameter Optimization ▼
Test multiple period values efficiently:
import numpy as np
from vectorta import dx_batch
high = np.array([...], dtype=float)
low = np.array([...], dtype=float)
close = np.array([...], dtype=float)
# (start, end, step)
result = dx_batch(high, low, close, period_range=(10, 30, 5), kernel="auto")
values = result["values"] # shape: (num_periods, len)
periods = result["periods"] # list of tested periods
print(values.shape, periods) CUDA Acceleration ▼
CUDA support for DX is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated DX calculations JavaScript/WASM Bindings
Basic Usage ▼
Calculate DX in JavaScript/TypeScript:
import { dx_js } from 'vectorta-wasm';
// H/L/C data as Float64Array
const high = new Float64Array([/* ... */]);
const low = new Float64Array([/* ... */]);
const close = new Float64Array([/* ... */]);
// Calculate DX with specified period
const values = dx_js(high, low, close, 14);
console.log('DX values:', values); Memory-Efficient Operations ▼
Use zero-copy operations with explicit memory:
import { dx_alloc, dx_free, dx_into, memory } from 'vectorta-wasm';
const len = close.length;
const hPtr = dx_alloc(len);
const lPtr = dx_alloc(len);
const cPtr = dx_alloc(len);
const outPtr = dx_alloc(len);
// Copy data into WASM memory
new Float64Array(memory.buffer, hPtr, len).set(high);
new Float64Array(memory.buffer, lPtr, len).set(low);
new Float64Array(memory.buffer, cPtr, len).set(close);
// Compute directly into the output buffer
dx_into(hPtr, lPtr, cPtr, outPtr, len, 14);
// Read back (slice() to copy out of WASM memory)
const dxValues = new Float64Array(memory.buffer, outPtr, len).slice();
// Free memory
dx_free(hPtr, len);
dx_free(lPtr, len);
dx_free(cPtr, len);
dx_free(outPtr, len); Batch Processing ▼
Test multiple periods in one call:
import { dx_batch } from 'vectorta-wasm';
const config = { period_range: [10, 30, 5] };
const { values, combos, rows, cols } = dx_batch(high, low, close, config);
// values is flat [rows * cols]; reshape as needed
const resultMatrix: number[][] = [];
for (let r = 0; r < rows; r++) {
const start = r * cols;
resultMatrix.push(values.slice(start, start + cols));
}
// combos[r].period holds the period for row r
console.log('Periods tested:', combos.map(c => c.period)); Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
CUDA note
In our benchmark workload, the Rust CPU implementation is faster than CUDA for this indicator. Prefer the Rust/CPU path unless your workload differs.
Related Indicators
Average Directional Index
Technical analysis indicator
Average Directional Movement Index Rating
Technical analysis indicator
Alligator
Technical analysis indicator
Aroon
Technical analysis indicator
Aroon Oscillator
Technical analysis indicator
Chande Momentum Oscillator
Technical analysis indicator