你以为你在用代码找最优参数,其实你只是在用代码,把过去那段噪声背得更熟。
上一篇我们画出了资金曲线,也算清了一堆绩效指标。
于是你很自然地动了一个念头:
均线参数我随手填的 20,要是改成 18 会不会更好?改成 22 呢?50 呢?
反正有代码了,我把所有可能都跑一遍,挑那条资金曲线最漂亮的不就行了?
这个念头,几乎每个刚学会写回测的人都会冒出来。它听起来无比科学、无比"数据驱动"。
但它,恰恰是这一季里最危险的一步。
这一篇,我们就来做参数优化——然后非常用力地,讲清它脚下那条红线。
先把"参数优化"这个词翻译成人话。
你的策略里,总有几个可以拨动的旋钮:均线的周期、止损的距离、过滤的阈值……每一个旋钮都能拨到不同的值。
所谓优化,就是把这些旋钮的各种组合都试一遍,看哪一组在历史上表现最好。
最朴素的做法叫网格搜索(grid search)——把参数想象成一张网格,每一格是一种组合,你挨个格子去测。
用代码写出来,核心就是一个循环:
results = []for fast in range(5, 30): for slow in range(30, 120): equity = run_backtest(data, fast, slow) # 第⑤篇那个引擎 results.append((fast, slow, sharpe(equity)))
这几行在干嘛?
它把"快线"从 5 试到 30、"慢线"从 30 试到 120,每一种搭配都拿第⑤篇写好的回测引擎跑一遍,把每组的夏普比率(第⑥篇的指标)记下来。
跑完,你手里就有了几千组结果。排个序,取最高的那组——
优化,完成了。
这件事,手工做几乎不可能:几千次回测,谁有耐心一组组改、一组组看?
但 Python 让它快到危险——一杯咖啡的时间,几千组就跑完了。
请记住"危险"这两个字。它不是修辞。
⚠️ 红线在哪:你挑的不是最优,是最贴合噪声的那组
现在来到这一篇的灵魂。
你排序、选出了夏普最高的那组参数。问题是——
在同一段历史上挑出来的"最优",往往只是最贴合这段历史里的噪声的那一组。
这句话值得你停下来读三遍。
市场的历史数据,从来不是干净的规律,而是规律 + 一大堆随机噪声混在一起。
当你拿几千组参数去同一段数据上比拼,总有一组会"恰好"踩中那些随机的涨跌——它在这段历史上闪闪发光,不是因为它抓住了规律,而是因为它背熟了这段考卷的答案。
这就是第四季④讲过的过拟合:模型不是在学规律,而是在背噪声。
换一段没见过的数据,这组"最优"参数立刻原形毕露。
这正是"回测赚翻、实盘亏穿"最常见的来源之一。
而且参数越多、网格越密,这个陷阱越深——旋钮越多,"恰好踩中噪声"的自由度就越大。
所以这里有一条要刻进肌肉的认知:
在历史上挑出"最好看"的那组,和挑出"最能用"的那组,是两件完全不同的事。
回想第⑥篇我们用夏普给曲线排序——那把尺子本身没错,错的是你拿它在同一段数据里既当裁判、又当选拔标准。用同一段数据选参数,再用同一段数据夸它好,这是在自己骗自己。
🛡️ 怎么守住:从"挑最好看"到"挑最稳健"
知道了红线,问题就变成:优化不是不能做,而是怎么做才不至于骗自己?
给你三条能落地的防线。
1️⃣ 看参数曲面,是高原还是尖峰。
别只盯着那个最高分。把所有参数组合的得分画成一张"地形图"——横竖是两个参数,高低是绩效。
然后看那个最高点长什么样:
- • 如果它是一根孤立的尖峰,旁边一格就是悬崖——参数稍微动一点,绩效就崩。这种"最优"碰都别碰,它几乎注定是过拟合。
- • 如果它落在一片宽阔平缓的高原上——周围一圈参数表现都不错,差不多稳定——这才是可以信的。
这正是第四季⑨《参数高原》的核心:
你要选的是一片高原,不是一根尖峰。
宁可要一组得分没那么炸、但周围都很稳的参数,也别要那根孤零零、一碰就倒的尖刺。因为实盘里,市场不会照着你那根尖峰的脚本走。
2️⃣ 留出样本外数据,别让它参与优化。
把历史切成两段。前一段用来跑网格、挑参数(样本内);后一段藏起来,优化时碰都不碰(样本外)。
参数定下来之后,再拿这段没见过的数据验一次。
代码上不过是一行切片:
in_sample = data[:'2022'] # 用来挑参数out_sample = data['2023':] # 藏起来,最后才验
逻辑很简单:真规律在新数据上也该管用;只会背噪声的参数,一到样本外就现形。
这是个朴素却极有效的诚实机制——它逼着你的策略去面对一段"没复习过"的考卷。
3️⃣ 对参数做敏感度检验。
选定一组参数后,故意把每个旋钮往两边各拨一点,再各跑一次。
如果轻轻一拨,绩效就天翻地覆,说明你站在悬崖边——这组参数对噪声太敏感,不稳。
如果拨来拨去结果都差不多,恭喜,你大概率站在高原上。
把这三条合起来,你做的事就从"在历史里挑最好看的",变成了"挑一组换个环境也不容易翻车的"。
这件事的内核,其实还是 0.01手 那句老话:先求活下来,再求赚得多。
一根过拟合的尖峰,回测里能给你画出梦幻曲线;可它在实盘第一波没见过的行情里,就会把你掀翻。
而一片稳健的高原,回测成绩也许平平无奇,却更可能陪你走得久。
参数优化最该优化的,从来不是那个最高分,而是你对"漂亮回测"的免疫力。
📌 小结
- • 参数优化 = 用循环遍历所有参数组合,逐组跑回测、按指标排序选最优;Python 让这件事快到危险。
- • 红线:同一段历史上挑出的"最优",常常只是最贴合这段噪声的那组——换段数据就失灵,这就是过拟合。
- • 三条防线:看参数曲面(选高原不选尖峰)、留出样本外数据别参与优化、做参数敏感度检验。
- • 目标从"挑最好看"换成"挑最稳健"——回测好看不算赢,换个环境不翻车才算。
【下一篇预告】我们留了"样本外"这一手,但只切一刀、藏一段,真的够诚实吗?下一篇讲 walk-forward:让窗口一段段往前滚,每次只用过去的数据挑参数、只在紧接着的未来验证——把"诚实"做成一套可重复的流程。
如果这篇帮你看清了"漂亮回测"背后的陷阱,欢迎点赞、关注,把它转给那个正准备"把所有参数都跑一遍"的朋友。你在优化参数时踩过哪些坑?评论区聊聊。
本文仅为个人学习记录与编程笔记,所涉代码与方法均为技术科普,非交易建议,不构成任何操作建议。市场有风险,据此操作风险自负。