跟风还是反转?用 ADX 判断趋势强度,Python 教程全程带你飞

炒股的朋友们都知道,趋势是咱们交易里的"风向标"。可光知道方向还不够呀,你得知道这股风到底是微风徐徐,还是飓风呼啸!😂 这就是 ADX(Average Directional Index,平均趋向指标) 登场的地方。

为什么要测趋势的"强度"呢?很简单:

  • 趋势弱 → 随时可能反转,交易胜率打折。
  • 趋势强 → 上车后跟着走,成功率和人均盈利都更香。

不过,这里有个小秘密------别被名字骗了,ADX 并不告诉你趋势的方向!它只是告诉你"风有多大"。那方向咋办?别急,ADX 有两位好搭档:

  • +DI(正向指标) → 检测上涨趋势
  • -DI(负向指标) → 检测下跌趋势

所以,ADX 就是趋势强度的量尺,+DI 和 -DI 则是方向指南针,三剑合璧,才算完整。

接下来,花姐会依次聊聊:

  1. ADX 指标到底是啥?
  2. 它的计算逻辑(数学党最爱)
  3. 用 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 的计算逻辑

讲到指标,免不了得撸一遍"数学流程图"。别怕,这里我帮你分了几步拆开讲,简单清晰:

  1. True Range(真实波动范围) 衡量一天价格的真实波动。比单纯的 High - Low 更全面。

  2. +DM(正向动向) 今天的高点比昨天高多少,如果比低点变化更大,那算上涨动向。

  3. -DM(负向动向) 今天的低点比昨天低多少,如果比高点变化更大,那算下跌动向。

  4. 平滑处理 Wilder 很喜欢平滑,直接用指数平滑(类似移动平均)来消除噪音。

  5. +DI 和 -DI 把 +DM 和 -DM 分别除以 True Range,然后算百分比,得到 +DI 和 -DI。

  6. 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(真实波动范围)

👉 公式其实也不难,就是三者取最大:

  1. 当前最高价 - 当前最低价
  2. |当前最高价 - 昨日收盘价|
  3. |当前最低价 - 昨日收盘价|

选最大值,就是当天的 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.07107%

  • 而我们的 -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指导交易策略,完整走了一遍流程。

💡 小结几点:

  1. ADX执行起来其实很简单,帮我们快速找到市场中的强趋势。
  2. 虽然它有局限性(比如不告诉你趋势方向),但是配合其他指标使用,交易策略会更稳、更可靠。
  3. 用Python操作,让数据处理和策略回测变得轻松又高效,再也不用靠Excel算到手抽筋😂。

免责声明 本文所有数据仅供参考,花姐不保证信息的完整性、准确性或时效性,也不对因使用本文信息而产生的任何损失负责。信息提供均为"原样"提供,投资有风险,入市需谨慎。

相关推荐
aFakeProgramer13 分钟前
使用 ROS2 构建客户端-服务器通信:一个简单的计算器示例
开发语言·python·ros2
jinlei20091 小时前
在python 代码中调用rust 源码库操作步骤
开发语言·python·rust
mit6.8241 小时前
[Sync_ai_vid] 唇形同步评判器 | 图像与视频处理器 | GPU测试
人工智能·python
float_六七2 小时前
Apache Commons Lang 3
开发语言·python·apache
栒U2 小时前
从高层 PyTorch 到中层 CUDA Kernel 到底层硬件 Tensor Core
人工智能·pytorch·python
精灵vector2 小时前
基于视觉的网页浏览Langraph Agent
python·aigc·ai编程
AiPy_极客团长3 小时前
AI解决生活小事系列——用AI给我的电脑做一次“深度体检”
人工智能·python·电脑维修·实战技巧
小王爱学人工智能3 小时前
神经网络模型搭建及手写数字识别案例
pytorch·python·神经网络
Go 鹏ya3 小时前
【Python学习笔记】whl包打包
笔记·python·学习