参数优化与参数平原:找平原,不找尖峰
样本内最优参数年化 8.61%,样本外 -2.12%——衰减 10.73 个百分点;而它在样本内参数网格上本就是一根孤针,不是一片高地
双均线 (fast, slow) 拉一张 15×15 的网格,218 组有效参数,全跑一遍。
全样本最优点:fast=2, slow=50,年化 4.21%。而全网格中位数只有 1.33%,买入持有 1.66%。
看起来找到宝了。但把样本切成前后两半再来一次:
样本内(2010-01 ~ 2018-04)最优 fast=6, slow=30 年化 8.61%
它在样本外 年化 -2.12%
衰减 -10.73 个百分点
而这件事本来在样本内就有迹象:把那个点放回参数网格上看,它四周并没有连成一片高地——
它不是一片高地,它是一根针。
这一节讲怎么在选参的当下就把针和高地区分开。
你要在一片山区盖房子。
有两块地:一块是孤峰顶,海拔最高;一块是高原,海拔略低但四周都一样高。
测量总有误差。如果你的海拔仪偏差 50 米,孤峰顶那块地可能根本不存在——而高原上偏 50 米,你还在高原上。
参数不是"选一个点",是"选一片区域"。
一、参数曲面:读法不是"哪里最红"
全样本年化(行=fast,列=slow,单位 %,· 表示 fast ≥ slow 无效):
20 30 40 50 60 70 80 90 100 110 120
2 0.87 1.50 2.80 4.21 2.47 2.70 2.91 2.27 1.39 2.49 2.64
4 -0.51 1.40 2.27 3.44 2.21 2.38 3.19 2.16 2.14 2.22 2.59
6 -0.51 3.24 3.01 2.42 3.76 1.35 2.87 0.81 1.84 2.06 1.33
8 -0.20 1.51 1.25 2.34 1.92 0.78 1.11 0.85 1.74 2.12 0.83
10 0.28 1.80 3.02 1.47 1.45 1.07 0.96 1.03 1.20 1.35 0.90
...
20 · 0.66 0.86 -0.67 -0.48 -0.37 0.85 2.09 1.81 2.41 1.30
这张表的正确读法不是"哪一格最红",是"红色成不成片"。
二、尖峰与平原的定量判据
定义平原分:
平原分 = 含自身的 3×3 邻域均值 − 邻域标准差
一个孤立尖峰的邻域均值低、标准差大,会被这个分数双重惩罚。
实测对比(全样本):
| 参数 | 该点年化 | 邻域均值(5 个,不含自身) | 邻域标准差 | 点比邻域高 | |
|---|---|---|---|---|---|
| 单点最优 | fast=2, slow=50 | 4.21% | 2.64% | 0.50 pp | +1.58 pp |
| 平原最优 | fast=2, slow=70 | 2.70% | 2.63% | 0.41 pp | +0.07 pp |
单点最优比邻居高 1.58 个百分点,平原最优只高 0.07 个百分点。
前者的意思是:只要参数选偏一格,你就掉下去 1.58 个百分点。而现实里你一定会选偏——因为选参用的是历史,兑现用的是未来。
报告"最优参数"= 报告 218 次比较的最大值。
这张网格跑了 218 组有效参数,你挑出年化最高的那一组来报告。
这就是 p3.4 的多重检验,和 p5.1 那 16 种读法是同一件事——只不过这次的比较次数从 16 变成了 218。
比较次数越多,"最大值"里噪声的占比越高。所以:
网格越密,单点最优越不可信。 加密网格不会让你找到更真的信号,只会让你找到更极端的噪声。
三、样本外检验:衰减 10.73 个百分点
把 4023 个交易日切成前后各半:
| 样本内 2010-01 ~ 2018-04 | 样本外 2018-04 ~ 2026-07 | |
|---|---|---|
| 单点最优 fast=6, slow=30 | 8.61% | -2.12% |
| 平原最优 fast=6, slow=50 | 4.26% | 0.36% |
| 全网格中位数 | — | -0.03% |
| 买入持有 | — | 2.39% |
三件事同时成立,缺一不可地读:
- 单点最优衰减 -10.73 个百分点——样本内 8.61%,样本外 -2.12%
- 平原最优在样本外更好(0.36% vs -2.12%,高 2.48 pp),平原这个启发式是有效的
- 但两者都跑输买入持有(2.39%)
所以"找平原不找尖峰"的正确表述是:它让你少输,不保证你能赢。
一个能少亏 2.48 个百分点的方法值得用;但如果因此以为"用了平原法就能跑赢",那是把风险控制误当成了收益来源。
还有一个数,比上面三条都更说明问题
样本外表现最好的参数是 fast=2, slow=50(样本外 4.47%)。而它在样本内只排第 25 名(218 组里)。
样本内排第 1 的 6/30,样本外是 -2.12%;样本外排第 1 的 2/50,样本内只排第 25。
两张排行榜几乎没有关系。
三张曲面图:形状比数值更早暴露问题
code/outputs/surface.png 把三张曲面并排画出来:
| 面板 | 看什么 |
|---|---|
| ① 样本内年化 | 像雪花点——高值零散分布,没有成片区域 |
| ② 平原分(样本内) | 噪声被邻域平滑掉,浮出两条连续的绿色带 |
| ③ 样本外年化 | 同样是雪花点,而且高值区和 ① 不重叠 |
面板 ① 和 ③ 放在一起看,就是本节全部结论的图形版:在噪声主导的曲面上,"最高点在哪"这个问题本身没有稳定答案。
🔧 动手做:尖峰点和平原点,谁扛得住样本外?(6 分钟)
跑 python param_plateau.py,看【三】样本外检验。样本内它给你两个"好"参数:尖峰 6/30 和平原 6/50。
你会看到(实测):样本内尖峰 6/30 年化 8.61%、样本外 -2.12%(崩了,衰减 10.73pp);平原 6/50 样本内 4.26%、样本外 0.36%(活着)。
想明白:样本内更高的那个点(8.61% vs 4.26%),样本外反而崩得更惨。网格给你的"最优点",大概率是噪声的最大值——判据不是"这个点多高",是"它周围也高吗"。找平原,别追尖峰。
四、网格结果有多脆:随机搜索三次
同样的搜索预算(每次随机抽 30 组参数,取其中最好的):
第 1 次随机 30 组:最好 fast=2, slow=60,年化 2.47%
第 2 次随机 30 组:最好 fast=4, slow=80,年化 3.19%
第 3 次随机 30 组:最好 fast=6, slow=30,年化 3.24%
同一份数据、同样的预算,三次选出的参数完全不同。
这说明这张曲面上"最优点"的位置,由噪声决定的成分很大。
顺带回答一个常见问题:"用贝叶斯优化会不会更好?"
贝叶斯优化解决的是"用更少的次数找到最高点"。而本节的问题是最高点本身不可信——搜索效率提高,只会让你更快地找到一根更尖的针。优化算法不解决过拟合。
五、选参的实操顺序
| 步骤 | 做什么 | 为什么 |
|---|---|---|
| 1 | 先定网格范围并写进规格书 | 事后扩网格 = 增加比较次数(p5.1/p3.4) |
| 2 | 跑全网格,先看曲面形状 | 成片的高地 vs 孤立的针 |
| 3 | 用平原分排序,不用单点年化排序 | 邻域惩罚孤峰 |
| 4 | 报告时同时给出网格中位数与比较次数 | 让读者能自己打折 |
| 5 | 参数定下后冻结,拿去做滚动前推(p5.5) | 一次样本外检验不够 |
📌 免责:本课为技术教学,标的为沪深300 指数,所有回测为历史模拟,参数网格为演示口径,不构成投资建议。
三件事:
- 参数曲面的读法不是"哪里最红",是"红色成不成片"。平原分 = 含自身 3×3 邻域均值 − 邻域标准差;实测单点最优比邻域高 +1.58 pp(尖峰),平原最优只高 +0.07 pp(高地)
- 样本内最优点样本外衰减 -10.73 个百分点(8.61% → -2.12%);平原点样本外 0.36%,比尖峰高 2.48 pp——平原启发式有效,但两者都跑输买入持有 2.39%。它让你少输,不保证你能赢
- 报告最优参数 = 报告 218 次比较的最大值(p3.4)。网格越密,单点最优越不可信;优化算法不解决过拟合——贝叶斯优化只会让你更快找到一根更尖的针
实操顺序:先定网格并写进规格书 → 看曲面形状 → 用平原分排序 → 报告时给出网格中位数与比较次数 → 参数冻结后交给滚动前推。
下一节把"一次样本外检验"升级成流水线:训练 3 年 → 选参 → 冻结 → 测试 1 年 → 前移,共 12 折。结果会很不好看:每年重新优化参数,还不如一开始定死 5/20 不动。
🔎 来源与核验· 5 条,点开核对
