MACD 是最常见的技术指标之一,也是最容易被“同名不同值”困扰的指标。两只软件都写着 12、26、9,画出来的 DIF 和柱状图却可能不同。差异通常不在公式本身,而在指数移动平均的初始化、预热期长度、价格口径和柱状图倍数。

一、EMA 的递归公式

指数移动平均 EMA 的标准递归写法是:EMA_t = α × P_t + (1 − α) × EMA_{t−1},其中 α = 2 ÷ (N + 1)。以 N = 12 为例,α 约为 0.1538;N = 26 时,α 约为 0.0741。权重随时间指数衰减,越新的价格影响越大。

递归公式需要一个起点。常见做法有两种:一是把第一根价格直接作为 EMA 的初始值;二是用前 N 根价格的简单平均作为初始值。两种做法在最初几十根 bar 上差异明显,随着时间推移会逐渐收敛,但收敛速度取决于 α 和价格波动。

pandas 的 ewm 提供了 adjust 参数。adjust=False 时按递归公式逐期更新,默认以第一根观测作为初始值;adjust=True 时使用归一化权重,早期结果相当于对已有观测做加权平均(来源 3)。两者不是“谁更正确”,而是两种不同的有限样本处理方式,必须在研究记录中写明。

二、DIF、DEA 与柱状图

常见定义是:DIF = EMA(P, 12) − EMA(P, 26);DEA = EMA(DIF, 9);柱状图 = 2 × (DIF − DEA)。12、26、9 这组参数因早期软件和 Murphy 的整理而广泛流传(来源 4)。国内软件多采用 2 倍柱状图,海外软件有时直接使用 DIF − DEA。倍数只改变柱子的尺度,不改变金叉、死叉的时点,但会让不同平台的图形看起来差异很大。

DEA 的初始化同样存在选择。DIF 的第一根值依赖两条 EMA 的起点,DEA 的第一根值又依赖 DIF 的起点。若把 DIF 的前 9 根做简单平均作为 DEA 起点,与直接把第一根 DIF 作为 DEA 起点,早期的交叉信号可能相差数个 bar。

因此,比较两个平台的指标时,第一步不是争论参数,而是对齐三件事:价格序列是否相同、EMA 初始化是否相同、柱状图是否使用 2 倍。任何一项不同,都不应该直接比较数值。

三、两个可复现的数值示例

先看 EMA 初始值的收敛速度。假设某证券前 11 个交易日收盘价均为 100 元,第 12 日涨到 110 元并保持不变;N = 12,α = 2/13。用第一根价格 100 作为起点,与用前 12 日均价 100.83 作为起点,第 12 日的 EMA 分别约为 101.54 和 102.24,相差约 0.71 元。此后两者按 0.8462 的比例逐日收敛,再经过 26 个交易日,差距缩小到约 0.01 元。这就是预热期的含义:不是初始值消失了,而是影响衰减到可接受范围。

再看 DEA 初始化对交叉信号的影响。构造一组逐日上升 0.1 的 DIF 序列:−1.0、−0.9、−0.8……,DEA 平滑系数取 0.2。若 DEA 起点取第一根 DIF(−1.0),第 2 根就出现 DIF 上穿 DEA;若起点取前 9 根 DIF 的均值(−0.60),上穿推迟到第 5 根,相差 3 个 bar。同一组 DIF,仅因 DEA 起点不同,信号日期就会移动。下表为构造示例,不对应任何真实证券。

交易日 DIF DEA(首值 −1.0) DEA(前 9 均值 −0.60)
1 −1.0 −1.000 −0.600
2 −0.9 −0.980 −0.660
3 −0.8 −0.944 −0.688
4 −0.7 −0.895 −0.690
5 −0.6 −0.836 −0.672

用 pandas 可以复现上述过程。注意 ewm(adjust=False) 默认以第一根观测为种子,若要改用前 N 根均值做种子,需要先手工构造初始序列,再逐期递推:

import pandas as pd

prices = pd.Series([100.0] * 11 + [110.0] * 60)
ema12 = prices.ewm(span=12, adjust=False).mean()
ema26 = prices.ewm(span=26, adjust=False).mean()
dif = ema12 - ema26
dea = dif.ewm(span=9, adjust=False).mean()
hist = 2 * (dif - dea)

代码本身只保证公式一致,不保证与某个软件一致。若软件使用的是简单平均种子,或者对 DIF 做了不同的平滑,结果仍会不同。复现时应对齐种子和预热长度,并保存价格序列与复权因子。

四、预热期与参数敏感性

EMA 是无限记忆的,理论上初始值永远不会完全消失。实践中需要设定预热期,让初始值的影响衰减到可忽略。经验上,预热长度至少取最长周期的三到五倍;对 26 日 EMA,前 100 根 bar 通常足以让差异变得很小。若研究从上市首日就开始计算,早期指标应视为不稳定。

参数也不是固定的。12、26、9 只是常见约定,不同市场、不同持有周期会使用 5、35、5 或 8、17、9 等组合。参数越短,指标越灵敏,也越容易被噪声触发;参数越长,信号越平滑,但滞后越明显。比较参数时,应同时报告信号次数、平均持有期、换手和不同市场阶段的稳定性。

价格口径同样重要。用收盘价、典型价(最高、最低、收盘的平均)或复权价计算,会得到不同曲线。除权日附近,原始价格会出现跳空,指标可能被动产生一个交叉;使用复权价可以减少这种伪信号,但复权方法本身也要固定版本。

五、指标解释的边界

MACD 本质上是两条不同速度的指数平均线之差,再加上一条对差值再做平滑的信号线。它描述的是价格趋势的变化速度,不是价格一定会继续沿原方向运动。金叉和死叉只是两条线的相对位置变化,不能单独构成完整的交易规则。

把该指标用于研究时,至少应明确:使用哪个价格、哪个周期、如何初始化、预热多长、柱状图是否乘 2、信号在收盘后还是盘中生成。若做回测,还要考虑信号生成时间与成交时间的间隔,避免用当日收盘价生成信号、又用同一收盘价成交。

对于分红送转频繁的证券,复权处理会显著影响长期曲线。前复权序列会随新的权益分派整体变化,今天保存的历史值在下一家公司分红后可能被重新缩放;后复权序列更稳定,但价格水平偏离当前报价。研究应保存复权因子和计算日期,而不是只保存指标值。

六、复核清单

  • 价格序列是原始价、前复权还是后复权,复权因子版本是否记录;
  • EMA 初始值采用第一根价格还是前 N 根均价,是否与目标平台一致;
  • 预热期是否足够,早期指标是否被排除在统计之外;
  • DIF、DEA 的周期是否与柱状图倍数一起记录;
  • 信号生成时间与成交假设是否分离,是否存在前视偏差;
  • 参数敏感性是否用样本外数据检验,是否报告换手与成本。

小结

两个平台的数值不一致时,先对齐价格、种子、预热和倍数,再讨论参数优劣。若研究目标是复现某个软件,就按该软件的种子与预热规则实现;若目标是做跨平台比较,就统一用同一套价格和预热期重算。把口径写进研究记录,比记住某个具体数值更可靠。更多指标计算方法,可参见技术指标栏目。