周一,我们的 AI 研究智能体找到了一套加密货币期货策略,Sharpe 比率达到 4.1。到了周四,在统计了实验次数并停止让智能体针对同一个验证窗口反复调参后,结果变成了 0.8。策略本身没变,变的是我们对搜索成果的估计。
我们把这项工作当作一份简短的研究日志来做,因为“谨慎优化”说起来容易,但当智能体能写代码、启动回测、查看评分,并在几分钟内再次尝试时,要把这条建议落实到操作中却很难。下面按顺序记录这过程中出了什么问题。
周一:给智能体一个边界明确的问题
我们让智能体在一个流动性较好的永续期货市场上测试一个简单的小时级趋势思路:短期移动平均线向上穿越长期移动平均线时入场,按固定波动率目标设定仓位,并在反向信号出现时平仓。我们指定了交易品种、日期、费用表、资金费率历史、执行假设,以及可供探索的参数范围。
历史样本覆盖 2021 至 2025 年。我们将 2021–2023 年用于开发,2024 年用于验证,并将 2025 年封存为最终留出集。这个划分写入了任务配置,因此智能体可以读取开发结果和验证评分,却无法获取留出集的收益。
我们的第一个错误,是在一次任务中允许测试 300 种参数组合,却没有把搜索预算作为研究结果记录下来。智能体返回了表现最佳的组合:快速均线为 9 小时,慢速均线为 73 小时,波动率目标为 0.8%。它在验证集上的 Sharpe 为 4.1。我们知道智能体尝试了很多设置,但当时还没采取措施,让我们无法忘记这一点。
周二:重新运行后,赢家变了
我们在干净的环境中重新运行了同一个任务。排名第一的设置变了,Sharpe 也降到了 2.7。第一次运行时,市场数据缓存提供的是更新后的资金费率序列,而重跑时使用的是固定快照。两次任务都声称使用了相同的日期范围,但只有一次记录了可复现的数据版本。
我们不再比较评分,转而记录完整的实验信息:代码修订版本、数据快照、费用、资金费率、执行设置、参数值,以及智能体启动的每一次试验。由此可见,4.1 并非什么神秘的市场优势,而是同一个验证年份上 300 次尝试中的一个设置的结果。
周三:打开留出集前冻结搜索
我们使用固定的数据快照和更小且预先声明的网格重新进行了实验,共 24 种组合。智能体可以根据 2021–2023 年的开发期数据对它们排序。我们只让它查看一次 2024 年的数据用于筛选,随后锁定选定的设置和代码。
选出的策略在验证集上的 Sharpe 为 0.8。在封存的 2025 年留出集上,计入 taker 费用、资金费率,以及整个研究中始终采用的 1 根 K 线执行延迟后,Sharpe 为 0.3。这是一个有用的答案,但不能证明该策略在实盘账户中会赚钱。
说句题外话:这周我们花在商定“单次试验”定义上的时间,比写移动平均线代码还多。我们把变更参数集算作一次试验,变更信号或仓位规则的运行也同样计入。新的数据快照或执行假设则单独记录一次运行,因为它们同样可能改变排名。
周四:下次我们会省掉什么
我们会省掉最初那次没有明确边界的任务。研究智能体需要搜索预算,也需要记录尝试过什么,尤其是它能够利用每次结果决定下一步尝试什么。留出集也需要防止非正式地被提前查看:一旦有人读了结果并据此修改策略,它就变成了另一个验证集。
对于小规模搜索,一份实用的实验记录表可以写得简单明了:
| 记录内容 | 重要原因 |
|---|---|
| 代码和数据版本 | 确保重跑时使用相同的输入和逻辑 |
| 每一种尝试过的变体 | 结合整个搜索过程理解胜出结果 |
| 开发集、验证集和留出集的用途 | 避免最终评分被悄悄拿来调参 |
| 费用、资金费率和执行假设 | 确保报告的结果描述的是可测试的模拟交易 |
打开留出集后,带着新的研究问题回到开发阶段,并将旧结果作为历史证据保存。不要针对策略已经看过的时期,继续打磨同一套策略。
智能体完成了自己的工作:它迅速进行了搜索,并找到了值得进一步研究的配置。我们的工作则是让搜索过程清晰可查,保留一份未触碰的测试集,并把评分视为有来历的测量结果。真正有意思的发现不是 4.1 或 0.3,而是我们准确看清了第一个数字是如何产生的。
← 全部文章


