跳到正文
进阶指标2026-08-1015分钟阅读

MACD:被误用最多的指标

目录(10 节)
  1. 写在前面
  2. 一、定义:它在回答什么问题
  3. 二、公式:为什么是"差的差"
  4. 三、三个实现细节坑
  5. 四、它能干什么(两个用法,都很克制)
  6. 五、实测:期货上多出来的三处麻烦
  7. 六、失效场景(请比第四节读得更用力)
  8. 七、代码
  9. 八、三个你该自己跑一遍的实验
  10. 九、三句话结论

写在前面

一个具体的场景。

你打开行情软件,切到「沪铜主连」,日线。MACD 刚刚金叉,柱子由绿转红。你下单——买入 cu2601。

这一步里藏着一个几乎没人注意的错位:

你判断用的那条线,和你下单买的那份合约,不是同一个东西。

主连是把一份份到期的合约首尾接起来拼出来的一条曲线,它自己不是合约,你下不了单——这件事之前专门讲过。但当时讲的是"接缝处那个跳空是假的"。

MACD 的麻烦比那个深一层。因为它是一个有记忆的指标。

EMA 的每一个值都压着它之前所有值的影子。所以接缝造成的那一下扰动,不会在换月当天结束——它会在那条线的记忆里住下来,住很久。

你看的那根 MACD,有一段记忆属于一份你从来没有持有过的合约。

住多久、有多深、会不会真的改掉一个金叉——这三个数就是本篇的正文。

先说清这篇不做什么:不做"金叉死叉的胜率是多少"的回测。那需要完整的回测框架、成本假设和样本外检验,是另一个栏目的活。本篇要说的是更前置的一件事——在你回测它之前,先确认你手里那条线是干净的。


一、定义:它在回答什么问题

MACD(Moving Average Convergence / Divergence),Gerald Appel 在 1970 年代提出。名字直译过来是「移动平均的收敛与发散」——名字里就写着答案。

它由三个部件组成:

部件算什么中文常见叫法
DIF快均线 − 慢均线差离值、快线
DEADIF 自己的平滑讯号线、慢线
柱DIF − DEA(国内普遍再乘 2)柱状图、能量柱

一句话定义:

MACD 测的是"快慢两条均线之间的距离,正在变大还是变小"。

距离变大,说明快线在加速甩开慢线,趋势在加速。 距离变小,说明快线在往回靠,趋势在减速。

请把这两个词咬住:加速、减速。

⚠️ MACD 测的是趋势的加速度,不是趋势的方向。

这是它的头号误用来源:把"减速"读成了"要反转"。

你可以想成划船:桨划得慢下来,船不会立刻倒退——它还带着惯性往前漂。

"桨慢了"和"船退了"是两件事,而 MACD 只看得见桨。它只知道推力在减弱,不知道船接下来往哪儿去。


二、公式:为什么是"差的差"

DIF=EMA12−EMA26DIF = EMA_{12} - EMA_{26} DEA=EMA9(DIF)DEA = EMA_{9}(DIF) 柱=2×(DIF−DEA)\text{柱} = 2 \times (DIF - DEA)

(EMA 就是加权更偏向近期的那种均线。它和 SMA、和 Wilder 平滑的差别,在 ATR 那一篇里已经拆过,这里不重复。)

值得说的是这个结构:它做了两次减法,而每一次减法都丢掉一层信息,换来一层灵敏。

第几层做了什么丢掉了什么
价格 → 均线平滑丢掉日内噪音
均线 → DIF快慢相减丢掉价格的绝对水平
DIF → 柱再减一次丢掉速度本身,只剩"速度在变吗"

第二行是关键:做完这一步,MACD 已经不知道价格是 3000 还是 30000 了。

它只知道两条均线拉开了多少。这也解释了为什么不同品种的 DIF 数值不能横向比大小——和 ATR 的绝对值不能跨品种比是同一个道理。

MACD 离价格隔着两层。两层之外的事,它一概不知道。

12、26、9 是哪来的?

没有公开的推导。 Appel 本人没有给出数学论证,后来也没有人补上。

流传最广的说法是"12 ≈ 两周、26 ≈ 一个月、9 ≈ 一周半"。这个口诀你可以自己验一下:按一周五个交易日算,12 天是 2.4 周、26 天是 5.2 周,哪个都对不齐。

它要能对齐,得假设一周有六个交易日——而美股结束周六交易,比 MACD 被提出来还早了二十多年。这更像是后人补上去的记忆口诀,不是当初的设计依据。

真正该记住的是另一件事:

这三个数,没有一个是为国内期货定的,更没有一个是为你做的那个品种定的。

那该不该改?

这里和 ATR 不一样。ATR 那篇说过"别在参数上花太多时间",因为 ATR 测的是波动率,而波动率本身有很强的持续性,12 和 20 算出来趋势一致。

MACD 没有这个性质。 它测的是差值,而差值会把参数的变化放大——12/26 改成 10/22,交叉点的位置可能整片挪动。

但也正因为它敏感,调参数是最容易滑进"拟合"的地方:你在历史图上把参数拧到金叉刚好都对上,这件事永远做得到,而它什么也证明不了。一个在历史上调出来的参数,和一个能赚钱的参数,中间隔着的东西比这个参数本身大得多。

我的建议:先用默认值,把下面三个坑填了再谈调参。绝大多数人的 MACD 出问题,不是因为参数不对,是因为喂给它的价格序列不对。


三、三个实现细节坑

① 柱状图,国内乘 2,国外不乘

国内绝大多数行情软件画的柱是 2 × (DIF − DEA),而国外的主流实现普遍不乘这个 2。

同一天、同一个品种,两边的柱子高度差整整一倍。

这不影响交叉的位置(乘个正数不改变正负号),但只要你用到柱子的高度——"柱子缩短了三分之一""柱高突破前高"——就必须先问清楚对方用的是哪种画法。

② 价格口径:收盘价还是结算价

这是期货独有的一个坑,股票上根本不存在。

期货每天有两个"收官价格":收盘价是最后一笔成交,结算价是全天成交量加权均价,两者的定义与差别在结算那一篇里讲过。而不同数据源、不同软件默认给你哪一个,并不统一。

按四象限那篇定下的规矩:口径要按"你在测什么"选。MACD 测的是价格序列自身的走势形态,该用收盘价——结算价是一串日均价,拿它算出来的序列会比真实价格平滑,交叉点会跟着挪。

差多少?我把两种口径各跑了一遍,数字在第五节末尾。

③ EMA 从哪一根开始算

EMA 是递推的,第一个值怎么定,后面全跟着变。不同库的默认行为不一样(有的从第一根开始递推,有的先取一段简单平均当种子)。

差异在开头几十根 K 线上明显,之后收敛——这一条和 ATR 那篇的实现细节是同一回事。

但请注意它在期货上会变得更要命,原因见第五节 ④:期货的单一合约,热起来的那段日子本身就没有多长,收敛所需的那段预热,要从这段日子里扣。


四、它能干什么(两个用法,都很克制)

用法一:当减速探测器,不当方向指示器

柱子由长变短,说明趋势在减速。这是 MACD 唯一真正擅长的事。

它的正确用途是提醒你去检查——你手上那个顺势仓位,推动它的那股劲儿正在退。至于要不要减仓、要不要出,那是仓位管理的事,不是 MACD 的事。

它不告诉你反手。 减速之后可能是横盘、可能是再加速、也可能是反转,三者在柱子上早期长得一模一样。

用法二:当过滤器,不当信号

比如:只在 DIF 位于零轴上方时考虑多头方向的入场,零轴下方只考虑空头方向。

注意这里 MACD 的角色——它没有给你入场点,它只是把一半的方向划掉了。入场点得由别的东西给(价格结构、突破、事件)。

这两个用法,没有一个会产生入场点。 如果你的系统里 MACD 是那个"扣扳机"的东西,那你用错它了。


五、实测:期货上多出来的三处麻烦

怎么测的

取成交额前 8 的品种——沪银、沪金、原油、棕榈油、天然橡胶、沪铜、锡、焦煤。品种池是事前定死的(直接沿用上一篇涨跌停实测排好的成交额名次),不因为"某个品种接缝大"而临时加人。

  • 样本:699 份单一合约 / 12792 个合约日 / 331 次主力换月,2020 年 1 月起
  • 两条线:A = 未调整的主连(该跳就跳,你在软件里看到的那条);B = 把每次接缝的价差减掉之后的主连
  • 价格用收盘价,不用结算价

⚠️ 先说清这不是什么:这里没有回测、没有成本假设、没有仓位规则。下面所有数字都不回答"MACD 赚不赚钱",只回答"你手里那条线干不干净"。


① 接缝在 MACD 里住多久:这一条不用测

先说一个我原本准备实测、结果发现根本不需要测的事。

A 和 B 只差一个"从换月那天起整体平移一段"的动作。而 EMA 是线性的,于是两条线的 DIF 之差,恰好等于接缝自己的 MACD——里面一点价格信息都没有,只剩 12 和 26 这两个参数。

所以"污染多久散掉"这个问题,推导就能答尽:

换月之后DIF 上还残留着接缝价差的……
第 1 个交易日8.0%
第 8 个交易日27.8%(峰值)
第 15 个交易日22.3%
第 28 个交易日才降到 10% 以下
第 38 个交易日才降到 5% 以下

注意峰值不在换月当天,在换月之后第 8 个交易日——快慢两条 EMA 消化这个跳的速度不一样,差距要过一周多才拉到最大。

这张表对所有品种、所有行情都成立,因为它压根不含行情。我拿真实数据里那些"距上一次换月超过 60 个交易日"的孤立接缝验了一遍,实测第 8 日 27.7%,理论 27.8%——逐点重合。

换月这件事,在价格上是一天,在 MACD 上是两个月。


② 接缝有多大:这个才要测,而且分两种品种

品种接缝价差中位主力任期中位
焦煤7.22%80 个交易日
棕榈油4.32%81
天然橡胶1.50%82
原油0.71%20
沪银0.34%46
沪金0.27%42
锡0.16%20
沪铜0.13%21

这张表分成了泾渭分明的两组,而且恰好是两条不同的中毒路径:

  • 焦煤、棕榈油、橡胶:主力月只有那么两三个(1/5/9 这一类),一换就跨四个月,接缝大——焦煤中位数就 7.22%,样本里最大的一次是 2022 年 12 月从 jm2301 换到 jm2305,−18.98%。好处是八十来个交易日才换一次,够散干净
  • 沪铜、锡、原油:月月都有合约,接缝很小(铜的中位数只有 0.13%)。但它们每二十来个交易日就换一次——而上面那张表说,散干净要 38 个交易日

第二种情况值得单独说一句。全样本的主力换月间隔中位数是 22 个交易日,73.1% 的间隔短于 40 个交易日。

对换月频繁的品种,上一次接缝还没散干净,下一次已经来了。 那条 DIF 从来没有回到过干净状态。


③ 那到底有没有影响:两个数

前面两条都是"输入"。真正要回答的是:这堆污染,改掉我看到的东西了吗?

第一个数,污染相对 DIF 自身有多大(不是相对价格,是相对这条线本身的幅度):

中位数7.7%
超过 10% 的交易日44.7%
超过 25% 的交易日26.7%
超过 50% 的交易日15.8%
超过 100% 的交易日8.7%

最后一行的意思是:有 8.7% 的交易日,接缝带来的偏移比 DIF 本身还大。

第二个数,也是最终答案——信号真的被改掉了多少:

品种脏线信号净线信号对不上错配率
沪银10811062.8%
沪金12612683.2%
沪铜120114166.8%
天然橡胶112124187.6%
锡130136249.0%
原油1211272610.5%
棕榈油1161183615.4%
焦煤1171155021.6%
合计9509701849.6%

"对不上"分两种:接缝凭空造出来的信号(真实价格里没有),和被接缝抹掉的信号(真实价格里有、主连上没有)。两种各占一半。

每十个金叉死叉里,大约有一个是接缝的产物,或者被接缝吃掉了。

注意错配率并不是简单跟着接缝大小走。 焦煤接缝最大(7.22%)、错配率也最高(21.6%),这符合直觉;但沪铜接缝只有 0.13%、错配率仍有 6.8%,锡 0.16% 对 9.0%——因为它们换得太勤,小接缝乘上次数,一样能改掉信号。

大接缝一次到位,小接缝细水长流,两条路通向同一个地方。


④ 那换成单一合约呢:躲开接缝,撞上寿命

既然主连脏,直接在你要交易的那份合约上算 MACD——这是对的做法,但它有自己的代价。

MACD 要 26 + 9 = 35 个交易日才算预热完(在此之前 DEA 还没稳定)。而:

  • 主力任期中位数:22 个交易日
  • 合约活跃期中位数:37 个交易日(活跃期 = 持仓量达到它自己峰值一半以上的那段日子)
  • 42.9% 的合约,活跃期短于 35 个交易日
品种活跃期中位vs 35 天预热期
锡26不够
原油28不够
沪铜39刚够
沪银49够
沪金58够
棕榈油78够
焦煤79够
天然橡胶82够

(样本 289 份合约,两头被样本期截断的已全部剔除——不剔的话活跃期会被系统性算短。)

你当然可以从这份合约挂牌第一天就开始算 MACD,那样预热绰绰有余。但挂牌初期它是一份没什么人交易的冷清合约,那段价格本身就是噪音,临近到期又会迅速塌掉。你拿噪音去喂一个有记忆的指标,它会老老实实把噪音记住。

于是就有了这个两难:

主连不干净,单合约不够长。在期货上,你没有一条既真实又足够长的价格序列可以拿来算 MACD。

这不是让你别用,是让你知道自己站在哪一边。 我的选择是:在单一合约上算,接受前 35 个交易日的信号不看;如果非要用主连,就先把接缝减掉(代码见第七节)。


⑤ 滞后的量级:同样的迟到,期货上要乘杠杆

MACD 滞后是常识,不需要证明,但量级值得标定一次。

在干净序列上找出所有事后确认的局部低点(前后各 10 个交易日最低),看第一个金叉什么时候来(748 个样本):

金叉比低点晚5 个交易日(中位数)
信号发出时,价格已经走了3.94%(中位数)
折成账户读数(5 倍真实杠杆)19.7%

⚠️ 局部低点是事后定义的,你在当下不知道那是低点。这组数只用来度量"滞后有多大",不构成任何可交易的规则。

最后一行才是期货独有的那部分。3.94% 在一个不带杠杆的账户上是 3.94%;而账户的波动约等于价格波动乘以你的真实杠杆,5 倍下就是接近两成。

滞后本身股票也有。期货多出来的是那个乘号。


附带:换个价格口径,信号又变一批

同一条干净主连,价格从收盘价换成结算价,其余一个字不改:

970 个信号 vs 920 个信号,对不上 130 个,错配率 6.9%。

比接缝那 9.6% 小一些,但同样是白送的误差——而它只取决于你的数据源默认给了你哪一列。


这批数据打几折

  1. 它不回答 MACD 赚不赚钱。 没有成本、没有仓位、没有出场规则,本篇一次回测都没做。"信号被改掉了 9.6%"和"这个策略行不行"是两个问题
  2. 主力判定用了前视信息(防抖要看后面三天),实盘做不到。这里只拿它把接缝位置定准,不是可交易规则
  3. 只有 8 个品种,而且是成交额最靠前的一档。 冷清品种的接缝只会更难看,分母小、一个大户挪仓就能翻倍
  4. 日线答不了日内。 60 分钟、15 分钟的 MACD 会怎样,这批数据一个字都说不了
  5. "净主连"只是一种拼接法(等差价差调整)。哪种拼接更好是另一个题目,本篇没碰——但用任何一种,都比不减强

六、失效场景(请比第四节读得更用力)

① 震荡市里,它会一直给信号,而且每个都讲得通

这是老手都见过的:横盘里 MACD 反复金叉死叉,来回打脸。我不打算用数据去"证明"一件从业者天天看见的事,只提醒一句它为什么危险——

不是因为信号多,是因为每一个信号事后都能讲出一套道理。用四象限那篇里的话说,讲得通,正是这类读法最危险的地方。

② 背离:只能事后确认

"价格创新低但 MACD 没创新低,是底背离"——这句话本身没错,错的是它的可用性。

在一个底背离成为底背离之前,它和"下跌中继"长得完全一样。你只有等到价格真的转上去,才能回头说"那是背离"。

一个只能在事后被认出来的形态,不能拿来在事前做决策。

③ 它的参数不是为你定的(承接第二节)

12/26/9 来自 1970 年代的美股。你做的可能是一个 2023 年才上市、日内波动是美股几倍的品种。这三个数没有任何理由恰好适合它。

④ 信号需要成交才能兑现

MACD 死叉让你出场,但如果价格封在跌停板上,你出不去。这一条在涨跌停那篇里已经讲透,ATR 那篇也从止损角度说过,这里只挂链,不重复。

指标画在屏幕上,成交发生在盘口上。这两件事之间没有必然联系。

⑤ 它不回答仓位——而在期货上,这一条能要命

MACD 就算全对,也只告诉你方向和时机,一个字都没说该开多少手。

而期货是带杠杆的。同样一次判断失误,在不同仓位下是完全不同的两个结果。第五节 ⑤ 那组数字讲的正是这件事:同样的滞后,在股票上是几个点,在期货上要乘以你的真实杠杆。

⑥ 就算某个信号真有统计优势,那也不等于能交易

概率不是收益、没扣手续费、没算滑点——这一整套账在四象限那篇里算过一遍,对 MACD 同样适用,不再重述。


七、代码

老规矩,计算逻辑写成纯函数,不绑定任何数据源。有一列按时间升序的收盘价就能跑。

import pandas as pd

def macd(close: pd.Series, fast: int = 12, slow: int = 26, signal: int = 9,
         hist_x2: bool = True) -> pd.DataFrame:
    """DIF / DEA / 柱。

    hist_x2: 柱要不要乘 2。国内软件普遍乘,国外普遍不乘 —— 见第三节 ①。
             它不改变交叉位置,但只要你用到柱高就必须对齐口径。
    """
    dif = (close.ewm(span=fast,  adjust=False).mean()
           - close.ewm(span=slow, adjust=False).mean())
    dea = dif.ewm(span=signal, adjust=False).mean()
    hist = (dif - dea) * (2 if hist_x2 else 1)
    return pd.DataFrame({"dif": dif, "dea": dea, "hist": hist})

def crosses(m: pd.DataFrame) -> pd.Series:
    """+1 金叉、−1 死叉、0 没事。"""
    d = m["dif"] - m["dea"]
    return ((d > 0) & (d.shift(1) <= 0)).astype(int) \
         - ((d < 0) & (d.shift(1) >= 0)).astype(int)

下面这个才是本篇最该带走的函数——把接缝抹掉:

def splice_adjust(px: pd.Series, switch_days, gaps) -> pd.Series:
    """等差价差调整:把换月造成的那一跳从序列里减掉。

    switch_days : 每次换月生效的那一天(新主力的第一天)
    gaps        : 对应的价差 = 切换前一日「新主力收盘 − 旧主力收盘」

    ⚠️ 这只是**一种**拼接法。哪种更好是另一个题目,本篇不碰。
       但用任何一种,都比直接拿未调整的主连算 MACD 强。
    """
    adj = pd.Series(0.0, index=px.index)
    for day, g in zip(switch_days, gaps):
        adj.loc[day:] += g          # 从换月那天起,之后全部平移
    return px - adj

⚠️ 拿不到各合约明细、算不出 gap 怎么办? 那就别在主连上算 MACD,直接在你正要交易的那份合约上算——代价是第五节 ④ 那个预热问题,但至少序列是真的。 两害相权,请选真的那个。


八、三个你该自己跑一遍的实验

实验一:把两条 DIF 画在一起

同一个品种,一条用未调整主连、一条用价差调整后的主连,把两条 DIF 画在一张图上,在横轴上标出换月日。

你会看到:每个换月日之后,两条线分开,然后用一两个月慢慢合拢。这张图是本篇最值得自己做一遍的东西——做完你很难再直接相信软件里那根主连 MACD。

实验二:数一数信号差几个

把两条线上的金叉死叉各列一张表,对一遍。

你要看的:有几个信号只出现在未调整的那条线上(接缝造出来的),有几个只出现在调整后的那条线上(被接缝抹掉的)。

实验三:把收盘价换成结算价,再跑一遍

一个字都不用改逻辑,只换价格列。

你要看的:交叉点挪了几天、总数差了几个。这个实验和四象限那篇的实验三是同一个动作——同一份数据、同一段代码,换一个口径就换一批结论,这件事值得你亲手撞一次。


九、三句话结论

1. MACD 测的是加速度,不是方向。 柱子变短说明推力在退,不说明要掉头。把"减速"读成"反转",是它最贵的一种误用。

2. 在期货上,先确认序列,再谈信号。 主连有接缝、单合约有寿命——两条路都不干净,你至少要知道自己走的是哪一条、脏在哪儿。

3. 它不扣扳机。 MACD 最多帮你划掉一半方向、提醒你趋势在减速。入场、止损、仓位,一个都不归它管——而在期货上,最后那个才是决定你能不能活下来的。


下一篇:《一个品种一张图 · 多晶硅》——光伏这条产业链上,中美两边各自在做什么,以及它落到那张合约上隔着几道工序。


⚠️ 风险提示 本文仅为期货知识分享与研究交流,不构成任何投资建议。文中所有指标参数、算例与代码均为原理演示,不构成任何交易参数或交易信号推荐,历史数据与统计结果不代表未来表现。期货交易具有高杠杆特性,可能导致本金全部损失甚至产生穿仓负债。文中涉及的合约规则、涨跌停等信息以各期货交易所官方最新公告为准。请通过正规期货公司开户,理性参与、独立决策、风险自担。

本文首发于微信公众号「米粒论期」 · 阅读原文

免责声明:本文仅供学习参考,不构成任何投资建议。期货交易存在风险,入市需谨慎。

本文涉及

文中提到的概念、品种和书目,都能在站内查到。

沪ICP备2026050790号-1