2422 字
12 分钟
《量化交易入门》第 4 章:第一个策略——均线交叉为什么有效又失效

《量化交易入门》第 4 章:第一个策略——均线交叉为什么有效又失效#

第 1 章我们写过 10 行的均线判断,第 3 章备齐了 Python 弹药。现在正式开工:这一章你会得到人生中第一个完整的交易策略——均线交叉。规则简单到一句话能说完,但真正值钱的是后半部分:它为什么有时候特别灵、有时候又把你反复按在地上摩擦。

4.1 均线:把锯齿磨成方向#

打开任何一张 K 线图,最扎眼的特征是什么?乱。 今天涨 2%,明天跌 1.5%,后天又涨回去,单日价格上蹿下跳,像锯齿一样。肉眼盯着这个看,很容易把一次普通抖动当成天大的机会。

均线(Moving Average,简称 MA)就是来治这个病的:把最近 N 天的收盘价求个平均,得到一个平滑过的数字。

  • 5 日均线(MA5)= 最近 5 天收盘价的平均
  • 20 日均线(MA20)= 最近 20 天收盘价的平均

单日暴涨暴跌,在 20 日均线里只占二十分之一的权重,所以均线比价格平滑得多。它回答的不是”今天多少钱”,而是”最近这段时间,大家的平均成本大概在什么位置”。短期均线代表近期参与者的成本,长期均线代表更久一批人的成本,两群人的成本一对比,强弱就出来了。

4.2 金叉买,死叉卖:规则就一句话#

均线交叉策略的全部规则,写在下面这张表里:

信号形态动作
金叉短期均线从下方上穿长期均线买入
死叉短期均线从上方下穿长期均线卖出
其他时间两条线各走各的不动

逻辑很顺:短期均线在长期均线下方,说明近期价格比”老成本”低,是弱势;当短期均线上穿长期均线,意味着新来的钱愿意出比平均成本更高的价格,趋势可能由弱转强,这就是金叉。反过来就是死叉。

注意一个关键细节:判断”交叉”不能只看今天谁在上谁在下,而要对比昨天和今天的相对位置——昨天短线还在长线下面,今天翻上来了,才算交叉。否则在上涨途中的每一天你都会误以为发了买入信号。

4.3 完整代码:在 30 天数据里抓金叉#

下面这段代码在 30 个交易日的收盘价上运行 MA5 和 MA20,自动找出交叉点。为了让两条线都有足够数据,我们从第 20 天开始观察。

# 某股票 30 个交易日收盘价(先跌后涨,模拟数据)
closes = [
12.0, 11.9, 11.8, 11.7, 11.6, 11.4, 11.2, 11.0, 10.8, 10.6,
10.4, 10.2, 10.0, 9.8, 9.7, 9.6, 9.5, 9.4, 9.5, 9.6,
9.8, 10.1, 10.5, 10.9, 11.3, 11.7, 12.0, 12.3, 12.6, 12.9,
]
def moving_average(data, i, window):
"""第 i 天(下标)为止、含当天在内,最近 window 天的均价"""
segment = data[i - window + 1: i + 1]
return sum(segment) / len(segment)
# 从第 20 天起,MA5 与 MA20 才算齐,开始判断交叉
prev_diff = None
for i in range(19, len(closes)):
ma5 = moving_average(closes, i, 5)
ma20 = moving_average(closes, i, 20)
diff = ma5 - ma20
day = i + 1
if prev_diff is not None:
if prev_diff <= 0 and diff > 0:
print(f"第 {day} 天 金叉!收盘 {closes[i]},MA5={ma5:.2f},MA20={ma20:.2f} → 买入")
elif prev_diff >= 0 and diff < 0:
print(f"第 {day} 天 死叉!收盘 {closes[i]},MA5={ma5:.2f},MA20={ma20:.2f} → 卖出")
else:
print(f"第 {day} 天 持有/观望(MA5={ma5:.2f}, MA20={ma20:.2f})")
else:
print(f"第 {day} 天 开始观察(MA5={ma5:.2f}, MA20={ma20:.2f})")
prev_diff = diff

运行结果(可以复制到本地亲自验证):

第 20 天 开始观察(MA5=9.52, MA20=10.58)
第 21 天 持有/观望(MA5=9.56, MA20=10.48)
第 22 天 持有/观望(MA5=9.68, MA20=10.38)
第 23 天 持有/观望(MA5=9.90, MA20=10.32)
第 24 天 持有/观望(MA5=10.18, MA20=10.28)
第 25 天 金叉!收盘 11.3,MA5=10.52,MA20=10.27 → 买入
第 26 天 持有/观望(MA5=10.90, MA20=10.28)
……(之后 MA5 一直在 MA20 上方,持有不动)
第 30 天 持有/观望(MA5=12.30, MA20=10.59)

看 prev_diff 这个变量:它存着”昨天两条线的差距”,正是它让我们能区分”刚刚交叉”和”早就站在上面”。这个”对比今昔”的写法,是写信号代码的通用套路,后面因子章节还会反复见到。

4.4 它为什么有效:趋势 + 自我实现#

均线交叉不是玄学,它能在几十年里被无数人使用,背后有两个实打实的原因。

第一,价格真的有”趋势”这回事。 市场信息不是一瞬间消化完的:一个利好从少数先知先觉的人,扩散到机构,再上新闻被散户看到,可能持续几周。价格因此呈现”涨了还会再涨一阵”的惯性,学术上叫动量效应。均线交叉本质上就是一个趋势跟踪器——它不预测顶和底,只在趋势已经走出来之后上车,吃中间最肥的那段。

第二,用的人多了,信号会自我实现。 金叉是几乎所有交易软件默认标注的形态,无数人和程序盯着同样的两条线。金叉一出,买盘真的涌进来,价格被推高,形态就更像要涨。你赚的钱里,有一部分来自”大家都信这件事”本身。

4.5 它为什么失效:三记耳光#

但是——重点来了——把均线交叉用在所有行情里,会被抽得很惨。它有三个天生的毛病。

第一记:滞后。 均线是过去价格的平均,天生慢半拍。等 30 天数据里第 25 天金叉出现时,价格从最低 9.4 已经涨到 11.3,反弹走了 20% 你才上车;等死叉确认时,利润可能也已经还回去一截。均线策略的座右铭是”吃鱼身,不吃鱼头鱼尾”,接受不了这个延迟,就拿不住这个策略。

第二记,也是最疼的一记:震荡市连环打脸。 趋势策略只在有趋势的行情里有效,而市场有大量时间在横盘震荡——价格在一个箱子里来回拉锯,均线就会反复金叉、死叉。每次交叉都是一次假信号:金叉买在小高点,死叉卖在小低点,左右挨耳光。我们用一段在 10 元附近拉锯的数据感受一下,这次把窗口调短成 MA5 和 MA10:

# 震荡市中的均线交叉(模拟 20 天数据)
choppy = [
10.0, 10.3, 10.6, 10.4, 10.1,
9.8, 9.6, 9.9, 10.2, 10.5,
10.3, 10.0, 9.7, 9.5, 9.8,
10.1, 10.4, 10.2, 9.9, 9.7,
]
def ma(data, i, w):
return sum(data[i - w + 1: i + 1]) / w
prev = None
trades = []
for i in range(9, len(choppy)):
diff = ma(choppy, i, 5) - ma(choppy, i, 10)
if prev is not None:
if prev <= 0 < diff:
print(f"第 {i+1} 天 金叉,买入价 {choppy[i]}")
trades.append(("买", choppy[i]))
elif prev >= 0 > diff:
print(f"第 {i+1} 天 死叉,卖出价 {choppy[i]}")
trades.append(("卖", choppy[i]))
prev = diff
for k in range(0, len(trades) - 1, 2):
buy, sell = trades[k][1], trades[k + 1][1]
print(f"一进一出:{buy} → {sell},盈亏 {((sell/buy)-1)*100:+.2f}%")

输出:

第 12 天 金叉,买入价 10.0
第 15 天 死叉,卖出价 9.8
第 19 天 金叉,买入价 9.9
一进一出:10.0 → 9.8,盈亏 -2.00%

价格从 10 块出发、最后还是 9.7 左右,几乎没动,但严格按信号做,先亏 2%,紧接着又收到一个买入信号——下次会不会还是耳光,你心里完全没底。横盘时间越长,这种小额失血次数越多。

第三记:参数没有标准答案。 MA5/MA20 灵,还是 MA10/MA30 灵?换个参数,历史成绩天差地别。更要命的是,在这只股票上最灵的参数,换到下一只就平庸。这背后藏着一个量化里最危险的词——过拟合,第 11 章会专门拆它。现在先记住:不存在”圣杯参数”。

4.6 知道了毛病,然后呢#

实战中常见的补救思路有三类,你可以先有个印象:

  1. 加过滤器:只在长期均线向上时才接受金叉,或者要求金叉时成交量放大,过滤掉横盘里的假动作。
  2. 多周期配合:大周期(比如周线)判断趋势方向,小周期(日线)找入场点,顺大逆小。
  3. 分散和止损兜底:承认假信号必然存在,用仓位控制和止损让每次打脸的代价变小,而不是幻想消灭它。

但所有这些”改良”到底有没有用,拍脑袋说了不算,得让历史数据裁判——这正好引向下一章的主题:回测。

4.7 这一章你该记住的#

  1. 均线把单日的锯齿磨平,反映一段时间内的平均成本
  2. 均线交叉:金叉(短线上穿长线)买入,死叉卖出;判断交叉必须对比昨天和今天
  3. 它有效是因为趋势会延续、且信号会自我实现;它失效是因为滞后、震荡市假信号、参数敏感
  4. 没有圣杯参数,改良策略要靠回测检验,而不是感觉

下一章,我们就给均线交叉策略装上”时光机”:回测——让历史告诉你答案。怎么把信号放到过去几年的数据上跑、怎么算收益、怎么判断一个策略是真有用还是运气好。


📚 《量化交易入门》系列:零基础小白向量化交易,每章一个主题 + 可运行 Python 示例。第 4 章已读,下一章《回测:让历史告诉你答案》明天见。

《量化交易入门》第 4 章:第一个策略——均线交叉为什么有效又失效
https://021028.xyz/posts/default/134/
作者
021028
发布于
2026-10-08
许可协议
CC BY-NC-SA 4.0