I was playing with this a little bit and found something that can help you with the issue:
def ADX(data: pd.DataFrame, period: int):
"""
Computes the ADX indicator.
"""
df = data.copy()
alpha = 1/period
# TR
df['H-L'] = df['High'] - df['Low']
df['H-C'] = np.abs(df['High'] - df['Close'].shift(1))
df['L-C'] = np.abs(df['Low'] - df['Close'].shift(1))
df['TR'] = df[['H-L', 'H-C', 'L-C']].max(axis=1)
del df['H-L'], df['H-C'], df['L-C']
# ATR
df['ATR'] = df['TR'].ewm(alpha=alpha, adjust=False).mean()
# +-DX
df['H-pH'] = df['High'] - df['High'].shift(1)
df['pL-L'] = df['Low'].shift(1) - df['Low']
df['+DX'] = np.where(
(df['H-pH'] > df['pL-L']) & (df['H-pH']>0),
df['H-pH'],
0.0
)
df['-DX'] = np.where(
(df['H-pH'] < df['pL-L']) & (df['pL-L']>0),
df['pL-L'],
0.0
)
del df['H-pH'], df['pL-L']
# +- DMI
df['S+DM'] = df['+DX'].ewm(alpha=alpha, adjust=False).mean()
df['S-DM'] = df['-DX'].ewm(alpha=alpha, adjust=False).mean()
df['+DMI'] = (df['S+DM']/df['ATR'])*100
df['-DMI'] = (df['S-DM']/df['ATR'])*100
del df['S+DM'], df['S-DM']
# ADX
df['DX'] = (np.abs(df['+DMI'] - df['-DMI'])/(df['+DMI'] + df['-DMI']))*100
df['ADX'] = df['DX'].ewm(alpha=alpha, adjust=False).mean()
del df['DX'], df['ATR'], df['TR'], df['-DX'], df['+DX'], df['+DMI'], df['-DMI']
return df
At the beginning the values aren't correct (as always with the EWM approach) but after several computations it converges to the correct value.
Answer from Fabio Gomez on Stack OverflowMedium
eodhd.medium.com › algorithmic-trading-with-the-average-directional-index-in-python-6f3b2ce08e75
Algorithmic Trading with ADX in Python | by EODHD APIs | Medium
October 3, 2024 - In this step, we implement the Average Directional Index (ADX) trading strategy using Python.
GitHub
github.com › Nikhil-Adithyan › Algorithmic-Trading-with-ADX-in-python › blob › master › adx_strategy_code.py
Algorithmic-Trading-with-ADX-in-python/adx_strategy_code.py at master · Nikhil-Adithyan/Algorithmic-Trading-with-ADX-in-python
aapl['minus_di'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[1]).rename(columns = {0:'minus_di'})
Author Nikhil-Adithyan
Videos
07:53
Python: Average Directional Index (ADX) 4 Directional Movement ...
21:02
GPT: ADX scalping strategy in Python makes 4479% - YouTube
08:02
Freqtrade: ADX Indicator Strategy in Python makes 329% - YouTube
06:18
Python: Average Directional Index (ADX) 2 Directional Movement ...
09:58
Python: Average Directional Index (ADX) 3 Directional Movement ...
05:10
ADX in Python - YouTube
Top answer 1 of 4
9
I was playing with this a little bit and found something that can help you with the issue:
def ADX(data: pd.DataFrame, period: int):
"""
Computes the ADX indicator.
"""
df = data.copy()
alpha = 1/period
# TR
df['H-L'] = df['High'] - df['Low']
df['H-C'] = np.abs(df['High'] - df['Close'].shift(1))
df['L-C'] = np.abs(df['Low'] - df['Close'].shift(1))
df['TR'] = df[['H-L', 'H-C', 'L-C']].max(axis=1)
del df['H-L'], df['H-C'], df['L-C']
# ATR
df['ATR'] = df['TR'].ewm(alpha=alpha, adjust=False).mean()
# +-DX
df['H-pH'] = df['High'] - df['High'].shift(1)
df['pL-L'] = df['Low'].shift(1) - df['Low']
df['+DX'] = np.where(
(df['H-pH'] > df['pL-L']) & (df['H-pH']>0),
df['H-pH'],
0.0
)
df['-DX'] = np.where(
(df['H-pH'] < df['pL-L']) & (df['pL-L']>0),
df['pL-L'],
0.0
)
del df['H-pH'], df['pL-L']
# +- DMI
df['S+DM'] = df['+DX'].ewm(alpha=alpha, adjust=False).mean()
df['S-DM'] = df['-DX'].ewm(alpha=alpha, adjust=False).mean()
df['+DMI'] = (df['S+DM']/df['ATR'])*100
df['-DMI'] = (df['S-DM']/df['ATR'])*100
del df['S+DM'], df['S-DM']
# ADX
df['DX'] = (np.abs(df['+DMI'] - df['-DMI'])/(df['+DMI'] + df['-DMI']))*100
df['ADX'] = df['DX'].ewm(alpha=alpha, adjust=False).mean()
del df['DX'], df['ATR'], df['TR'], df['-DX'], df['+DX'], df['+DMI'], df['-DMI']
return df
At the beginning the values aren't correct (as always with the EWM approach) but after several computations it converges to the correct value.
2 of 4
4
This gives you the exact numbers as Tradingview and Thinkorswim.
import numpy as np
def ema(arr, periods=14, weight=1, init=None):
leading_na = np.where(~np.isnan(arr))[0][0]
arr = arr[leading_na:]
alpha = weight / (periods + (weight-1))
alpha_rev = 1 - alpha
n = arr.shape[0]
pows = alpha_rev**(np.arange(n+1))
out1 = np.array([])
if 0 in pows:
out1 = ema(arr[:int(len(arr)/2)], periods)
arr = arr[int(len(arr)/2) - 1:]
init = out1[-1]
n = arr.shape[0]
pows = alpha_rev**(np.arange(n+1))
scale_arr = 1/pows[:-1]
if init:
offset = init * pows[1:]
else:
offset = arr[0]*pows[1:]
pw0 = alpha*alpha_rev**(n-1)
mult = arr*pw0*scale_arr
cumsums = mult.cumsum()
out = offset + cumsums*scale_arr[::-1]
out = out[1:] if len(out1) > 0 else out
out = np.concatenate([out1, out])
out[:periods] = np.nan
out = np.concatenate(([np.nan]*leading_na, out))
return out
def atr(highs, lows, closes, periods=14, ema_weight=1):
hi = np.array(highs)
lo = np.array(lows)
c = np.array(closes)
tr = np.vstack([np.abs(hi[1:]-c[:-1]),
np.abs(lo[1:]-c[:-1]),
(hi-lo)[1:]]).max(axis=0)
atr = ema(tr, periods=periods, weight=ema_weight)
atr = np.concatenate([[np.nan], atr])
return atr
def adx(highs, lows, closes, periods=14):
highs = np.array(highs)
lows = np.array(lows)
closes = np.array(closes)
up = highs[1:] - highs[:-1]
down = lows[:-1] - lows[1:]
up_idx = up > down
down_idx = down > up
updm = np.zeros(len(up))
updm[up_idx] = up[up_idx]
updm[updm < 0] = 0
downdm = np.zeros(len(down))
downdm[down_idx] = down[down_idx]
downdm[downdm < 0] = 0
_atr = atr(highs, lows, closes, periods)[1:]
updi = 100 * ema(updm, periods) / _atr
downdi = 100 * ema(downdm, periods) / _atr
zeros = (updi + downdi == 0)
downdi[zeros] = .0000001
adx = 100 * np.abs(updi - downdi) / (updi + downdi)
adx = ema(np.concatenate([[np.nan], adx]), periods)
return adx
Technical Analysis Library in Python
technical-analysis-library-in-python.readthedocs.io › en › latest › ta.html
Documentation — Technical Analysis Library in Python 0.1.4 documentation
The Average Directional Index (ADX) is in turn derived from the smoothed averages of the difference between +DI and -DI, and measures the strength of the trend (regardless of direction) over time.
DataCamp
campus.datacamp.com › courses › financial-trading-in-python › technical-indicators
Calculate the ADX | Python
Calculate the ADX using the appropriate function from talib, and the High, Low and Close columns in the stock_data.
DataCamp
campus.datacamp.com › courses › financial-trading-in-python › technical-indicators
Strength indicator: ADX | Python
ADX can be implemented in Python by calling talib dot ADX, and passing three types of price data as input, the high, low and close price. Originally Welles Wilder used a 14-period lookback window for ADX calculations, which became the industry standard. You can change the default period with ...
Medium
medium.com › codex › algorithmic-trading-with-average-directional-index-in-python-2b5a20ecf06a
Algorithmic Trading with Average Directional Index in Python | by Nikhil Adithyan | CodeX | Medium
October 5, 2023 - In this article, we are going to explore one of the most popular trend indicators, the Average Directional Index (shortly known as ADX). We will first build some basic understanding of what ADX is all about and its calculation, then, move on to building the indicator from scratch and construct a trading strategy based on that indicator in python.
GitHub
github.com › mantasavas › trading-strategy-automation
GitHub - mantasavas/trading-strategy-automation: Python automated script for outputting and displaying stock data. Two widespread indicators are being used: Average Directional Index (ADX) and Bollinger Bands.
Python automated script for outputting and displaying stock data. Two widespread indicators are being used: Average Directional Index (ADX) and Bollinger Bands. - mantasavas/trading-strategy-automation
Starred by 7 users
Forked by 4 users
Languages Python 100.0% | Python 100.0%
CodeRivers
coderivers.org › blog › python-adx-calculation
Python ADX Calculation: A Comprehensive Guide - CodeRivers
April 12, 2025 - The ADX is calculated as the smoothed moving average of the Difference between $+DI$ and $-DI$ (the Directional Movement Index, DMI). [DMI = |+DI - -DI|] ADX is then calculated as an exponential moving average (EMA) of DMI over a specified period (usually 14 days). pandas is a powerful library for data manipulation and analysis in Python.
Stack Overflow
stackoverflow.com › questions › 79331942 › how-to-get-the-adx-with-pandas-ta-library-in-python-without-smoothing
algorithmic trading - How to get the ADX with pandas-ta library in Python without smoothing? - Stack Overflow
import pandas as pd def ExponentialMA(i, period, prev_value, values): if i == 0: return prev_value else: ema = (values[i] - prev_value) * 2 / (period + 1) + prev_value return ema def ADX(high, low, close, adx_period): # Initialize the PDI and NDI arrays with the same length as the input arrays pdi = [0] * len(high) ndi = [0] * len(high) # Initialize the ADX array with the same length as the input arrays adx = [0] * len(high) # Initialize the temporary buffer with the same length as the input arrays tmp_buffer = [0] * len(high) # Iterate through the data points for i in range(1, len(high)): # G
PyPI
pypi.org › project › stockstats
stockstats · PyPI
February 16, 2026 - Python :: Implementation :: CPython · Topic · Utilities · Report project as malware · Supply a wrapper StockDataFrame for pandas.DataFrame with inline stock statistics/indicators support. Supported statistics/indicators are: Moving Averages: SMA, EMA, SMMA, TEMA, LRMA, KAMA, VWMA, DMA · Momentum: RSI, StochRSI, MACD, PPO, KDJ, ROC, CMO, KST, Coppock, AO, BOP, CTI, Inertia, PSL · Trend: Supertrend, Aroon, Ichimoku, CR, DMI (+DI/-DI/ADX/ADXR), TRIX, WT ·
» pip install stockstats