⚠️ 免责声明:本章仅为教育与研究方法展示,不构成任何投资建议。 所有回测结果来自历史数据,不代表未来表现。投资有风险,决策需独立判断。
第三课:均值-标准差策略——离正常有多远¶
本章代码:
code/lesson3_mean_std.py运行方式:python lesson3_mean_std.py
3.0 策略概述¶
这是什么策略¶
PE 分位数(第二课)问的是"排第几"。均值-标准差问的是"偏多远"。
举个例子。一个班的考试成绩,你的分数是 85 分。分位数告诉你"你排在班级前 30%"。标准差告诉你"你比班级平均分高 1.5 个标准差"。两个答案都有用,但含义不同——分位数只看排名,标准差看偏离幅度。
在投资中:PE 分位数说"当前 PE 排在历史的 80% 分位"。均值-标准差说"当前 PE 比历史均值高 2 个标准差"。
它回答什么问题¶
| 问题 | 白话 |
|---|---|
| PE 偏离它的正常范围多远? | 用标准差衡量偏离幅度 |
| 什么叫"极端"? | 超过 ±2 个标准差 = 统计学上的极端 |
| 为什么分位数还不够? | 分位数在趋势性市场中会失效——标准差捕捉偏离幅度 |
核心算法¶
每周末做一次判断:
1. 取最近 5 周的 PE 均值(平滑)
2. 计算历史 PE 的滚动均值 avg 和标准差 std
3. 创建 5 个区间:
当前 PE <= avg - 2*std → 满仓(极度低估)
avg - 2*std < PE <= avg - 1.5*std → 加仓(低估)
avg - 1.5*std < PE < avg + 1.5*std → 不动(正常)
avg + 1.5*std <= PE < avg + 2*std → 减仓(高估)
当前 PE >= avg + 2*std → 空仓(极度高估)
参数 m=2.0、n=1.5 来自原始 notebook,但在不同指数上需要重新调整。
死穴¶
这个策略假设 PE 围绕一个固定的均值波动。 如果 PE 长期单边上涨(像深证红利 2008—2017:PE 从 9 到 42),滚动均值永远追不上当前 PE,策略永远不触发——变成"永远空仓,吃利息"。
3.1 核心代码¶
# 参数
m = 2.0 # 上轨:avg + 2*std = 极度高估
n = 1.0 # 下轨:avg - 1*std = 低估(从 1.5 调下来后效果更好)
position = [0] # 初始空仓
for i in range(WARMUP, n_weeks):
current_pe = pe_data[i-5:i].mean() # 5 周平滑
# 关键:均值 and 标准差只用 PAST 数据(没有未来信息泄露)
avg = pe_data[0:(i-1)].mean() # 到今天为止的历史均值
std = pe_data[0:(i-1)].std() # 到今天为止的历史标准差
if current_pe <= avg - m*std:
position.append(1) # 比均值低 2 个标准差 → 极度低估 → 满仓
elif current_pe <= avg - n*std:
if position[-1] >= 0.5: position.append(1)
else: position.append(0.5) # 低估 → 建仓
elif current_pe < avg + n*std:
position.append(position[-1]) # 正常 → 不动
elif current_pe < avg + m*std:
if position[-1] == 1: position.append(0.5)
else: position.append(position[-1]) # 高估 → 减仓
else:
position.append(0) # 极度高估 → 空仓
和 PE 分位数的关键区别¶
| PE 分位数(第二课) | 均值-标准差(本课) | |
|---|---|---|
| 问什么 | 排第几 | 偏多远 |
| 阈值来源 | 排序(20%/30%/60%/80%) | 统计量(均值 ±n*σ) |
| 优势 | 不假设正态分布 | 对"极端"有明确定义 |
| 死穴 | 趋势市场中分位数无意义 | PE 不均值回归时永远空仓 |
| 深证红利 | +44.5%(旧数据) | 任何参数都失效 |
3.2 参数实验:从失效到有效¶
原始 notebook 用 m=2.0, n=1.5。在深证红利上完全失效——298 周中 0 周满仓、0 周半仓、298 周空仓。策略变成了银行存款。
我们换了四个指数来试四组参数:
| m, n | CSI300 年化 | 说明 |
|---|---|---|
| 2.5, 1.5 | 3.6% | 区间太宽 → 永远不触发 → 等于存银行 |
| 2.0, 1.5 | 3.6% | 同上 |
| 2.0, 1.0 | 11.5% | 最佳——比买入持有(7.7%)高 49% |
| 1.5, 1.0 | 10.3% | 也不错 |
| 1.0, 0.5 | 7.9% | 区间太窄 → 频繁交易 → 交易成本吃掉收益 |
教训:参数不是复制过来的。 m=2.0, n=1.5 是原始 notebook 在深证价值(399348.SZ)上调出来的。换个指数就要重新调。这就是为什么第二章开始说——"回测好看不等于策略有效"。
图 3-1:沪深300 PE 与滚动均值(新数据 2005-2026)。 PE 长期在均值带内波动时,均值-标准差策略才有意义;趋势性上涨/下跌时它永远不触发。

3.3 为什么深证红利上完全失效¶
深证红利的 PE 从 2008 年的 9 涨到 2017 年的 42。它从来没有均值回归——它一直在涨。
想象一个人在长身体:12 岁 150cm,18 岁 180cm。你用"历史平均身高"(165cm)来判断他"是不是太高了"——你会永远觉得他"高于平均",永远建议他"少吃饭"。但他只是正常成长。
深证红利的 PE 就是这个人。它的"正常 PE"不是一个数字,是一条向上的曲线。
3.4 分位数 vs 标准差——终极对比¶
| 场景 | 用分位数 | 用标准差 |
|---|---|---|
| PE 在稳定区间震荡(如 15-25) | ✅ | ✅ |
| PE 长期单边上涨 | ✅ 仍有效 | ❌ 永远空仓 |
| PE 有极端值(暴涨暴跌) | ✅ 只看排名 | ❌ 极端值撑大标准差 |
| PE 近似正态分布 | ✅ | ✅ |
均值-标准差只在 PE 真正围绕一个稳定均值波动时才有效。 在 A 股,这样的指数极少。这就是为什么这个策略在 11 课里出场最晚——不是因为它厉害,是因为它的适用条件最苛刻。
3.5 这一课教了你什么¶
- 均值-标准差问的不是"排第几",是"偏多远"。
- 参数 m 和 n 是指数特定的——m=2.0, n=1.0 在 CSI300 上有效,在深证红利上完全无用。
- 失效的根本原因:策略假设 PE 均值回归。深证红利的 PE 从不均值回归——它在 10 年里涨了 4 倍。
- 一个残酷的事实:A 股市场上,满足"均值回归"条件的指数极少。 这个策略的适用面比 PE 分位数窄得多。
- 你学会了第二个防止被骗的工具:当别人说"这个策略有效"时,问他"在哪个指数上?用什么参数?数据到哪一年?"
3.6 课堂问答¶
问:你在书中说深证红利的 PE 一直在涨,像一个人在长身体。那是不是意味着 PE 策略永远失效了?
不是永远。是\"在那个时间段失效了\"。2008—2017 年深证红利 PE 单边上涨——PE 分位数策略失效,因为\"排第几\"失去了意义。但如果某一天深证红利 PE 开始在一个区间内震荡(比如 15—25 之间反复),PE 分位数策略会重新有效。策略的有效性不是永恒属性——是特定市场条件下的属性。
问:你一直在说\"参数不能复制\"。那怎么找到正确的参数?
滚动窗口测试。用 2005—2010 的数据调参数 → 在 2011—2013 上验证 → 用 2005—2013 重新调 → 在 2014—2017 上验证。让参数选择和收益验证完全分离。如果某组参数在所有滚动窗口上都稳定——这才是真正有效的参数。m=2.0, n=1.0 在 CSI300 上就是我这样找到的。
动手练习(第 3 课)¶
- 入门:扩大参数扫描。把 m, n 的范围扩大到 (3.0, 0.5) 和 (0.5, 0.3), 补全第 3.2 节的表格。你会看到参数"最优区"有多窄。
- 进阶:半程验证(walk-forward 雏形)。用 2008-2012 的数据找最优参数, 然后在 2013-2017 上验证——"最优参数"在验证期还灵吗? 如果失效,恭喜你,你刚刚亲眼看到了过拟合。
- 挑战:迁移到采购决策。把你行业的原材料价格序列,套用"偏离均值 N 个标准差 就是采购信号"的逻辑:过去 10 年,这个信号每次都对吗?错了几次?
下节预告: 前两课都用的是历史数据——\"过去发生了什么\"。第四课换一个角度:\"未来可能发生什么\"——100,000 种可能的未来,蒙特卡洛模拟。