如何在不自欺欺人的情况下回测 AI 交易机器人
一份务实、不炒作的指南,教你如何验证 AI 交易策略:避免过拟合、使用滚动前进和样本外测试、计入真实成本,并识别重绘指标。
回测是交易者最接近水晶球的工具。它能让你在让 AI 交易机器人进入真实市场之前,先观察它在过去会如何表现。做得好,回测能在你亏掉真金白银之前暴露糟糕的想法;做得不好,它就会变成一台谎言制造机,产出漂亮的权益曲线和诱人的统计数据,然后在上线后悄无声息地崩溃。
这篇文章讲的是如何做好回测。它不是轻松获利的承诺,不是秘密公式,也不是"破解"市场的方法。它是一份面向散户交易者和开发者的实战指南,教你如何诚实地验证 AI 交易策略。我们将涵盖过拟合陷阱、滚动前进测试、样本外验证、真实成本建模、重绘指标以及稳健性检查。读完之后,你应该掌握一套可重复的工作流,让你的回测更难被愚弄,也更容易被信任。
1. 过拟合陷阱
过拟合是回测在实盘中失效的最常见原因。当策略被过度精确地调整到历史价格数据时,它捕捉的往往不是可重复的优势,而是随机噪音。结果是一条看起来好得不可思议的权益曲线,而这通常意味着它是假的。
AI 交易机器人尤其容易过拟合。机器学习模型可能有几十个、几百个甚至上千个内部参数。只要有足够的灵活性,模型就可能记住特定数据集的怪癖。它之所以能在过去准确知道何时买入卖出,是因为它实际上已经看过了答案。而在实盘交易中,问题变了,模型却不知所措。
自动交易还会放大这种危险。手动交易者可能会注意到策略开始变得奇怪,然后暂停并反思;自动化机器人不会停下来重新思考,它会继续根据已经不适用的规则下单。损失可能迅速累积。
以下是一张过拟合警告信号表:
| 警告信号 | 表现形式 | 为什么重要 |
|---|---|---|
| 参数过多 | 大量阈值、滞后、过滤器和例外规则 | 参数越多,越容易拟合到噪音 |
| 接近完美的权益曲线 | 平滑的对角线利润曲线,回撤极小 | 真实策略通常会有一些波动 |
| 样本内很好,样本外很差 | 训练数据表现优异,未见数据表现糟糕 | 说明模型在记忆而非泛化 |
| 入场时机过度优化 | 精准买在每日低点、卖在每日高点 | 可能在利用未来信息或微观结构偏差 |
| 参数脆弱 | 微小改动就让表现崩塌 | 真正的优势应该能容忍合理变化 |
| 交易次数太少 | 历史信号寥寥无几 | 统计显著性低,高度依赖运气 |
如果一个回测显示夏普比率高于 3、胜率接近 90%、几乎没有回撤,这通常不是 天才的证明,而是在警告:策略可能过拟合、成本被忽略,或者数据存在泄露。
过拟合的根源往往是好意办了坏事。交易者测试一个想法,看到结果平庸,于是开始添加过滤条件:避开财报日、跳过周五、只在 VIX 低于 20 时交易。每条规则都让回测好一点,但策略已经不再被验证,而是在围绕过去设计。等权益曲线看起来诱人时,优势已经被优化过程本身套利掉了。
要对抗过拟合,需要采取防御性心态。把回测当作一场试镜,而不是推销材料。目标不是让过去看起来赚钱,而是证明策略能在它没有见过的未来中生存。
2. 滚动前进测试
滚动前进测试是减少过拟合的最有力方法之一。与一次性在所有历史数据上优化策略不同,它在滚动的样本内窗口上反复优化,并在紧随其后的区间上测试。这个过程模拟了真实交易者实际运行机器人的方式:重新训练、测试、部署,然后再重新训练。
基本设置很简单。你选择样本内窗口大小,例如两年,以及样本外窗口大小,例如六个月。首先用前两年的数据优化策略参数,然后在未来六个月不改动参数地运行这些参数。之后,将整个窗口向前滚动六个月,在新的样本内区间重新优化,再次测试。重复这一过程直到数据集末尾。
| 组件 | 典型起点 | 注意事项 |
|---|---|---|
| 样本内窗口 | 1-3 年日频数据 | 足够长,以包含多种市场环境 |
| 样本外窗口 | 3-12 个月 | 足够长,以积累有统计意义的交易次数 |
| 步长 | 与样本外窗口相同 | 滚动窗口可避免重叠偏差 |
| 优化目标 | 风险调整收益,如夏普或索提诺 | 避免只看原始利润,因为它忽略风险 |
| 每轮保留的参数组 | 1-3 组最优参数 | 参数组太多会放大选择偏差 |
滚动前进测试有多个优势。它要求策略多次证明自己,而不是只证明一次。它能捕捉参数随市场环境变化而漂移的过程。它还能给出一系列样本外结果分布,这比单个 headline 数字更有信息量。
常见的两种形式是滚动式滚动前进和锚定式滚动前进。滚动式中,样本内窗口随每一步向前移动,训练数据始终保持新鲜和相关,但策略会遗忘较旧的市场环境。锚定式中,样本内窗口从数据集起点开始并随时间增长,保留了长期历史,但适应新环境可能较慢。
| 滚动前进类型 | 最适合 | 缺点 |
|---|---|---|
| 滚动式 | 快速变化的市场、短记忆策略 | 可能丢弃有价值的历史行情 |
| 锚定式 | 长期趋势策略、对市场环境敏感的模型 | 旧数据可能主导,减慢适应速度 |
滚动前进分析中一个有用的指标是滚动前进效率。它是年化样本外收益与年化样本内收益的比率。比率接近或高于 1 是鼓舞人心的;远低于 1 则说明优化结果无法迁移到新数据。
滚动前进测试并非完美。如果你尝试足够多的窗口大小、步长和优化指标组合,仍然可能过拟合整个滚动前进过程本身。关键是保持结构简单,在运行测试前就记录好选择,避免反复调整设置直到结果看起来好看。
3. 样本外验证
样本外验证是指在模型训练或优化过程中完全不看的数据集上测试策略。这是回测中最简单的概念,也是最容易被忽视的。如果一个策略从未在真正未见过的数据上测试过,它的历史表现毫无意义。
典型的错误是:在整个数据集上优化后,声称最后几个月的结果是"样本外"。只有在你开发过程中完全没有碰过那几个月时,它们才算样本外。一旦你看了一眼、调整了策略、重新跑回测,它们就变成了样本内。
对 AI 交易机器人来说,单一的训练-测试拆分往往不够。金融时间序列不是独立同分布的。趋势、波动率和相关性都会随时间变化。在牛市中训练的模型可能在熊市中失效,反之亦然。你需要尊重时间顺序并覆盖不同市场环境的拆分方式。
| 验证方法 | 做法 | 适用场景 |
|---|---|---|
| 简单训练-测试拆分 | 前 70% 训练,后 30% 测试 | 快速 sanity check,数据充足 |
| 滚动窗口 | 移动窗口训练,下一块测试 | 策略随时间重新优化 |
| 清洗 k 折 | 移除边界附近样本以防泄露 | 横截面或面板数据 |
| 禁运期 | 训练集与测试集之间留出空白 | 标签可能通过时间泄露时 |
| 基于行情的拆分 | 在一个行情训练,另一个行情测试 | 压力测试适应能力 |
样本外数据是一种有限资源。每当你偷看一眼、调整模型、再偷看一眼,你就在消耗它。 严格规定自己能看保留数据集的频率。
建议至少保留 20% 到 30% 的数据用于最终验证。如果策略交易频率很低,比如月度轮动模型,你可能需要多年的样本外数据才能获得统计上有意义的结果。对高频策略来说,几个月可能就够,但数据必须包含多样化的市场条件。
一种高级技术是嵌套交叉验证。外层循环定义训练和测试周期,内层循环进行所有超参数调优。这能确保参数本身不会过拟合到外层测试集。缺点是复杂度更高,增加了实现错误的可能。如果选择这条路,先用合成数据仔细测试你的流程。
另一个需要考虑的点是数据泄露。泄露指未来信息意外进入训练集。例如,用收盘价做日内决策、使用当时尚未公布的修正后基本面数据、或将标签在时间上前移。哪怕是很小的泄露,也能让一个毫无价值的策略看起来很出色。永远要追溯每个特征到它在真实交易中能被获知的精确时刻。
4. 滑点与手续费
再漂亮的回测,如果忽略了交易成本,也毫无意义。佣金、点差、借券费、市场冲击和滑点不是细枝末节,而是决定策略盈利还是亏损的关键。许多有前景的 AI 机器人一旦接触现实就死掉,不是因为信号错了,而是因为信号太微弱,无法承受交易成本。
从明确的成本假设开始。不要依赖平台默认设置。不同资产类别的成本结构差异巨大。在大盘股有效的策略,在小盘股或山寨币上可能被手续费压垮。高换手率的日内策略与低换手率的月度策略经济逻辑完全不同。
| 成本项 | 美股 | 外汇 | 加密货币 | 期货 |
|---|---|---|---|---|
| 佣金 | $0-$0.005/股 | 含在点差中 | 0.05%-0.5% | $1-$5/手 |
| 点差 | $0.01-$0.05 常见 | 0.1-2 pips | 0.05%-1% | 1-2 个最小变动单位 |
| 滑点 | $0.01-$0.10/股 | 0.1-1 pip | 0.1%-0.5% | 1-3 个最小变动单位 |
| 借券费 | 做空时 0%-30%+ | 无 | 无 | 无 |
| 市场冲击 | 占日成交量 1% 以上时显著 | 中等 | 低流动性币种较高 | 中等 |
滑点值得特别关注,因为它常被低估。滑点是信号触发时的预期成交价与实际成交时的成交价之间的差异。在平静、流动性好的市场中,滑点可能很小;但在快速行情、新闻事件或流动性差的品种中,滑点可能非常大。
要现实地建模滑点,需要考虑你的订单规模相对于日均成交量的比例。一个在 500 亿美元大盘股上回测表现良好的策略,一旦你的订单占成交量显著比例,就可能无法扩大规模。还要考虑订单类型。市价单通常滑点较大但成交概率高;限价单成交时滑点较小,但在快速行情中可能完全无法成交。
如果你的策略依赖频繁的小额单笔利润,滑点就是大敌。一个每笔交易目标 0.05% 收益的机器人, 可能因为一个最小变动单位的反向滑点或略宽的点差就被抹去利润。
市场冲击是另一个隐形杀手。随着资金规模增长,你自己的交易会推动价格反向移动。这在小盘股、期权和加密货币中尤其明显。假设你能按买价买入、按卖价卖出而不影响市场,这是幻想。对更现实的预期,应加入随订单规模和流动性缩放的市场冲击模型。
最后,别忘了融资和借券成本。做空需要借券,借券利率在轧空或 heavily shorted 的股票中可能飙升。杠杆仓位有隔夜融资费。加密货币永续合约的资金费率可能从正转负。这些成本从第一天起就应计入回测。
5. 重绘指标
重绘是回测虚假乐观情绪的最隐蔽来源之一。重绘指标会随新 K 线到来而改变历史数值。在回测中,它看起来仿佛能预知未来;在实盘交易中,它不能。
一个经典例子是 ZigZag 指标。在历史图表上,ZigZag 完美地标记波段高点和低点,看起来能在拐点给出精确的入场和出场点。但图表没有告诉你的是,随着价格发展,该指标会重绘这些点。只有当价格从高点显著回落后,波段高点才会被确认。等信号稳定下来,机会早已消失。
| 指标或特征 | 重绘风险 | 处理方式 |
|---|---|---|
| ZigZag、分型、波段标签 | 高 | 避免作为主要信号,用固定时间逻辑确认 |
| 当前 K 线的最高/最低价 | 高 | 只使用已收盘的前一根 K 线数值 |
| 多时间框架指标 | 中 | 等待更高时间框架 K 线收盘 |
| 机器学习预测 | 中高 | 只用决策时刻可用数据生成的预测 |
| 动态绘制的趋势线 | 中 | 明确绘制和重绘规则 |
| 会话或 VWAP 重置 | 低中 | 明确使用哪个会话的数据 |
重绘也可能发生在策略使用了决策点不可用的数据时。例如,一个日频模型在开盘时做出决策,却使用当天收盘价,这就是偷看未来。一个日内模型使用尚未收盘的 K 线的高点或低价,也是同样的错误。
要避免重绘,用时间点来思考。在回测的每一个模拟时刻,问问自己当时能获得什么信息。如果 K 线还没收盘,它的收盘价、最高价和最低价都是未知的;如果经济报告还没发布,它的数值不能作为特征;如果上季度财报的修正还没发生,原始公布的数值才是相关的。
算法交易中最昂贵的一句话是:"我就用收盘价。"如果你的策略在收盘前做出决策, 收盘价就是未来信息。请使用前收盘价或当前开盘价。
另一种隐蔽的重绘发生在机器学习特征工程中。假设你构建了一个特征,是某只股票过去一个月收益的排名。如果策略每天再平衡,而排名使用当天收盘价计算,你就是在使用未来信息。正确做法是使用前一天收盘价计算排名,并在第二天开盘时交易。
许多平台提供用于图表的"重绘"版指标和用于策略测试的"非重绘"版指标。学会区分它们。如果不确定,就自己写指标逻辑并审计每一个 K 线引用。一个差一的索引错误,就能让一个毫无价值的模型在回测中变成超级明星。
6. 稳健性检查
即使是构建良好的回测也可能很脆弱。稳健性检查就是主动在让市场搞垮你之前搞垮策略。如果优势能经受住现实的噪音、参数变化和市场环境变化,你就更有理由信任它。
从参数敏感性分析开始。稳健的策略不应依赖某个神奇数字。在合理范围内改变阈值、回看周期和仓位管理规则。如果小幅改动就让表现崩塌,那么优势很可能是特定参数的 artifact,而非真实现象。
| 稳健性测试 | 做法 | 好的表现 |
|---|---|---|
| 参数敏感性 | 关键输入变化 20-50% | 在较宽区域保持稳定正收益 |
| 蒙特卡洛模拟 | 随机化交易顺序或收益 | 回撤和权益曲线仍可接受 |
| 噪音扰动 | 在价格中加入随机噪音 | 扣除成本后仍能盈利 |
| 行情测试 | 在牛、熊、震荡市中测试 | survive 所有行情,即使某些行情盈利较低 |
| 资产类别迁移 | 应用到相关但未见过的市场 | 优势具有泛化能力,而非只针对某个品种 |
| 时间周期变化 | 在更高和更低周期运行 | 核心逻辑仍然成立,避免只拟合某一根 K 线大小 |
蒙特卡洛模拟是系统交易者 favorite 的工具之一。其思路是随机打乱历史交易顺序或扰动其收益,然后重新运行成千上万次绩效统计。这样你得到的是可能结果的分布,而不是单一路径。如果最坏情况仍然可接受,策略就更值得信赖。
蒙特卡洛方法展示的是过去可能发生的情况,而不是未来一定会怎样。它是一种压力测试, 而非保证。用它来为回撤和连亏设置现实预期。
噪音测试是另一个有用的检查。在历史价格中加入少量随机噪音,然后重新运行策略。脆弱模型会因为信号被调优到精确价格水平而表现崩塌;稳健模型则会继续表现,因为它依赖的是持久关系而非精确入场点。
别忘了操作稳健性。依赖完美数据流、即时执行和零宕机的策略在现实世界中会举步维艰。测试数据点缺失、订单被拒绝、仓位晚一根 K 线建立等情形。这些边界情况能区分可部署策略和理论策略。
稳健性的另一个维度是市场行情的独立性。市场会经历低波动、高波动、趋势、均值回归和恐慌等阶段。只在某一种行情中有效的策略,如果在回测期间恰好覆盖该行情,可能看起来很棒,但行情一变就会失败。确保数据集至少包含一次重大危机、一次强劲趋势和一段震荡盘整期。
7. 整合:一个验证工作流
验证不是一次测试,而是一系列策略必须通过的关卡,才能配得上实盘资金。以下是一个实用工作流,你可以根据自己的 AI 交易机器人进行调整。
-
定义假设。 用简单语言写下策略试图捕捉的市场非有效性。如果你无法简单解释它,模型可能过于复杂。
-
仔细构建数据集。 只使用决策时刻可获得的数据。清理缺失值时不能引入未来信息。在开始实验前就将数据分为训练集、验证集和最终测试集。
-
有纪律地训练。 先用简单模型。只有当简单版本失败,并且你有明确理由相信更多参数有帮助时,才增加复杂度。积极正则化以防止过拟合。
-
运行滚动前进测试。 在滚动样本内窗口上优化,在样本外区间上测试。提前固定窗口结构,不要为了改善结果而调整它。
-
加入真实成本。 用悲观而非乐观假设建模佣金、点差、滑点、借券费和市场冲击。如果策略在宽松假设下都只是勉强存活,它就无法在现实中生存。
-
检查重绘和泄露。 审计每一个特征、每一个指标、每一个订单价格。确认没有任何地方使用了未来信息。
-
压力测试稳健性。 进行参数扫描、蒙特卡洛模拟、噪音测试和行情测试。找出能搞垮策略的条件,并判断自己是否能接受。
-
先模拟交易。 即使是最干净的回测也不是实盘交易。先用模拟账户运行至少几周,最好覆盖与回测不同的市场行为。
-
从小开始。 正式上线时,先用计划仓位的一小部分交易。监控实盘表现与回测预期的偏差。如果实盘结果明显偏离,在加仓前停下来调查。
无论多少回测都无法替代停止亏损策略的纪律。在实盘交易前就设定最大回撤规则, 即使回测说你本不该亏损,也要遵守它。
这个工作流并不刺激,也不会在第一次尝试时就产出完美的权益曲线。这正是重点。目标是区分真正具有优势的策略和那些只是因为被优化到好看才显得有优势的策略。
8. 常见问题
回测中的过拟合是什么?
过拟合指策略被过度调优到历史数据,以至于捕捉到的是噪音而非真实优势。它会生成漂亮的回测曲线,但上线后通常表现糟糕。
我需要多少样本外数据?
建议至少保留 20-30% 的数据用于最终验证,并覆盖不同的市场环境。如果交易频率较低,样本外数据越多越好。
什么是滚动前进测试?
滚动前进测试会在样本内窗口上反复优化策略,然后在紧随其后的样本外区间上测试,再向前滚动窗口。它模拟了真实交易中的重新优化过程。
为什么滑点和手续费如此重要?
即使每笔交易的成本很小,长期累积也会非常可观。一个在忽略成本时看似盈利的策略,一旦计入佣金、点差和滑点,很可能变成亏损策略。
什么是重绘指标?
重绘指标会随新 K 线到来而改写历史数值。它们在回测中看起来像能预测未来,但在实盘交易中无法执行。
如何对策略稳健性进行压力测试?
可以使用蒙特卡洛模拟、参数敏感性分析、噪音扰动测试,以及在牛市、熊市和震荡市等不同行情中进行样本外测试。
总结
回测必不可少,但它也很危险,因为自欺欺人是如此容易。市场不在乎你的纸面权益曲线有多漂亮。它在乎的是,你的策略在扣除成本、实时运行、且面对从未见过的情况时,是否仍能提取真实优势。
通过滚动前进测试和真正的样本外验证来保护自己。诚实地建模成本,消除重绘,并对稳健性进行压力测试。最重要的是,保持现实预期。一个经过仔细验证、纪律执行的小优势,胜过一个一开启就崩盘的华丽回测。
无论你是自己构建还是购买 AI 交易机器人,最重要的问题不是"它在回测中赚了多少钱?"而是"要让这套策略继续有效,必须满足哪些条件?"诚实地回答这个问题,你就已经领先于大多数交易者。