策略智能体即使没有把任何测试行放进训练任务,也可能污染测试集。如果智能体看到测试分数、调整参数,然后再次运行,这个分数就已经影响了策略。代码里或许把这段时间称为“样本外”。但研究流程已经把它纳入搜索范围。
我见过这种情况,往往是图方便造成的:智能体跑完一批实验,读取汇总表,然后提出一项小改进。没人要求它在留出集上拟合,但反馈循环还是完成了拟合。
错误 1:让智能体每次运行后都查看结果
常见的后果是测试 Sharpe 规规矩矩地逐步上升。智能体先试 30 个变体,留下最好的那个,再围绕它试 30 个变体。每次单独的改动看起来都合情合理,累积起来却把测试期变成了优化目标。
来看一个简单例子。假设策略没有真正的优势,你在留出集上测试 100 个彼此独立的变体。如果选取 Sharpe 最高的那个,完全可能碰巧得到一个看起来很漂亮的结果。大多数策略搜索中的变体并非真正独立,但这并不能挽救整个流程:反复利用反馈,仍会奖励那些碰巧拟合了留出集特性的设置。
把留出集隔离在结果边界之后。智能体可以基于训练期和验证期进行开发,但不能读取留出集的指标或图表。将最终评估放在单独的任务中,等研究决策全部冻结后只运行 1 次,并把策略版本和数据快照与结果一并记录。
错误 2:把所有更晚的时期都称为“全新”
某个日期范围并不会仅仅因为晚于训练窗口就变得全新。如果智能体看过该范围的分数,或者研究人员根据其中的回撤换了特征,那它就已经进入反馈循环。
| 时期 | 允许的用途 | 哪些情况会改变其状态 |
|---|---|---|
| 训练期 | 拟合规则和参数 | 无;它本来就是供搜索使用的 |
| 验证期 | 比较候选方案并做出研究决策 | 反复使用会增加过拟合的可能 |
| 最终留出集 | 对冻结后的候选方案评估 1 次 | 查看结果后再修改候选方案 |
| 未来模拟交易期 | 前瞻观察策略的实际运行表现 | 利用结果调参会开启新的研究周期 |
滚动前向评估有助于估计固定研究流程在不同时间段的表现,但这并不意味着可以无限次查看每个折的结果。如果智能体看过各折结果并据此调整搜索,那些折也成了反馈数据。请保留一段最终未触碰的时期,用于做出你真正关心的决策。
错误 3:冻结代码,却改变评估问题
有时策略代码保持不变,但研究人员看过结果后更改评估方式:更换基准、排除表现糟糕的月份、换一组标的,或只报告看起来最好的指标。即使参数没变,测试集也已经影响了研究结论。
常见后果是一份包装精美的报告,只有一个漂亮的标题结论,却没有记录尝试过的其他视角。股票策略对比广泛市场指数时可能表现平平,对比现金时却显得很强;加密策略可能是在检查过多个平台后,才发现它在某个平台上表现出色。这些比较本身有用,但看过留出集结果后再从中挑选,又多了一次筛选。
维护研究日志。每次运行都保存假设、代码版本、数据快照、参数搜索、评估窗口、请求的指标,以及智能体或研究人员是否看过结果。一份简洁的日志,比一个听起来完美的“样本外”标签更有用。
然后在评估前明确最终问题:选哪个候选方案、哪个市场范围、哪个基准、哪些成本和哪些指标?如果结果出来后答案变了,就把下一次运行视为研究,并为下一次最终检查预留新数据。
被污染的留出集还能告诉我什么?
它并非毫无用处。它可以展示策略在该时期的表现,也有助于诊断失败。只是不要再把它的分数说成独立验证。把它作为开发证据,冻结下一个候选方案,再用真正未来的模拟交易期评估该方案,并沿用相同的核算和执行假设。
在智能体驱动的工作流中,实验次数很容易失控:一个提示词就能生成几十次运行,等到有人察觉时已经晚了。解决办法在于流程管理。限制智能体能查看的内容,记录每次实验,并保留 1 次评估,确保其结果无法左右正在接受评判的候选方案。
← 全部文章


