写在前面
一个几乎每个人都问过的问题:
"我该用 MA 还是 EMA?"
网上流传最广的答案是:"EMA 更灵敏、反应更快,适合短线;MA 更稳,适合中长线。"
这句话对一半,而错的那一半,恰恰是大多数人拿它做决定的那一半。
对的那一半:对今天这一根,EMA(20) 的反应确实大约是 MA(20) 的两倍。
错的那一半:对一段持续的趋势,两条线落后价格的距离一模一样,一分钱不差。
而且这不是巧合,也不是恰好。它是被人特意凑出来的:
EMA(20) 之所以叫"20",就是因为有人特意把它调成了和 MA(20) 一样慢。
这一篇要做的事,是把整个均线族——MA、EMA、WMA、还有 ATR 用的那个 Wilder 平滑——装进同一个式子里,然后回答三个问题:
- 它们到底差在哪儿(不是快慢)
- 滞后有多大(这个数可以算,不用测)
- 在国内期货上,这套东西你实际能不能用(这一条要数据)
先说清这篇不做什么:不做"均线金叉的胜率是多少"的回测,一次都没做。那是另一个栏目的活。
一、定义:均线在回答什么问题
移动平均线(Moving Average),一句话定义:
它把过去一段时间的价格做加权平均,然后把这个平均值,画在今天这个位置上。
请把"画在今天这个位置上"这几个字咬住。它是全篇所有麻烦的源头。
这个数本身没有问题——它诚实地描述了"过去这一段,价格的中心在哪儿"。问题出在它被画的位置:一个属于过去的数,被摆在了今天的坐标上,于是看图的人自然而然地把它当成了一个"今天的价位"。
它不是。
⚠️ 均线不回答"现在贵不贵",也不回答"接下来往哪儿走"。
它只回答一件事:过去那一段的中心在哪儿。 而那个中心站在多少天以前,是你选参数的时候就定死的。
「均线站在多少天以前」——这个数就是本篇的主角。它有个名字,叫平均年龄。
二、数学本质:整个均线族只有一个式子
2.1 它们只是权重形状不同
所有均线都是同一个东西:一组非负的、加起来等于 1 的权重。
区别只在这组权重长什么样:
| 均线 | 权重形状 | 一句话 |
|---|---|---|
| SMA(n) | 矩形:前 n 根各 1/n,再往前是 0 | 一视同仁,然后一刀切断 |
| EMA(α) | 指数衰减: | 越近越重,但永远不切断 |
| WMA(n) | 三角形:n, n−1, …, 1 | 线性递减,也在 n 根处切断 |
| Wilder(n) | 指数衰减, | EMA 的一种,衰减更慢 |
(这四种的算法差别,ATR 那篇已经拆过,这里不重复。本篇要问的是它们各自站在多少天以前。)
2.2 滞后 = 权重的重心
既然均线是一堆过去价格的加权平均,那么"它代表哪一天"这个问题,就有一个再自然不过的答案:权重的重心。
算出来是这样:
| 均线 | 平均年龄 |
|---|---|
| SMA(n) | (n−1)/2 |
| EMA(α) | (1−α)/α |
| WMA(n) | (n−1)/3 |
| Wilder(n) | n−1 |
第一行就够很多人吃一惊了:
MA(20) 的滞后不是 20 天,是 9.5 天。
它平均代表的是九天半以前的价格中心,不是二十天以前。这个数比大多数人以为的小一半,而它决定了后面所有的事。
2.3 ⭐ α = 2/(n+1) 是哪来的
EMA 真正的参数是 α,不是"20 日"。所谓 EMA(20),是软件替你把 α 定成了 2/(20+1)。
这个公式没人解释过它是怎么来的。它其实是一个方程的解——
令 EMA 的重心等于 SMA(n) 的重心:
就是它。
"EMA(20)" 这个叫法的全部含义就是:它的重心被凑得和 MA(20) 一样。
所以开头那句"EMA 更快"错在哪儿,现在清楚了:在"重心"这个意义上,同周期的 EMA 和 MA 一样慢,因为这就是当初设计它的目的。 快的只是它对最新一根的反应——权重 α = 2/(n+1),大约是 SMA 那个 1/n 的两倍。
对单根价格更敏感,对整段趋势一样迟钝。 这两件事同时成立,而它们经常被混成一件事讲。
2.4 ⭐ 顺带补上一个数:那个 27 是怎么来的
ATR 那篇提过一句:Wilder 的 14 期平滑,强度大致相当于 27 期的常规 EMA。 当时只给了结论,没给来历。
现在可以补上了。Wilder 的 α = 1/n,重心 = n − 1 = 13。而 SMA(m) 的重心是 (m−1)/2,令它等于 13,解出 m = 27。
这个数不是谁试出来的,是解出来的。 换成 ATR(20),对应的就是 EMA(39)。
2.5 ⭐ MA 和 EMA 真正的分界,是那 13.5%
如果快慢不是它们的区别,那区别是什么?
是切不切断。
SMA(20) 只看最近 20 根,第 21 根之前的价格,权重恒等于 0。EMA 不切断——它的权重一路衰减下去,但永远不到 0。
那"n 根之前"到底还剩多少?算一下:
| span n | 最近 n 根一共占 | n 根之前还剩 |
|---|---|---|
| 20 | 86.5% | 13.5% |
| 60 | 86.5% | 13.5% |
| 250 | 86.5% | 13.5% |
三行一模一样,不是我抄错了。这个数收敛到 ,和 n 无关。
不管你用 EMA(20) 还是 EMA(250),都有大约七分之一的权重,压在"你以为它已经不看了"的那一段上。
这才是两者真正的分界:MA 会忘,EMA 不会。
("指标有记忆"这个说法不是本篇造的,MACD 那篇讲接缝污染时已经讲透了——那里的结论是"换月这件事,在价格上是一天,在 MACD 上是两个月"。本篇只是把这份记忆量化到了一个具体的百分比上。)
三、滞后有多大:这一条不用测
有了平均年龄,一件很多人以为只能靠感觉的事,就变成了一道算术题。
3.1 均线落后价格多远
设想价格在一段趋势里匀速走,每个交易日涨 k。那么均线与价格的稳态距离是:
代进去(取 k = 0.5%/日,一段不算夸张的趋势):
| 均线 | 平均年龄 | 乖离 |
|---|---|---|
| MA(5) | 2.0 | 1.0% |
| MA(20) | 9.5 | 4.8% |
| MA(60) | 29.5 | 14.8% |
| MA(250) | 124.5 | 62.3% |
均线落后价格多远,是你选的参数决定的,不是行情决定的。
同一段行情,你换个周期,乖离就换一个数。所以"乖离率太大了,要回归"这种话,在没有说清楚是哪条均线之前,是没有内容的。
3.2 为什么均线永远只能事后跟随
这一条也是算出来的,不是经验。
均线是过去价格的加权平均,而且权重都是非负的。一组非负权重的加权平均,必然落在这些价格的最大值和最小值之间。
于是:
- 价格没涨过的地方,均线不可能先涨上去
- 价格转向的那一天,均线一定还在往原方向走(因为它还压着一堆旧价格)
- 均线拐头的那一天,价格早就拐完了
均线不是被走出来的,是被算出来的。 它没有"预测"这个功能,它连"同步"都做不到——它的位置在数学上被钉死在过去。
这不是均线的缺点,是它的定义。 一个不落后的均线,等于没有做平均。
3.3 ⭐ MA 拐头,可能跟今天一点关系都没有
这一条是本篇最实用的一个副产品,而且几乎没人讲。
把 MA 今天和昨天的值相减,中间那一大堆全部抵消掉,只剩两个数:
今天的价格,减去 n 天前那一根。
也就是说——
MA 今天是涨是跌,只取决于两件事:今天的价格,和 n 天前那个刚刚被挤出窗口的价格。中间那 n−2 天,一个字都不算数。
于是就有了盘面上那种让人莫名其妙的现象:今天价格几乎没动,MA20 却明显拐头了。不是今天发生了什么,是 20 天前那根大阳线终于滚出了窗口。
EMA 没有这个毛病,因为它不切断:
EMA 拐头,一定是因为今天的价格穿过了昨天的均线值。 它的每一次方向变化都有一个当天的理由。
这才是选 MA 还是 EMA 时该问的问题——不是"哪个更快",是"我能不能接受一根 n 天前的 K 线在今天替我做决定"。
四、参数:5 / 10 / 20 / 60 / 250 是哪来的
这一组数比 MACD 那个 12/26/9 诚实一些——它们确实对得上交易日历:一周 5 天、一个月 20 天、一个季度 60 天、一年约 250 天。不像 12/26/9 那个口诀,得假设一周有六个交易日才凑得齐。
但"对得上日历"不等于"对得上市场"。请注意三件事:
① 它们是日历数,不是市场数。 没有任何一个是从你做的那个品种的行情里算出来的。一个 2024 年上市、日内波动是别人几倍的品种,凭什么用"一个月"这个数?
② 期货的"一天"和日历上的一天不是一回事。 这个市场的一个交易日是从前一天晚上开始的,长假前后还会连着堆好几天的信息进一根 K 线。"20 天 ≈ 一个月"这种直觉,在这里比在股票上更松。
③ 真正该问的问题,第二节已经给了。
调参数不是在调"灵敏度",而是在调平均年龄,也就是在调你愿意落后多少天:
| 你想落后 | 该用的 MA / EMA |
|---|---|
| 约 5 个交易日 | 11 |
| 约 10 个交易日 | 21 |
| 约 20 个交易日 | 41 |
| 约 30 个交易日 | 61 |
(反解 (n−1)/2 即可。MA(n) 和 EMA(n) 这张表通用,因为它们重心相同。)
这么一列,"该用 20 还是 30"就不再是个玄学问题了:你先决定能接受多大的滞后,n 是被算出来的。 反过来在历史图上把 n 拧到金叉刚好都对上,那件事永远做得到,而它什么也证明不了。
五、它能干什么(两个用法,都很克制)
用法一:当趋势过滤器,不当扳机
只在价格位于某条均线上方时考虑多头方向,下方只考虑空头方向。
注意均线在这里的角色——它没给你入场点,它只是把一半的方向划掉了。这和 MACD 那篇讲的过滤器用法是同一个思路,不重复。
但均线这里多一条本篇才能给的:过滤器的周期该选多少,等于问"我希望自己多久换一次立场"。 平均年龄就是那个答案。你希望立场大约一个月才翻一次,就去第四节那张表里查——不是拍脑袋选 20 或 60。
用法二:当"我这笔打算拿多久"的对照
这条更有用,也更少人用。
你的持仓打算拿三五天,却盯着一条平均年龄 29.5 天的 MA60 找信号——它给出信号的时候,你那笔交易早就该结束了。 反过来,你想拿一个季度,却用 MA5 决定进出,那你会被每一次噪音赶下车。
均线的周期和你的持仓周期不匹配,这件事比"用 MA 还是用 EMA"重要一个数量级。 而前者从来没人讨论,后者被讨论了几十年。
这两个用法,没有一个会产生入场点。 如果你的系统里均线是那个扣扳机的东西,那你用错它了。
六、实测:预热期撞上合约寿命
上面全是推导,对所有品种、所有行情都成立。但有一件事推导答不了:这套东西在国内期货上,你实际能不能用。
这一条要数据。
怎么测的
样本整套复用上一次做 MACD 时那批:8 个成交额最靠前的品种(品种池事前定死,不因结论好看而调整)、289 份单一合约、2020 年 1 月起。活跃期的口径是持仓量达到该合约自身峰值 50% 以上的交易日数。
中位数是 37 个交易日。
⚠️ 先说清这不是什么:这里没有回测、没有成本假设。下面的数字不回答"均线赚不赚钱",只回答"这条线你算不算得出来"。
结果:60 以上那一档,基本不存在
均线要预热。MA(n) 在第 n 根之前根本没有值;EMA 更麻烦——它没有"预热完"这个时刻(第 2.5 节说了,它不切断),实践中只能取一个标准,比如"最初那个种子值的影响衰减到 1% 以下",算下来大约是 2.3(n+1) 根。
拿这两个数去撞那 289 份合约:
| 周期 | MA 要几根 | 撑不住 | EMA 要几根 | 撑不住 |
|---|---|---|---|---|
| 20 | 20 | 3.8% | 47 | — |
| 60 | 60 | 75.8% | 139 | 100% |
| 120 | 120 | 99.3% | 277 | 100% |
| 250 | 250 | 100% | 576 | 100% |
"撑不住"的意思不是算不出数,是——等它预热完,这份合约已经没人交易了。
在国内期货的单一合约上,"年线"这个东西不存在。 不是不好用,是压根活不到那一天。
分品种更值得看一眼:
| 品种 | 活跃期中位 | 撑不住 MA60 |
|---|---|---|
| 天然橡胶 | 82 | 0% |
| 焦煤 | 79 | 5.9% |
| 沪金 | 58 | 53.8% |
| 沪铜 | 39 | 100% |
| 原油 | 28 | 100% |
| 锡 | 26 | 100% |
⭐ 这张表里有一件我开跑前没想到的事:撑不住的全是月月都挂合约的品种(铜、原油、锡),而扛得住的全是只有少数几个主力月的品种(橡胶、焦煤、棕榈油)。
"月份齐全"和"每份合约活得久",是两件相反的事。 月份挂得越密,每一份分到的日子越短。这一条和 MACD 那篇发现的两条中毒路径是同一个结构在另一个问题上的投影。
那用主连行不行
不行,而且这一条不用再论证了:
主连不干净,单合约不够长。 在期货上,你没有一条既真实又足够长的价格序列可以拿来算指标——这是 MACD 那篇的结论,对均线只会更严重,因为均线的周期通常比 MACD 那 35 根长得多。
接缝造成的那一跳会被均线记住多久,第 2.5 节那 13.5% 已经给了答案的形状:用 EMA,它永远散不干净;用 MA,它会在 n 根之后突然消失——而"突然消失"本身又是一次假拐头(第 3.3 节)。
这批数据打几折
- 它不回答均线赚不赚钱。 本篇一次回测都没做
- 只有 8 个品种,而且是成交额最靠前的一档。 冷清品种的合约寿命只会更短——这批数是乐观的那一头
- EMA 那个"预热期"是我挑的阈值。 换成宽松阈值重算过一遍:60 以上那一档的结论不变(最宽松的组合下 MA60 仍有六成撑不住),但 20 那一档对阈值很敏感,所以正文只写了 60 以上
- 日线答不了日内。 60 分钟、15 分钟上的均线预热期折成自然日要短得多,这批数据一个字都说不了
七、失效场景(请比第五节读得更用力)
① 双均线金叉:它测的不是方向
快线减慢线,得到的不是"方向",是两个不同重心之间的距离。这个差值本质上是一个被平滑过的斜率估计,而"差值"这一层丢掉了什么,MACD 那篇已经拆过三层,这里只挂链。
要紧的是它的代价:金叉发生的时候,行情已经走了一段了。这个滞后的量级 MACD 那篇标定过——中位晚 5 个交易日、价格已经走了 3.94%,而在期货上这个数还要乘以你的真实杠杆。
均线自己的那份代价还要再加一条:你没法通过换参数躲开它。 第三节那个式子摆在那儿——滞后 = 平均年龄 × 斜率。你把周期调小,滞后确实变小,但被噪音扫的次数同步上升。这不是可以优化掉的东西,是一个只能选、不能赢的取舍。
② 震荡市里,交叉会密集出现
这是老手天天看见的,我不打算用数据去"证明"它。只提醒一句它为什么危险——
不是因为信号多,是因为每一次交叉事后都能讲出一套道理。讲得通,正是这类读法最危险的地方。
③ ⭐ 多头排列:那不是四个证据,是一个证据被画了四遍
"5 日在 10 日上、10 日在 20 日上、20 日在 60 日上,多头排列,很强。"
这句话听起来像是四条独立的证据在互相印证。它不是。
四条均线全部由同一串价格算出来,只是权重形状不同。它们排开,说的只有一件事:过去这几段的斜率都是正的。 同一件事被数了四遍,不会因此变得更可靠。
均线越多,看起来越像一场投票,其实全场只有一个人在说话。
这个坑和组合里那几个"看起来分散"的品种其实只等于一笔半是同一个错误——把高度相关的东西当成互相独立的证据来累加。那一篇给的是判据:别问它们叫什么名字,问它们之间能不能画出一条线。 四条均线之间,那条线画得再清楚不过了。
④ 它不回答"这个价位有没有意义"
"回踩 20 日线不破就进"——这是均线第二常见的用法,也是最没有依据的一个。
MA20 今天这个数,是过去二十根价格的平均。它凭什么在市场上有意义? 没有任何机制让成交发生在一个"由过去二十天算出来的数"上。它在图上是一条线,在盘口上什么都不是。
更要命的是第 3.3 节那条:这个数明天会变,而它变的原因可能只是二十天前那根 K 线滚出了窗口。 你守着一个会自己挪动、且挪动理由和今天无关的价位。
⑤ 信号需要成交才能兑现
均线下穿让你出场,但价格封在跌停板上,你出不去。这一条在涨跌停那篇里讲透了,ATR 那篇从止损角度也说过,只挂链,不重复。
⑥ 它不回答仓位——而这一条能要命
均线就算全对,也只给方向和时机,一个字都没说该开多少手。而在期货上,决定你能不能活下来的是后面那个数。第七节 ① 那个"晚 5 天、3.94%",落在不同仓位上是完全不同的两种后果。
八、代码
老规矩,计算逻辑写成纯函数,不绑定任何数据源。一列按时间升序的收盘价就能跑。
import math
import pandas as pd
def sma(close: pd.Series, n: int) -> pd.Series:
return close.rolling(n).mean()
def ema(close: pd.Series, n: int) -> pd.Series:
"""通行口径:alpha = 2/(n+1),重心与 sma(n) 相同 —— 见第 2.3 节。"""
return close.ewm(span=n, adjust=False).mean()
def wma(close: pd.Series, n: int) -> pd.Series:
w = pd.Series(range(1, n + 1), dtype=float)
return close.rolling(n).apply(lambda x: (x * w).sum() / w.sum(), raw=True)
def wilder(close: pd.Series, n: int) -> pd.Series:
"""alpha = 1/n。重心 n-1,等于 sma(2n-1) —— 见第 2.4 节。"""
return close.ewm(alpha=1 / n, adjust=False).mean()
下面这三个才是本篇最该带走的东西——它们不算均线,它们算"这条均线站在多少天以前":
def age_sma(n: int) -> float:
"""SMA(n) 的平均年龄 = 权重重心。"""
return (n - 1) / 2
def age_ema(alpha: float) -> float:
"""EMA(alpha) 的平均年龄。传 2/(n+1) 进去,结果等于 age_sma(n)。"""
return (1 - alpha) / alpha
def span_for_lag(lag_days: float) -> float:
"""反过来:我愿意落后 lag_days 天,该用几日均线。 —— 第四节那张表"""
return 2 * lag_days + 1
def steady_gap(age: float, daily_pct: float) -> float:
"""匀速趋势下均线与价格的稳态乖离(一阶近似)。 —— 第 3.1 节"""
return age * daily_pct
def ema_warmup(n: int, thresh: float = 0.01) -> int:
"""种子值影响衰减到 thresh 以下需要几根 K 线。约等于 2.3*(n+1)。"""
alpha = 2 / (n + 1)
return math.ceil(math.log(thresh) / math.log(1 - alpha))
⚠️
ema()用的是adjust=False(真正的递推),这才是行情软件的画法。adjust=True是另一套定义,开头几十根差得很明显——和 ATR 那篇说的实现细节是同一回事。
九、三个你该自己跑一遍的实验
实验一:把 MA(20) 和 EMA(20) 画在一起
你会看到:在一段单边行情的中段,两条线几乎重合并且平行——这就是"重心相同"的样子。差别只出现在拐点附近的那几根上。
结论:你为"用 MA 还是 EMA"纠结掉的那些时间,换算成图上的距离,大概只有拐点处那么一点点。
实验二:把 (P_t − P_{t−n})/n 单独画出来
这就是 MA 的日增量(第 3.3 节)。把它和当天的涨跌幅画在一起。
你要看的:有多少次 MA 拐头的那一天,当天价格其实没怎么动。那些拐头是 n 天前那根 K 线造成的。 亲手看一次,你以后再也不会把"均线拐头"当成一个当天发生的事件。
实验三:在单一合约上算 MA60,数一数还剩几天
挑一份你真的交易过的合约,从它挂牌算起,看 MA60 什么时候出第一个值,再看那时候它的持仓量离峰值还有多远。
你要看的:不是数字,是那个顺序——它到底是先热起来,还是先预热完。 第六节那 75.8% 就是这么来的。
十、三句话结论
1. 均线的滞后是算出来的,不是感觉出来的。 平均年龄 = (n−1)/2,MA(20) 站在九天半以前,不是二十天。你调参数调的不是灵敏度,是你愿意落后多少天。
2. MA 和 EMA 的区别不在快慢,在切不切断。 同周期下两者重心完全相同——那本来就是 α = 2/(n+1) 的设计目的。真正的差别是:MA 会忘,EMA 有大约七分之一的权重永远留在过去。
3. 它永远只能事后跟随,而在国内期货上,长周期均线连"事后"都赶不上。 289 份合约里,七成五撑不住 MA60,没有一份撑得住 MA250。选周期之前,先看看你要交易的那份合约能活多久。
下一篇:《手续费、平今仓惩罚、交易所减免那些事》——把一笔交易从下单到平仓,中间被收走的每一道钱掰开算给你看。
⚠️ 风险提示 本文仅为期货知识分享与研究交流,不构成任何投资建议。文中所有指标参数、公式与代码均为原理演示,不构成任何交易参数或交易信号推荐,历史数据与统计结果不代表未来表现。期货交易具有高杠杆特性,可能导致本金全部损失甚至产生穿仓负债。文中涉及的合约规则、涨跌停等信息以各期货交易所官方最新公告为准。请通过正规期货公司开户,理性参与、独立决策、风险自担。


