量化入门

回测过拟合怎么看出来?参数最优化之后该做的三件事

2026-10-06·7 分钟阅读

你把参数扫了一轮,回测曲线漂亮到让你想直接按 live trading——年化 120%、最大回撤 8%、胜率 62%。 接下来大概率会发生的事:实盘第一个月就吃掉回测三年净利的一半。这不是坏运气,是「过拟合」 (overfitting)留下的收据。

这篇不评论你用哪个策略逻辑——逻辑本身可能没问题,问题往往出在参数怎么挑的、用哪段数据挑的。 给你三件事,都是最优化按下去之后、把策略搬上实盘之前该做的验证,一件都不能省。

先讲结论
先讲结论:参数最优化跑完不是终点,是起点。挑到「最佳」那一组之后, 至少要做三件事——样本外重跑(walk-forward)、参数敏感度扫描、以及用 1/3 仓位的小规模实盘—— 三关通过才有资格上正常仓。回测数字看得再漂亮,这三关没过就是还没验过。

先讲清楚:过拟合到底把「什么」配给「什么」

过拟合的机制很直接:你在同一段历史数据上,同时做「选策略」与「调参数」两件事, 最后挑到的那一组,本质上是对这段历史的噪音拿到满分——不是对市场的 结构性行为拿到满分。

把数据想成一张考卷。你先看完考卷再回头挑答题方法,考出来当然全对——但那不能推论你 下一张考卷也会这样。过拟合的核心就是这个:你用未来看过的数据回头挑参数,然后用同一份 数据验证挑得对不对,整个流程里没有任何信息在告诉你这组参数对「没见过的数据」有没有效。

数学特征:in-sample 误差很低,out-of-sample 误差爆炸
这是识别过拟合最直接的信号。你在最优化那段数据(in-sample)看到胜率 62%、 Sharpe 2.1;换到没碰过的那段(out-of-sample),胜率掉到 48%、Sharpe 0.4—— 这种落差不是「运气不好」,是曲线硬拉出来配这段历史的直接证据。

第一关:把数据切开,最优化只能碰 in-sample

最基本、也最常被跳过的动作:数据一开始就切两块。一块给你随便玩—— 参数怎么调、指标怎么加、规则怎么改都可以;另一块锁起来,最优化跑完那一刻才第一次 拿出来看。这块不能参与任何选择,一旦拿出来看过就报废,不能再用。

70 / 30
常见比例,前 70% 给最优化
80 / 20
数据短的话会这样切
1 次
OOS 数据只能看 1 次,看过就报废
6~12 个月
OOS 至少要涵盖一个像样的市场周期

切法没有唯一正解,看你手上有多少年数据。(本文写作时整理的常见基准)

这里有个很容易骗自己的做法:你把 out-of-sample 拿出来看,发现不理想,回头改参数, 再看一次。这个当下 OOS 就报废了——它已经被最优化流程间接碰过, 跟本来的 in-sample 没有本质差别。看第二次的 OOS 不叫 out-of-sample,叫另一段 in-sample。

想避开这个陷阱,可以再切第三块叫 hold-out:整个开发过程完全不碰, 策略要交付给实盘那天才第一次看。这块小一点没关系(15% 到 20%),它的作用是给你 「这组参数在真的没见过的数据上长什么样」一个诚实的参考。

第二关:walk-forward — 让「最优化」变成一直发生的事

切一次 in-sample/out-of-sample 有个弱点:你只验证了「用前 70% 挑的参数, 在后 30% 上还有效」这一个切点。市场如果换了个模式,你这组挑三年前数据调出来的 参数,可能三年来都在慢慢失效,你只是还没发现。

walk-forward 的想法很单纯:把数据切成很多小段,每段都跑一次「用前面 N 个月调参数、 用接下来 M 个月验证」,然后把「验证段」全部拼起来当成一条连续的样本外曲线。 这条曲线比较接近「真的照这个流程做的话,这几年会拿到什么」。

单次切样本外walk-forward
验证了几个时间点?1 个切点很多个滚动窗口
对「市场换模式」的抵抗力低(用一段旧数据挑)高(每个窗口都重新挑)
设定复杂度简单要决定窗口长度与滚动步长
运算成本跑 1 次最优化跑 N 次最优化
最像实盘的行为不太像接近你会怎么定期重调

两种验证方式的取舍。walk-forward 较贵,但更接近「策略要定期重调」的现实。

walk-forward 有个副产品同样重要:每个窗口挑到的「最佳参数」是什么?如果十个窗口挑到十组差很多的值,那不是这个策略敏感——是这个策略没有真的规律, 只是每次都在配当下那段噪音。反过来,十个窗口挑到差不多的参数,那才是真的抓到什么。

这里的取舍要自己拍板
窗口要切多长?滚动步长要多大?官方没有标准答案,选择会影响结果。一个常见的起点是 「训练窗 = 6 个月、测试窗 = 1~2 个月、每次前进一个测试窗」,但拿加密数据还是股票、 日线还是 1 小时线,都要重挑。这是由概念推导出的建议,不是官方白纸黑字的 规则——照做前先确认符合你的策略频率。

第三关:参数敏感度 — 你挑到的是山峰还是山脊?

同样一组回测拿到 Sharpe 2.1,可能是两种很不一样的东西:山峰—— 你刚好挑到那唯一的高点,任何一个参数挪一格数字就掉到 Sharpe 0.5;山脊—— 你周围一片参数都在 Sharpe 1.8~2.1,挪一格还是差不多。第一种是过拟合的教科书范例, 第二种才是可以搬上实盘的东西。

1
把「最佳」那组参数的每个维度都 ±10% 扫一遍,Sharpe 掉多少?
掉 50% 以上 →山峰。这组参数大概率是配这段历史的噪音,不要搬上实盘——回去检查逻辑或缩小参数空间。
掉 20~40% →边坡。可以继续往下看,但用小仓位测试。
掉 10% 以内 →山脊。这是你要找的形状,可以进第三步。
2
把每个维度上「还过得去」的参数范围画出来,加总后有几组能通过门槛?
只有那一组能过 →回去山峰那格处理。
有一整个连续区块都能过 →就从那个区块的中位数挑,不要挑最高点。中位数才是「你可以承受一点漂移」的位置。

把「参数 vs 绩效」的 3D 热图画出来看是最直观的做法。真的有规律的策略,图看起来会是 一片缓坡;过拟合的策略看起来是几根尖刺。这一步不需要新工具,用你已经在跑的最优化 结果自己画。

顺带一提:数据量够不够支撑你调的参数个数

参数愈多,过拟合愈容易——这句话几乎是常识,但少有人讲具体门槛。这里列一个粗略的 经验值,来自机器学习的一般原则(不是交易独有):每多一个要调的参数,你需要的独立 样本数会加倍成长。把「回测跑过的交易笔数」当成样本数来估:

2 个参数
至少 100 笔交易
3 个参数
至少 200 笔交易
5 个参数
至少 500 笔交易
7 个以上
多半已经无药可救

这是粗略的健康检查值,不是精确门槛。策略愈复杂,数字要往上抓。

如果你的策略跑三年只成交 40 笔,却在调 5 个参数,那不是「策略太挑」——是数据量根本 不够让你分辨「真的有效」与「刚好配到」。这种情况下,唯一有意义的动作是换更高频的 timeframe、或把参数个数砍到 2 个以内。

三关都过了:实盘上线前的最后两步

就算前面三关全过,也不建议直接开正常仓。上线之后的两件事同样关键:

  • 先开 1/3 或更小的仓位跑一到两个月。回测会漏算的东西——真实成交延迟、滑点、部分成交、交易所偶尔的拒单——只有实盘会告诉你。
  • 纪录每一笔回测 vs 实盘的偏差。同一根 K 棒的信号、实际成交价、以及最终 PnL 有没有系统性偏离回测预期。
  • 设定一个停止线:实盘累积亏损超过 X% 或连续 N 笔偏离回测,就先停下来检查——不要等到已经吃完 3 个月才发现不对。
  • 要把仓位放大之前,用实盘这一到两个月的数据再跑一次walk-forward验证。这是最诚实的一份 out-of-sample 数据。

仓位怎么从小开始加大,跟策略逻辑是两回事,属于资金管理的问题。这一段可以另外看 Kelly 公式与仓位大小 那篇,那边有讲「半 Kelly」为什么是实务常用的折衷。

这三关都帮不了你的事

讲完做得到什么,也该讲清楚做不到什么——这是这篇最容易被误解的地方。walk-forward 与参数敏感度都是「同一个市场环境」的验证, 它们对付不了下面这几种东西:

这几件事只有实盘会告诉你
市场结构性变化:加密的 2021 牛市与 2023 盘整期是两个不同的市场, 你用 2021 数据 walk-forward 出来的参数,换到 2023 一样会失效。
执行成本被低估:多数回测工具预设的手续费、滑点都是理想值, 真实的做市商库存、taker 手续费、部分成交都会啃掉一部分理论净利。
信号稀疏度:一年只触发 10 次的策略,就算 walk-forward 过关, 也可能只是这 10 次刚好对——样本太少,统计上没有意义。
你自己会不会关掉它:一组回测看起来能扛 40% 回撤,实盘跌到 20% 你就 睡不着关掉了——这是行为问题,测不出来。

诚实的一段:把回测数字放在该有的位置

这篇本身没有贴任何具体的策略回测数字,是刻意的——没有标的、期间、参数、样本外设定 一起附上的绩效数字,不管数字多漂亮,读者拿去做决策都是危险的。过去绩效不代表未来表现,这句话在回测结果上尤其成立: 回测是模拟,不是实单纪录。

如果你要在自己的文章、Twitter 或给付费订阅者的信号里放回测结果,最低限度该附上: 标的(例如 BTCUSDT.P)、时间范围(例如 2023-01 至 2025-12)、 参数组(不要只写「经最优化」)、有没有 walk-forward、以及一句「这是模拟结果, 不代表实盘获利」。少一个都会让别人没办法判断这份绩效值不值得跟。

这也是为什么建议在做量化之前先看 散户怎么开始做量化交易 那篇——里面有一整段在讲「年化 500% 不是 overfitting 就是还没崩」,可以当这篇的姐妹篇。

常见问题

walk-forward 的每个窗口都要重新挑参数吗?那不是等于一直在最优化?
对,这正是重点。walk-forward 模拟的是「你会定期重新调参数」这个行为—— 它不是为了找一组永远不动的最佳参数,是为了衡量「这个策略逻辑配上定期重调的流程」 能不能长期有效。实盘上真的要做的事,就是每隔一段时间用最新数据重跑一次最优化。
为什么参数敏感度要 ±10%,不是 ±20% 或 ±5%?
没有标准答案,10% 是合理起点。真实动机是「参数在实盘上会漂移多少 仍然算稳定」。如果你的参数本来就是很粗的档位(例如 EMA 只能是整数),改用 「±1 档」跟「±2 档」代替 ±10% 更合适。这是概念上的敏感度检查,不是精确公式。
in-sample 表现太差,能不能回去换策略逻辑,再走一次流程?
可以,但你有一次算一次——每回头改一次策略逻辑,数据就多被「看过」一次, 过拟合的风险就多叠一层。实务上常见的纪律是限制改的次数(例如三次为上限),并在最后把 hold-out 那块拿出来做最后检验。多改几次还是不行, 那可能是这个题目本身没有规律,不是参数的问题。
什么样的策略最容易过拟合?
几个高风险征兆:参数个数多(五个以上)、信号稀疏(一年少于几十笔)、用复合条件(三个以上指标同时成立才进场)、时间框架短但只回测几个月。四个占了两个以上就要特别小心, 回测数字愈漂亮愈可疑。
工具面上,这三关要怎么跑?
数据切法与参数敏感度大部分回测工具都做得到,关键是你要记得手动去切—— 不要按下「optimize」看到最佳结果就停手。walk-forward 有些平台有内置、有些要靠 Python (backtesting.py、vectorbt)自己组。先去自己工具的设定里找 「walk-forward」或「rolling window」的选项,没有的话就得把数据导出到别的工具做。

Get started

想把今天学到的东西自动化跑起来?

TVSBot 是非托管的 TradingView → 交易所自动下单平台。把你验过的策略接上 webhook,用你自己的 API key,先开 dry-run 或小仓位跑一轮实盘——这是「三关通过之后」该接的下一段。

免费开始