Skip to main content

ADX Indicator: Average Directional Index in a JavaScript or React Financial Chart

The ADX (Average Directional Index) measures how strong a trend is, whichever way it is going. This page explains what the ADX indicator is, how ADX and its +DI and −DI lines are calculated and how traders read them, and shows how to add an ADX indicator to a JavaScript or React financial chart with SciTrader.js's ADXStudy, with live examples you can edit in CodePen.

info

The ADX is one of the 32 built-in technical indicators and studies in the SciTrader SDK. For the full list, with each one's options and defaults, see Every Built-in Indicator and Study. To add and remove any of them, or build an indicator picker, see Add Technical Indicators to a Financial Chart.

What Is the ADX Indicator?​

The ADX, developed by J. Welles Wilder Jr. as part of his Directional Movement System, is drawn with two companion lines:

  • ADX measures trend strength, from 0 to 100. It rises in a strong trend, up or down, and falls when the market is moving sideways.
  • +DI (the positive directional indicator) measures upward movement.
  • −DI (the negative directional indicator) measures downward movement.

So ADX says how strong the trend is, and +DI and −DI say which way it is going. They have their own scale, so a chart draws them in a pane of their own below the price chart.

How Is the ADX Calculated?​

The ADX is built in four steps, over length candles, 14 by default:

  1. Directional movement. Compare each candle with the one before. Only the larger of the up move and the down move counts, and only if it is positive:

    up=hight−hight−1down=lowt−1−lowt+DM={upif up>down and up>00otherwise−DM={downif down>up and down>00otherwise\begin{aligned} \text{up} &= \text{high}_t - \text{high}_{t-1} \qquad \text{down} = \text{low}_{t-1} - \text{low}_t \\ {+}\text{DM} &= \begin{cases} \text{up} & \text{if up} > \text{down and up} > 0 \\ 0 & \text{otherwise} \end{cases} \qquad {-}\text{DM} = \begin{cases} \text{down} & \text{if down} > \text{up and down} > 0 \\ 0 & \text{otherwise} \end{cases} \end{aligned}
  2. True range. The candle's range, including any gap from the previous close; see ATR.

  3. Wilder smoothing. +DM, −DM and TR are each smoothed with Wilder's running sum, SS. Its first value is the sum of the first nn values; each later one is

    St=St−1−St−1n+xtS_t = S_{t-1} - \frac{S_{t-1}}{n} + x_t

    where nn is length and xtx_t the latest value. Then

    +DI=100×S(+DM)S(TR)−DI=100×S(−DM)S(TR)DX=100×∣+DI−−DI∣+DI+−DI{+}\text{DI} = 100 \times \frac{S({+}\text{DM})}{S(\text{TR})} \qquad {-}\text{DI} = 100 \times \frac{S({-}\text{DM})}{S(\text{TR})} \qquad \text{DX} = 100 \times \frac{\left|{+}\text{DI} - {-}\text{DI}\right|}{{+}\text{DI} + {-}\text{DI}}
  4. ADX is the Wilder average of DX: the first value is the simple average of the first nn DX values, and each later one moves 1/n1/n of the way towards the latest DX.

Because DX is smoothed again, the first ADX value needs about twice length candles. SciTrader loads extra candles to the left of the visible period, so the lines start at the left edge.

How to Read the ADX​

These are the common readings. They are conventions traders use, not signals that hold every time:

  • Trend strength. ADX above 25 is commonly read as a trending market, and below 20 as weak or no trend. ADXStudy doesn't draw these levels; read them from the axis.
  • Rising or falling ADX. A rising ADX means the trend is strengthening, whichever way it points; a falling ADX means it is weakening.
  • DI crossovers. +DI crossing above −DI is read as bullish, and −DI crossing above +DI as bearish. Many traders act on them only when ADX shows a trend.
  • Choosing a strategy. A high ADX favours trend-following; a low ADX favours range trading.

How to Add an ADX Indicator to a JavaScript Financial Chart​

Add an ADXStudy to the chart's studies. The example below is a 6-hour BTC-USD chart from Coinbase with a 14-candle ADX in its own pane: ADX in amber, +DI in green and −DI in red.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import {
ADXStudy,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
OHLCStudy,
SciFinanceChartPanel,
VolumeStudy,
} from "scichart-scitrader";

// This example expects this HTML:
// <div id="chart" style="height: 100%"></div>

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

async function createChart() {
// A financial chart is a SciFinanceChartPanel. Its indicators are studies, passed in `studies`
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// ADX: an oscillator, so it gets a pane of its own below the price pane.
// It draws three lines: ADX (trend strength), +DI and -DI (direction).
// length: the smoothing length of all three (default 14)
new ADXStudy({
length: 14,
adxColor: "#ff9f1c", // ADX
pdiColor: "#26a69a", // +DI
mdiColor: "#ef5350", // -DI
strokeThickness: 2,
}),
],
});

// When the page goes away: financeChartPanel.cleanup();
return financeChartPanel;
}

createChart();

How to Add an ADX Indicator to a React Financial Chart​

In React, pass the same studies in the config of SciFinanceChartView, from scichart-scitrader-react. Create them in a useMemo, once per mounted chart: a study is a live object, bound to one chart.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
ADXStudy,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciFinanceChartPanelConfig,
OHLCStudy,
VolumeStudy,
} from "scichart-scitrader";
import { SciFinanceChartView } from "scichart-scitrader-react";

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

export function AdxChart() {
// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [
new OHLCStudy(), // the price series, as candlesticks
new VolumeStudy(), // volume, along the bottom of the price pane
// ADX: an oscillator, so it gets a pane of its own below the price pane.
// It draws three lines: ADX (trend strength), +DI and -DI (direction).
// length: the smoothing length of all three (default 14)
new ADXStudy({
length: 14,
adxColor: "#ff9f1c", // ADX
pdiColor: "#26a69a", // +DI
mdiColor: "#ef5350", // -DI
strokeThickness: 2,
}),
],
}),
[]
);

// SciFinanceChartView fills its parent, so give the parent a height
return <SciFinanceChartView config={config} />;
}

Adding and Removing the ADX Indicator at Runtime​

ADXStudy is a study like any other, so you can add it to a chart that is already showing, and remove it again:

import { EStudyType, ADXStudy, studyProvider } from "scichart-scitrader";

const chart = financeChartPanel.financeApi;

// Add one with your own settings...
const study = new ADXStudy();
await chart.attachStudy(study);

// ...or by type, with the default settings, e.g. from an indicator picker
await chart.attachStudy(studyProvider.getStudy(EStudyType.ADX));

// Remove it
chart.detachStudy(study);

See Add Technical Indicators to a Financial Chart for more, including a ready-made indicator picker.

ADXStudy Options and Settings​

OptionDefaultWhat it does
length14The smoothing length of +DI, −DI and ADX
adxColorThe theme's colourThe ADX line
pdiColorThe theme's colourThe +DI line
mdiColorThe theme's colourThe −DI line
strokeThickness2The thickness of all three lines
paneIdA new paneThe pane to draw in

Users can change the same settings in the Settings Form, and you can change them from code with applyDescriptor. There, length is named period:

StudyInputsStyles
ADXStudyperiodadxColor, pdiColor, mdiColor, strokeThickness
The ADXStudy class, with its TSDoc
/**
* Average Directional Index — three lines (ADX, +DI, -DI), 0–100, on their own
* pane. HLC input. Three distinctly-named outputs (the single-output
* {@link StudyBase.createOutputSourceId} helper would collide their ids).
*/
class ADXStudy extends StudyBase<number> {
/** Indicator pane — small relative weight (price pane defaults to 3×). */
readonly paneSizeConfig: {
grow: number;
};
length: number;
adxColor: string;
pdiColor: string;
mdiColor: string;
strokeThickness: number;
getRequiredWarmup(): number;
constructor(options?: IADXOptions);
static getOptionsFromDescriptor(descriptor: TStudyDescriptor): IADXOptions;
get supportsLiveApply(): boolean;
createInputOutputIds(): void;
createDataSeries(): void;
createAxes(): AxisBase2D[];
/** @inheritDoc */
getLegendColor(outputId: DataSourceId): string | undefined;
createRenderableSeries(): IRenderableSeries[];
}
The IADXOptions interface, with its TSDoc
interface IADXOptions extends IStudyOptions {
length?: number;
adxColor?: string;
pdiColor?: string;
mdiColor?: string;
strokeThickness?: number;
}