
炒股的朋友们都知道,趋势是咱们交易里的"风向标"。可光知道方向还不够呀,你得知道这股风到底是微风徐徐,还是飓风呼啸!😂 这就是 ADX(Average Directional Index,平均趋向指标) 登场的地方。
为什么要测趋势的"强度"呢?很简单:
- 趋势弱 → 随时可能反转,交易胜率打折。
- 趋势强 → 上车后跟着走,成功率和人均盈利都更香。
不过,这里有个小秘密------别被名字骗了,ADX 并不告诉你趋势的方向!它只是告诉你"风有多大"。那方向咋办?别急,ADX 有两位好搭档:
- +DI(正向指标) → 检测上涨趋势
- -DI(负向指标) → 检测下跌趋势
所以,ADX 就是趋势强度的量尺,+DI 和 -DI 则是方向指南针,三剑合璧,才算完整。
接下来,花姐会依次聊聊:
- ADX 指标到底是啥?
- 它的计算逻辑(数学党最爱)
- 用 Python 写个小策略,把理论搬到实盘里
ADX 指标到底是啥?
提到 ADX 指标 ,就不得不说它的"发明人"------技术分析大佬 Welles Wilder。这位老哥可是技术指标界的"顶流",不光搞出了 RSI,还整出了 ADX 和方向性指标(Directional Movement Indicator)。
那 ADX 是怎么来的呢?它的家族成员有三位:
- True Range(真实波动范围)
- +DI(正向指标)
- -DI(负向指标)
Wilder 的思路是:先用 +DI 和 -DI 分别捕捉上升和下降的趋势,然后再算它们的"差异强度",最后用平滑处理得到一个指标------这就是 ADX。简单说,ADX 就是告诉你趋势"强不强",而不是"涨还是跌"。
👉 指标范围在 0 到 100 之间:
- 小于 20:市场基本在划水,趋势弱。
- 大于 25:趋势算是成型,可以关注。
- 50 以上:趋势非常强,但你可能也得小心见顶或见底。
ADX 的计算逻辑
讲到指标,免不了得撸一遍"数学流程图"。别怕,这里我帮你分了几步拆开讲,简单清晰:
-
True Range(真实波动范围) 衡量一天价格的真实波动。比单纯的 High - Low 更全面。
-
+DM(正向动向) 今天的高点比昨天高多少,如果比低点变化更大,那算上涨动向。
-
-DM(负向动向) 今天的低点比昨天低多少,如果比高点变化更大,那算下跌动向。
-
平滑处理 Wilder 很喜欢平滑,直接用指数平滑(类似移动平均)来消除噪音。
-
+DI 和 -DI 把 +DM 和 -DM 分别除以 True Range,然后算百分比,得到 +DI 和 -DI。
-
ADX 最终计算 用 |(+DI -- -DI)| - (+DI + -DI) 算出一个"方向差异比率",再平滑一下,就是 ADX。
现在我们来举个小栗子。假设某只股票的数据如下:
Date | High | Low | Close |
---|---|---|---|
2019-11-29 | 90 | 82 | 87 |
2019-12-2 | 95 | 85 | 87 |
2019-12-3 | 105 | 93 | 97 |
2019-12-4 | 120 | 106 | 114 |
2019-12-5 | 140 | 124 | 133 |
2019-12-6 | 165 | 147 | 157 |
2019-12-9 | 195 | 175 | 186 |
2019-12-10 | 230 | 208 | 223 |
2019-12-11 | 270 | 246 | 264 |
2019-12-12 | 315 | 289 | 311 |
2019-12-13 | 365 | 337 | 350 |
别看表格有点长,其实就是我们接下来要用来一步步算 ADX 的"样本数据"。
第一步:True Range(真实波动范围)
很多小伙伴看到 High - Low 就以为波动范围很简单嘛,今天最高价减最低价不就完了?😂 但是!如果只这么算,就会漏掉一个重要细节:价格可能在收盘和次日开盘之间跳空 。这就是为什么 Wilder 引入了 True Range(真实波动范围)。
👉 公式其实也不难,就是三者取最大:
- 当前最高价 - 当前最低价
- |当前最高价 - 昨日收盘价|
- |当前最低价 - 昨日收盘价|
选最大值,就是当天的 True Range。
举个例子: 日期:2019-12-2
- (High - Low) = 95 - 85 = 10
- |High - Prev Close| = |95 - 87| = 8
- |Low - Prev Close| = |85 - 87| = 2
所以 True Range = max(10, 8, 2) = 10
来看一下完整的 True Range 表格:
Date | High | Low | Close | High-Low | High-PrevClose | Low-PrevClose | True Range |
---|---|---|---|---|---|---|---|
2019-11-29 | 90 | 82 | 87 | - | - | - | - |
2019-12-2 | 95 | 85 | 87 | 10 | 8 | 2 | 10 |
2019-12-3 | 105 | 93 | 97 | 12 | 18 | 6 | 18 |
2019-12-4 | 120 | 106 | 114 | 14 | 23 | 9 | 23 |
2019-12-5 | 140 | 124 | 133 | 16 | 26 | 10 | 26 |
2019-12-6 | 165 | 147 | 157 | 18 | 32 | 14 | 32 |
2019-12-9 | 195 | 175 | 186 | 20 | 38 | 18 | 38 |
2019-12-10 | 230 | 208 | 223 | 22 | 44 | 22 | 44 |
2019-12-11 | 270 | 246 | 264 | 24 | 47 | 23 | 47 |
2019-12-12 | 315 | 289 | 311 | 26 | 51 | 25 | 51 |
2019-12-13 | 365 | 337 | 350 | 28 | 54 | 26 | 54 |
是不是比单纯的 High - Low 更"真实"了?
好了,True Range 我们拿下 。
第二步:正向动向(+DM)
前面咱们搞定了 True Range,现在该看 市场往上冲的力量 了。顾名思义,+DM(Positive Directional Movement) 就是用来捕捉上涨动能的。
问题来了:怎么判断"市场是真的在往上走"?🤔
直觉上,如果今天的 最高价 比昨天更高,那就说明有人愿意出更高的价买入,市场在往上推。 但是 Wilder 可没这么随便,他给了个小公式:
判断逻辑(if-else 版本):
- 如果 (今天高点 - 昨天高点) > (昨天低点 - 今天低点) → +DM = 今天高点 - 昨天高点
- 否则 → +DM = 0
这么做的意义在哪? 其实就是在比较:
- 上涨的"幅度" vs 下跌的"幅度"。
如果上涨的那一截更大,说明买盘更强,+DM 就记下来;
反之,就算了(记 0)。
这样,我们就能比较客观地量化"市场是否真的在往上走"。
第三步:负向动向(-DM)
股市就像人生,有上就有下。前面我们聊了 +DM(正向动向) 用来捕捉上涨力量,那这一步,自然要看看 市场往下砸的力度 ------也就是 -DM(Negative Directional Movement)。
判断逻辑也不难,和 +DM 是镜像关系:
👉 公式:
- 如果 (昨天低点 - 今天低点) > (今天高点 - 昨天高点) → -DM = 昨天低点 - 今天低点
- 否则 → -DM = 0
说白了,就是看 下跌的那一截是不是比上涨的更大。 如果跌幅更明显,就把这部分记为 -DM; 如果涨得多,说明空头不够强,那就记 0。
用我们之前的数据表来跑一下,结果如下:
Date | High | Low | Close | True Range | +DM | -DM |
---|---|---|---|---|---|---|
2019-11-29 | 90 | 82 | 87 | - | - | - |
2019-12-2 | 95 | 85 | 87 | 10 | 5 | 0 |
2019-12-3 | 105 | 93 | 97 | 18 | 10 | 0 |
2019-12-4 | 120 | 106 | 114 | 23 | 15 | 0 |
2019-12-5 | 140 | 124 | 133 | 26 | 20 | 0 |
2019-12-6 | 165 | 147 | 157 | 32 | 25 | 0 |
2019-12-9 | 195 | 175 | 186 | 38 | 30 | 0 |
2019-12-10 | 230 | 208 | 223 | 44 | 35 | 0 |
2019-12-11 | 270 | 246 | 264 | 47 | 40 | 0 |
2019-12-12 | 315 | 289 | 311 | 51 | 45 | 0 |
2019-12-13 | 365 | 337 | 350 | 54 | 50 | 0 |
可以看到,这段时间几乎全是上涨行情,所以 -DM 一直是 0,+DM 独自刷存在感。😂
第四步:平滑处理(Smoothed Values)
前面我们算了 True Range、+DM、-DM,但这些数据每天波动太大了,直接拿来用容易"眼花缭乱"。怎么办? 👉 Wilder 给出了答案:平滑处理,有点像移动平均,用来消掉短期噪音。
这里我们随便取个周期,假设 Period = 5 。 先看 +DM 的平滑值:
- 第一个平滑值 = 前 5 个 +DM 直接求和。 (5 + 10 + 15 + 20 + 25) = 75
- 然后算平均 = 75 / 5 = 15
- 接着,算下一个平滑值时,就用: 前一个平滑值 - (前一个平滑值/周期) + 当前值
举个例子:
- 当前是第 6 个 +DM(= 30)
- 所以第二个平滑值 = 75 - 15 + 30 = 90
是不是看着有点像 指数平滑平均?其实就是一个"滚动更新"的过程。
算出来的平滑表格如下:
Date | True Range | +DM | -DM | Smoothed +DM |
---|---|---|---|---|
2019-11-29 | - | - | - | - |
2019-12-2 | 10 | 5 | 0 | - |
2019-12-3 | 18 | 10 | 0 | - |
2019-12-4 | 23 | 15 | 0 | - |
2019-12-5 | 26 | 20 | 0 | - |
2019-12-6 | 32 | 25 | 0 | 75.0 |
2019-12-9 | 38 | 30 | 0 | 90.0 |
2019-12-10 | 44 | 35 | 0 | 107.0 |
2019-12-11 | 47 | 40 | 0 | 125.6 |
2019-12-12 | 51 | 45 | 0 | 145.5 |
2019-12-13 | 54 | 50 | 0 | 166.4 |
因为之前 -DM 一直是 0,所以它的平滑值自然也全是 0。 同理,True Range 也要做同样的平滑处理,完整表格如下:
Date | True Range | +DM | -DM | Smoothed +DM | Smoothed -DM | Smoothed TR |
---|---|---|---|---|---|---|
2019-11-29 | - | - | - | - | - | - |
2019-12-2 | 10 | 5 | 0 | - | - | - |
2019-12-3 | 18 | 10 | 0 | - | - | - |
2019-12-4 | 23 | 15 | 0 | - | - | - |
2019-12-5 | 26 | 20 | 0 | - | - | - |
2019-12-6 | 32 | 25 | 0 | 75.0 | 0.0 | 109.0 |
2019-12-9 | 38 | 30 | 0 | 90.0 | 0.0 | 125.2 |
2019-12-10 | 44 | 35 | 0 | 107.0 | 0.0 | 144.2 |
2019-12-11 | 47 | 40 | 0 | 125.6 | 0.0 | 162.3 |
2019-12-12 | 51 | 45 | 0 | 145.5 | 0.0 | 180.9 |
2019-12-13 | 54 | 50 | 0 | 166.4 | 0.0 | 198.7 |
到这里,我们手里已经有了 平滑后的 TR、+DM、-DM,就差最后三剑客了:
- +DI(正向指标)
- -DI(负向指标)
- ADX(平均趋向指标,大Boss)
下一步,就要正式进入这三兄弟的计算了!
正向指标(+DI)和负向指标(-DI)
我们之前算出了 平滑后的 +DM 和 -DM ,但单独看这两个指标,其实作用有限。Wilder 的聪明之处在于:把两者结合起来看交叉信号,这才有意义。💡
不过两个指标大小可能差别很大,为了好比较,我们要 归一化:
- 方法就是用平滑后的 +DM 或 -DM 除以平滑后的 True Range,然后转成百分比。
举个例子:
-
平滑后的 +DM = 75
-
平滑后的 True Range = 70
-
所以 +DI = 75 ÷ 70 ≈ 1.07 → 107%
-
而我们的 -DM 一直是 0,所以 -DI = 0%
ADX 指标:最终计算
记住一件事:ADX 告诉我们趋势的"强度",而不是方向。方向是 +DI 和 -DI 告诉我们的,但单看方向不足以判断市场有多"猛"。
想象一下,如果 +DI 和 -DI 很接近,说明买卖力量差不多,趋势可能很弱; 如果两者差距很大,说明趋势很强!Wilder 就用这个思想推出了 DX(Directional Index):
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> D X = ∣ + D I − − D I ∣ + D I + − D I × 100 DX = \frac{|+DI - -DI|}{+DI + -DI} \times 100 </math>DX=+DI+−DI∣+DI−−DI∣×100
举例:2019-12-6
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> D X = 75 − 0 75 + 0 × 100 = 100 DX = \frac{75 - 0}{75 + 0} \times 100 = 100 </math>DX=75+075−0×100=100
为了去掉波动,我们再对 DX 做 移动平均 ,得到最终的 ADX 指标。
- 时间周期取 5,那么 ADX = 最近 5 个 DX 的平均值。
计算出来后,我们可以直接看趋势强弱:
- ADX = 100 → 趋势非常强烈
- ADX < 20 → 趋势很弱或盘整
Date | True Range | +DM | -DM | Smoothed +DM | Smoothed -DM | Smoothed TR | +DI | -DI | DX | ADX |
---|---|---|---|---|---|---|---|---|---|---|
2019-11-29 | - | - | - | - | - | - | - | - | - | - |
2019-12-2 | 10 | 5 | 0 | - | - | - | - | - | - | - |
2019-12-3 | 18 | 10 | 0 | - | - | - | - | - | - | - |
2019-12-4 | 23 | 15 | 0 | - | - | - | - | - | - | - |
2019-12-5 | 26 | 20 | 0 | - | - | - | - | - | - | - |
2019-12-6 | 32 | 25 | 0 | 75.0 | 0.0 | 109.0 | 68.81 | 0 | 100 | - |
2019-12-9 | 38 | 30 | 0 | 90.0 | 0.0 | 125.2 | 71.88 | 0 | 100 | - |
2019-12-10 | 44 | 35 | 0 | 107.0 | 0.0 | 144.2 | 74.22 | 0 | 100 | - |
2019-12-11 | 47 | 40 | 0 | 125.6 | 0.0 | 162.3 | 77.37 | 0 | 100 | - |
2019-12-12 | 51 | 45 | 0 | 145.5 | 0.0 | 180.9 | 80.44 | 0 | 100 | 100 |
2019-12-13 | 54 | 50 | 0 | 166.4 | 0.0 | 198.7 | 83.74 | 0 | 100 | 100 |
💡 从表格可以看出,从 2019-12-6 开始正向指标远高于负向指标,DX 值保持在 100,说明趋势非常强。12月12日、12月13日 的 ADX 达到 100,也明确表明趋势力度极强,这种情况下,即便价格波动,趋势方向的可靠性很高。
用Python玩转ADX指标,轻松搞定趋势交易策略
首先,我们从AKShare库拿数据,随便挑了比亚迪,从2024年1月1日到2025年8月1日:
python
import akshare as ak
df = ak.stock_zh_a_hist(
symbol='002594',
period='daily',
start_date='20240101',
end_date='20250801',
adjust='qfq')
返回结果如下:
yaml
日期 股票代码 开盘 收盘 最高 最低 成交量 成交额 振幅 涨跌幅 涨跌额 换手率
0 2024-01-02 002594 64.18 61.84 64.18 61.77 113928 2.212162e+09 3.79 -2.83 -1.80 0.98
1 2024-01-03 002594 61.81 62.03 62.27 61.21 84486 1.624093e+09 1.71 0.31 0.19 0.73
2 2024-01-04 002594 62.42 61.98 62.53 61.34 89870 1.731882e+09 1.92 -0.08 -0.05 0.77
3 2024-01-05 002594 61.80 61.87 63.48 61.35 112402 2.187836e+09 3.44 -0.18 -0.11 0.97
4 2024-01-08 002594 61.91 60.78 62.20 60.69 81078 1.543894e+09 2.44 -1.76 -1.09 0.70
.. ... ... ... ... ... ... ... ... ... ... ... ...
378 2025-07-28 002594 111.32 111.01 111.71 110.52 117057 3.947001e+09 1.07 -0.28 -0.31 1.01
379 2025-07-29 002594 112.01 111.42 112.50 109.77 387360 4.322742e+09 2.46 0.37 0.41 1.11
380 2025-07-30 002594 108.05 108.70 111.16 107.12 524834 5.743879e+09 3.63 -2.44 -2.72 1.51
381 2025-07-31 002594 108.20 105.24 108.20 105.00 599499 6.344901e+09 2.94 -3.18 -3.46 1.72
382 2025-08-01 002594 104.95 105.80 106.24 104.36 362337 3.816660e+09 1.79 0.53 0.56 1.04
接下来,直接调用Python里的神器库ta
,计算ADX指标:
python
from ta.trend import ADXIndicator
adxi = ADXIndicator(
high=df['最高'],
low=df['最低'],
close=df['收盘'],
window=14,
fillna=False)
df['adx_pos'] = adxi.adx_pos()
df['adx_neg'] = adxi.adx_neg()
df['adx'] = adxi.adx()
得到的结果如下:
yaml
日期 股票代码 开盘 收盘 最高 最低 成交量 成交额 振幅 涨跌幅 涨跌额 换手率 adx_pos adx_neg adx
0 2024-01-02 002594 64.18 61.84 64.18 61.77 113928 2.212162e+09 3.79 -2.83 -1.80 0.98 0.000000 0.000000 0.000000
1 2024-01-03 002594 61.81 62.03 62.27 61.21 84486 1.624093e+09 1.71 0.31 0.19 0.73 0.000000 0.000000 0.000000
2 2024-01-04 002594 62.42 61.98 62.53 61.34 89870 1.731882e+09 1.92 -0.08 -0.05 0.77 0.000000 0.000000 0.000000
3 2024-01-05 002594 61.80 61.87 63.48 61.35 112402 2.187836e+09 3.44 -0.18 -0.11 0.97 0.000000 0.000000 0.000000
4 2024-01-08 002594 61.91 60.78 62.20 60.69 81078 1.543894e+09 2.44 -1.76 -1.09 0.70 0.000000 0.000000 0.000000
.. ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
378 2025-07-28 002594 111.32 111.01 111.71 110.52 117057 3.947001e+09 1.07 -0.28 -0.31 1.01 25.205620 19.053876 20.202389
379 2025-07-29 002594 112.01 111.42 112.50 109.77 387360 4.322742e+09 2.46 0.37 0.41 1.11 25.537332 17.360353 20.120903
380 2025-07-30 002594 108.05 108.70 111.16 107.12 524834 5.743879e+09 3.63 -2.44 -2.72 1.51 22.191630 23.159943 18.836205
381 2025-07-31 002594 108.20 105.24 108.20 105.00 599499 6.344901e+09 2.94 -3.18 -3.46 1.72 19.789164 26.855653 18.572874
382 2025-08-01 002594 104.95 105.80 106.24 104.36 362337 3.816660e+09 1.79 0.53 0.56 1.04 18.682433 27.257589 18.579524
现在我们有了三个核心数据:正向指标、负向指标和ADX本体,直接看就知道趋势强弱了。
可视化更直观 用matplotlib
画图,趋势一目了然:
python
import matplotlib.pyplot as plt
def plot_price_and_adx(price, adx, xlabel='日期'):
# 解决中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12,10), sharex=True) # 2行1列,x轴共享
# 上图:收盘价
ax1.plot(price, color='blue', label='收盘价')
ax1.set_ylabel('价格')
ax1.set_title('收盘价')
ax1.grid(True)
# 下图:ADX
ax2.plot(adx, color='red', label='ADX')
ax2.set_ylabel('ADX')
ax2.set_xlabel(xlabel)
ax2.set_title('ADX')
ax2.grid(True)
plt.tight_layout() # 自动调整间距
plt.show()
# 调用函数
plot_price_and_adx(df['收盘'], df['adx'])

不过光看ADX还是有点抽象,我们可以直接标记出ADX>25的强趋势区域:
python
import numpy as np
df['trend'] = np.where(df.adx>25, df['收盘'], np.nan)
df['trend_signal'] = np.where(df.adx>25, 1, 0)
plt.figure(figsize=(10,7))
plt.grid()
plt.plot(df['收盘'])
plt.plot(df['trend'])
plt.ylabel('Price')
plt.xlabel('Date')
plt.show()
看到没有?一条线标出来,告诉你哪段时间趋势强!
怎么用在交易上? ADX只告诉你趋势强弱,不告诉你方向。我们还需要结合其它指标,比如+DI > -DI → 看多
策略代码可以这样写,算出每日收益:
python
df['direction'] = np.where(df.adx_pos > df.adx_neg, 1, -1) * df['trend_signal']
df['daily_returns'] = df['收盘'].pct_change()
df['strategy_returns'] = df.daily_returns.shift(-1) * df.direction
plt.figure(figsize=(10,7))
plt.grid()
plt.plot((df['strategy_returns'] + 1).cumprod())
plt.ylabel('Returns')
plt.xlabel('Date')
plt.show()

ADX是趋势强弱的利器,但没有万能指标,最好搭配其他指标一起用,确认信号再出手,收益更稳。
总结一下今天的ADX之旅
今天我们从手工计算ADX指标 →到Python一键实现 →再到用ADX指导交易策略,完整走了一遍流程。
💡 小结几点:
- ADX执行起来其实很简单,帮我们快速找到市场中的强趋势。
- 虽然它有局限性(比如不告诉你趋势方向),但是配合其他指标使用,交易策略会更稳、更可靠。
- 用Python操作,让数据处理和策略回测变得轻松又高效,再也不用靠Excel算到手抽筋😂。
免责声明 本文所有数据仅供参考,花姐不保证信息的完整性、准确性或时效性,也不对因使用本文信息而产生的任何损失负责。信息提供均为"原样"提供,投资有风险,入市需谨慎。