量化喵是独立第三方信息站,与任何交易所都没有隶属关系。本页不含推广链接与邀请码。 完整披露 →

回测 · 常见陷阱

回测很漂亮,实盘就亏钱:五个最常见的原因

回测曲线一路向上,接上实盘两周就开始亏——这大概是量化路上最让人泄气的一幕。多数人的第一反应是「运气不好」「行情不配合」,然后回去接着调参数。但绝大多数时候问题不在运气,而在回测本身:那条漂亮的曲线从一开始就不成立。

这篇不讲回测怎么跑(想补流程的看 策略回测怎么做),只讲一件事:回测是怎么骗你的。五个原因按隐蔽程度排,越往后越难靠自己发现,每个都配一条能立刻拿去用的自查动作。

漂亮的回测为什么值得先怀疑

先给一个反直觉的判断:回测结果越漂亮,越该先怀疑,而不是先高兴。

原因在于,回测是在一个已经知道结局的世界里做的。历史行情已经走完了,你在它上面反复试参数、改规则、加条件,本质上是在往答案上凑。凑得越贴合,曲线越好看,而未来的行情不会照抄这一段。真正有参考价值的回测通常长得平平无奇:有赚有亏,有像样的回撤,中间还有一段难受的横盘——因为真实的策略就长这样。

下面五个原因里,前两个是技术性的错误(回测本身写错了),后三个是样本性的错误(数据选得不对)。

原因一:过拟合,把噪音当成了规律

过拟合可以说得很朴素:你的策略学会的不是市场规律,而是这一段历史里的偶然。

它很少是一步到位的,而是一点点滑进去的。第一版跑出来一般,你把周期参数往上调了调,好看了一点;加一个过滤条件,又好看了一点;发现某段回撤特别难看,于是补一条「这种情况下不开仓」的规则——曲线自然更漂亮了。每一步看起来都合情合理,但连起来,你其实是在用后视镜给这段历史量身定做一件衣服。

三个自查动作:

  • 样本外测试。把数据切成两段,只用前一段调参数,调完拿后一段跑一次,而且只跑一次。如果后一段表现掉得很厉害,基本可以确定是过拟合。这一步的难点全在纪律:一旦你看了后一段结果又回去改参数,它就不再是样本外了。
  • 参数敏感度。把参数上下挪一点点再跑。健康的策略,参数微调后表现应该是缓慢变化的;如果稍微一动收益就塌,说明你找到的是悬崖边上的一个点,不是一片高地。
  • 数一数参数个数。一套只有两三个参数的策略,和一套带十几个开关、阈值、例外条件的策略,在同一段数据上,后者跑出漂亮曲线太容易了。参数越多,越需要更长、更杂的样本才撑得住。

原因二:未来函数,用了当时拿不到的信息

未来函数(look-ahead bias)是指策略在做决定的那一刻,用到了当时其实还不存在的信息。它比过拟合更致命:过拟合至少还是「真实但不可靠」,未来函数直接让整条曲线失去意义。

最隐蔽、也最常见的一种,是用当根 K 线的收盘价决定当根的开仓。代码里写着「如果这根 K 线收盘价上穿均线,就在这根 K 线买入」,读起来毫无问题;可现实中你要等这根 K 线走完才知道收盘价,而它走完的那一刻,这根 K 线已经过去了,你不可能回到中间某个价格去成交。回测里这一笔按当根价格成交,等于每次都提前知道了结果。

同类写法还有几种:用整段数据算完均值和标准差再回头做标准化;用「后面若干根有没有创新高」来定义训练标签;或者在数据表里做位移时方向弄反,把未来行填进了当前行。它们的共同特征是——不报错,回测照样跑完,还跑得特别好看。

自查方法只有一条,但要一个信号一个信号地问:做这个决定的那一秒,我手上真的有这个数吗?工程上有个习惯很管用——所有用于决策的指标一律往后错一位,用上一根已经收完的 K 线的值来决定这一根怎么做。宁可保守一点少赚,也别把结论建在拿不到的信息上。

原因三:幸存者偏差,归零的那些没进样本

挑测试标的时,你大概率是打开当前的行情列表,选几个熟悉又活跃的交易对。问题就出在「当前」两个字:今天还在列表里的,都是活下来的那些。

过去几年下架的、流动性枯掉的、项目方跑路归零的,不会出现在你的样本里。于是策略在一组「事后证明都没死」的标的上跑,自然显得稳健。真实交易时你没有这份先知——你选中的,可能正是后来消失的那批。

这个偏差在小市值币上尤其严重,在主流交易对上相对轻一些,但只要你的策略属于「在全市场里筛标的」那一类,它就一定存在。

包含已下架标的的历史数据在公开数据源里确实不好找。拿不到的话,至少做两件事:一是把回测标的固定成少数几个长期存在、流动性好的交易对,别拿「筛出来的最优组合」当结论;二是在结论里明确写上一句「本次回测未包含已下架标的」,免得过几个月自己都忘了这个口子。

原因四:手续费和滑点没算进去

这是最容易验证、也最常被跳过的一条。纸面上赚的那部分,常常刚好等于你没算的成本。

成本至少有三层:成交手续费(挂单和吃单通常不同价)、滑点(你想要的价格和真正成交的价格之间的差)、以及资金费率这类持仓成本(如果你测的是合约)。交易频率越高,这些成本被乘的次数越多——一个每天开平十几次的策略和一个一个月动两次的策略,对成本的敏感度根本不在一个量级。

做法是:先按你账户实际适用的费率把手续费加进去,再对滑点做一个明显偏保守的假设(具体取多少要看你测的交易对流动性和自己的下单量,自己代,别抄别人的数),然后看曲线还剩多少。如果加完成本收益就没了,那这个策略本来就不成立,和执行得好不好没关系。想先粗算一下成本占比,可以用工具页的 手续费计算器

原因五:样本期太短,只见过一种行情

最后一个原因看起来最无害,埋的雷却最大:你的回测只覆盖了一段风格单一的行情。

如果测试区间正好落在一段持续上涨里,那么几乎任何「敢拿住」的策略都会赚钱——不是策略好,是那段时间买什么拿着都涨。同理,一段长期横盘里跑出来的高胜率,换到单边行情里可能连着吃止损。所以样本期该看的不是「测了几个月」,而是「有没有覆盖过性格不同的市场」:涨过、跌过、横着磨过,最好还包含一两次剧烈波动。

这一点和策略本身的适用边界,其实是同一件事的两面:同一套参数在不同市场状态下的表现可能完全相反。这个话题单独写了一篇 同一个策略,牛市赚钱、震荡市亏光,样本这一关过了之后建议接着看。

拿到回测结果,先问自己这五个问题

回测跑完先别看收益数字,按这张表过一遍。顺序反过来的话,你会先被曲线说服,然后为它找理由。

问自己没过关的信号
参数是在哪段数据上调的?调完有没有拿没看过的数据跑过?全程只有一段数据,调参和验证用的是同一批
每一个下单决定,当时手上真的有那个数吗?用当根收盘价决定当根开仓;指标用整段数据算出来
测试标的是怎么选出来的?从今天的行情列表里挑「表现好的」那几个
手续费和滑点按什么口径扣的?没扣,或者按一个自己都说不清哪来的数扣
样本期里有没有出现过跟现在完全不同的行情?只覆盖了一段单边行情

五个问题里只要有一个答不上来,这份回测就先别拿去支撑真金决策。回测的价值从来不是告诉你「能赚多少」,而是尽早淘汰掉明显不行的想法——它是个筛子,不是水晶球。筛完之后,模拟盘和小额实盘那两步一步都省不掉。

风险提示:回测基于历史数据,不代表未来表现,任何策略都可能在实盘中亏损。加密资产价格波动剧烈,本金可能大幅缩水甚至归零,合约与杠杆可能导致全部本金亏损。本文是方法与常见错误的整理,不构成投资建议,文中不提供任何可直接套用的参数、收益或成本数值。请只用你能承受全部损失的闲钱,并自行对交易决策负责。

常见问题

回测收益很高,是不是说明策略好?

不一定,反而该先怀疑。历史行情已经走完了,在上面反复调参数很容易凑出一条漂亮曲线。判断一套策略可不可信,看的是它在没参与过调参的那段数据上表现如何、参数微调之后会不会塌掉、扣掉手续费和滑点还剩多少,而不是那条曲线的终点有多高。

怎么判断自己的策略是不是过拟合了?

三个动作:把数据切成两段,只用前一段调参数,调完拿后一段跑一次而且只跑一次;把参数上下挪一点再跑,看表现是缓慢变化还是直接塌掉;数一数策略里到底有多少参数、阈值和例外条件,数量越多越可疑。三条里有两条不对劲,就按过拟合处理。

什么是未来函数?为什么它特别难发现?

未来函数指策略在做决定的那一刻用到了当时还拿不到的信息,最常见的是用当根 K 线的收盘价决定当根开仓——收盘价要等这根 K 线走完才知道,那时已经没法回到中间去成交了。它难发现是因为代码不会报错,回测照样跑完,只是每一笔都提前知道了答案。

回测里手续费和滑点该怎么算?

手续费按你自己账户实际适用的费率代进去,挂单和吃单通常不同价;滑点没有通用数值,取决于交易对流动性和你的下单量,做一个明显偏保守的假设即可,别抄别人的数。交易频率越高,这两项被乘的次数越多。扣完成本收益就消失的策略,本来就不成立。

回测样本期要多长才够?

关键不是跑了几个月,而是这段样本里有没有出现过性格不同的行情。涨过、跌过、横着磨过,最好还包含一两次剧烈波动,这样的样本才算把策略压过。只覆盖一段单边上涨的回测证明不了策略,只证明那段时间行情好。

回测通过了,接下来该做什么?

别直接上真金。先去模拟盘按真实节奏跑一段,确认下单、断线重连、异常处理这些执行层面也没问题,再用一笔亏光也不影响生活的小钱做小额实盘,并盯住实盘成交价和回测假设之间的偏差。回测是个筛子,它负责淘汰明显不行的想法,不负责证明剩下的能赚钱。

把这五条当成体检表用就好:每次回测跑完先过一遍,再看收益。想把回测流程本身补扎实,去 策略回测怎么做;还没搞清量化到底是什么的,先看 量化交易到底是什么;至于策略在不同行情下会怎样,接着看 同一个策略,牛市赚钱、震荡市亏光