每一行公式都算对了,回测却总能在好消息前买入。沿着输入的公开时间往回查,才发现有些数值在决策那天还不存在。怎样查出这种“算术正确、信息越界”的结果?
未来函数不一定是代码里写了“读取明天”。它也可能藏在今日成员名单、后来修订的财报、全样本计算的平均值,甚至研究者反复打开测试成绩的动作里。我们先找到第一处越过时间线的连接,再逐项修复。
这次要解决的问题
- 用可得时间和处理顺序定位成交、数据与研究过程的泄漏。
- 分别纠正三类可复查错误,说明数字改变与尚未证明的部分。
- 设计故意扰动与时间截断检查,保存一张泄漏审查记录。
所有输入,都得回答同一个时间问题
把G33的时间表延伸到一次完整决策:业务或交易发生,资料公开,自己取得,完成核验与预处理,形成信号,最后才尝试执行。每条输入都应能走到这条链上,而不是只带一个“日期”标签。
数据泄漏是预测或决策时本来不可用的信息,进入了模型构造或评价。scikit-learn官方文档将测试资料用于模型选择、预处理学习等列为常见来源。[1] 对投资研究,还要追问历史记录的版本和可执行时点。
以下三个查错任务为C4错误实验室的隔离练习。第一个复用C4-S1已定五日价格和账本规则,另列错误执行版本作比较;其余财报和数值材料为独立合成输入,不改变C2或C4-S1规格,不冒充真实公司数据。
| 要追查的记录 | 错误连接 | 修复首先要找到什么 |
|---|---|---|
| 收盘信号与成交 | 看完整收盘后仍按同一收盘成交 | 信号完成与实际最早执行时点 |
| 财报与成员 | 把期间、今日版本或未来身份当作过去已知 | 发布、取得、修订及成员有效时间 |
| 数据预处理与模型 | 用后段数据学习过去的处理规则 | 每次训练时点的可用范围与固定转换 |
这张表不是三种检查通过就能保证无泄漏。它帮助你把模糊怀疑缩成一个可以找到输入、输出和时间证据的问题。
错误一:收盘后才知道,却按那个收盘成交
C4-S1从1000美元现金开始,无持仓;收盘严格大于11才以20股为目标,否则目标0。下一列示交易日开盘执行非零调整,每个成交订单费用1美元,现金不足整笔拒绝,主例没有缺价或公司行动。
G39已给定D2收盘12、D3开盘13且收盘11、D4开盘10。正确路径是D2收盘产生买单,D3开盘买20股,支出260加1,剩739;D3收盘产生卖单,D4开盘收200再付1,现金938,后续无新成交。
现在只引入一项错误:收盘完成信号后,立即按同一个收盘价执行。于是D2按12买20股,剩759;D3按11卖出,收220付1,最后978。两版初始资金与每次费用相同,差40美元,累计收益从正确的负6.2%变成错误版负2.2%。
错误版没有神奇地减少风险,只是换了执行条件。在这份规格下,完整收盘价要等收盘后才可知,不能反过来保证自己已经参加了那次收盘交易。修复后成绩下降,是时间顺序恢复的结果,不是应该把错误改回去的理由。
也不能推广为任何收盘成交都必然错误。若另一策略依据此前已知信息,符合相应订单与交易机制,属于需要单独核验的规则;这里错误的是把本例完整收盘信号与同收盘保证成交相连。
错误二:财报的日期,写成了数据可得日期
再看独立合成资料,以下时刻统一采用同一明确时区。某季度截至3月31日,收入100;5月13日08:00首次公开,08:05研究程序取得,08:10完成核验。6月10日另有更正,把该季度收入改为90。
如果回测把100放在3月31日的决策输入里,就提前使用了尚未公开的季度结果。若今天下载的文件只留下90,又将90回填5月15日的旧判断,则是把后来修订也送回了过去。
修复不能只做“全部滞后一天”。应按实际公开、取得与处理时间连接:3月底这项结果不可用;在5月13日08:10以后,才满足本例自己的处理条件;5月15日版本仍是当时可得的100,不是6月才知道的90。何时成交,还要再接对应市场日历与策略规则。
EDGAR说明带“/A”的表单为修订文件,但修订的内容和可得时间仍需单独检查。[2] 并非任何今日数据库都能返回所有旧版本;若历史版本无法取得,就记录限制,不用当前正确数值假扮当时已知值。
同样的连接错误会出现在成员数据。若一只证券在7月宣布、8月才加入指定指数,不能因今天它是成员,就允许1月的原指数成员策略选择它。修复应回到当时的资格、公布与生效记录,保持与G34的股票池定义一致。
这一步可能改变信号和持仓,也可能在某段样本里没有改变收益。没有变化不证明数据连接正确,有变化也不证明新策略有价值;先检验时间关系,再评价经济结果。
错误三:模型没看收益,预处理却看了测试段
有人说:“我没有把未来收益放进输入,只是先把全部数据统一处理一下。”可处理参数本身也可能带回未来信息,尤其是用全样本均值、标准差、缺失填充值或筛选结果。
用一份独立合成特征表看得更清楚。训练时已经可得的两个数为2、4,后来的测试段为100、102。若只用训练段学习均值,得到3,数值4减均值后为1;若用四个数一起学,均值52,过去的4便变成负48。
假设模型判断“处理后严格为正”时触发条件,过去同一个4就从满足变成不满足。未来值没有直接出现在那一行,却通过平均值改变了它。这是计算过程泄漏,不是数据单位统一的无害步骤。
修复是先按研究时间划分资料,只从当时允许的训练资料学习处理参数,再固定这套参数转换相应后段输入。官方文档明确区分学习预处理与应用相同转换,也指出特征筛选等步骤同样可能泄漏。[1]
本题是演示均值居中,不是建议采用这种投资信号。原始特征的含义、样本选择和模型训练仍需自己的依据;把训练段单独处理正确,只是修好了一条连接。
填补缺失也可以沿同样方式检查。若M5的特征为空,工具拿M6才公布的值补回M5,即使用的只是“最近一项”,方向仍是从未来回到过去。沿用更早已知值则未必穿越时间,却还需说明它是否过时、规则是否允许。一个叫“填补”的按钮,可能对应这两种完全不同的研究条件。
标签的结果,可能还活在未来几天
如果要预测未来若干交易日收益,标签就是之后结果。建模时可以用已经结束的历史标签,但训练截止时尚未实现的标签,不能因为它写在较早那一行,就被算成已知。
例如,用D5作一条训练输入,其标签覆盖D5之后至D10的收益;模型却在D5收盘就训练完,并从D6开始测试。标签要到D10才完整知道,这次训练已经借用了后面的结果。仅按输入行日期把表切成两段,没有修好它。
需要检查每条标签所覆盖的区间和最晚可得时间,排除跨越当前训练边界而尚未知的标签,或重新设计训练与测试安排。重叠结果也可能共享信息,影响独立证据的解释。
scikit-learn的TimeSeriesSplit提供按时间顺序划分与设置间隔的工具接口。[3] 但一个固定的间隔数不会自动理解财报延迟、标签期限、交易日历或多资产时间。是否足够,要根据本题真实数据链核查,而不是只看到函数名就宣布无泄漏。
测试结果,也能从人的眼睛回到模型
假设原来答应只用开发段选窗口,最后用测试段评价。研究者跑完测试,看到效果不好,改窗口再试;循环多次,最终只交最好一版。即使程序每次没有直接读取未来标签,测试表现也已经参与选择。
修复应如实记录测试段已被使用、全部尝试和改变理由,重新安排评价,不把它继续称为完全未接触的检验。某段历史被作者反复分析过,也不能靠重新命名“留出”而变回未知未来。
这里先定位泄漏路径,多次尝试和结果挑选将在G42展开。一次规则冻结后的真正前瞻记录,与作者知道后续的历史教学留出,需要分开报告。
故意动一动未来,看过去是否跟着变
可以把这三类错误变成具体检查。先保存截止某决策日的原始输入、处理参数和输出,再把之后尚不可得的资料临时移走或改动,检查此前输出是否改变。改变的应是测试副本,不覆盖原始材料。
在合成财报例中,把6月10日修订90改为另一个数,不应改变按当时版本重建的5月15日输入100。若旧信号随之变化,就找到了一条需要追踪的未来连接。
在特征例中,把测试段100、102改成别的值,训练段均值仍应为3,过去4的处理结果仍为1。若它跟着变,先查是否把处理参数在全样本上重新学习,而不是把变化归为模型“更全面”。
交易检查则要核对每笔成交使用的输入何时完成。也可做逐步截断:只提供当时已知资料,是否还能复现相同信号与订单?最终权益会随之后的真实价格变动,这本身不是泄漏;检查对象是过去决策,而非要求未来收益永远不变。
扰动通过只能增加对所查路径的信心。没有被改动的字段、未覆盖的分支、错误时间戳或隐蔽选择,仍可能漏查。全局把所有字段机械移后一天,也可能既没解决慢披露,又错误移动本来即时可得的价格。
先查错,再说明修复改变了什么
解释题:错误版C4最后978,为什么不是比938更好的有效策略证据?应用题:某工具说“财报已经统一推迟一个交易日,所以没有前视”,你会先查哪两项时间?先写答案再核对。
第一题中,978来自违反原规格的同收盘成交。它可以作为独立错误对照,不能冒充原规则的合法结果。第二题应核财报首次公开与实际取得、处理完成;相对报告期末只推后一天,仍可能早了数周。
换一个预处理输入
另一份独立合成记录,训练段为10、14,后段测试为30、34。助手先用四项总均值22处理,得到训练中的14为负8,然后声称训练与测试已经按行分开。请写出仅用训练段的正确均值、14的转换结果,并提出一次能复查的扰动检查。
训练均值是12,14应转成2。先分段再只从训练段学习参数,不能用表格已经分开掩盖前面全样本处理。将后段30、34改为其他值,训练均值12与过去输出2应保持不变;若改变,继续沿参数来源追查。
最后再说明哪些未验证:本题没有回测真实成员、交易与收益,也没有证明这种特征有预测价值。修复输入时间,与证明投资能力是不同任务。
保存你的泄漏审查记录
挑一条信号,逐项列出价格、财报、成员、公司行动、预处理参数和标签各自的观察范围、公开与取得时间、版本、处理完成时间、允许使用位置。再将订单与成交接上去,标明证据或缺口。
至少保留三项可复查错误、修复前后输入与输出、变更原因及影响范围。先一次只改一个错误,再做组合检查;费用、样本和规则也若同时变化,要另列说明,不能把全部收益差归给一次修复。
自检时问:另一位读者能否重现第一处时间越界?故意改变未来资料时,过去对应输出是否稳定?无法核实的历史版本或成员资料,要限制结论;不要把AI给出的“检查通过”当作独立证据。
小结:查的不是日期标签,而是信息怎么走
先沿同一条可得时间线,把信号、数据版本、处理参数和标签连到决策,再连到执行。过去的输入行不保证里面只有过去信息,当前正确的数据也不等于当时能知道的版本。
修复后数字变差可以是查错成功,数字不变却不保证无错。用隔离修复、时间截断和未来扰动留下可复核记录,再诚实说明未查范围,才有条件讨论这段研究还剩多少可信证据。
参考资料
- scikit-learn:Common Pitfalls—Data Leakage。训练/测试分离、预处理与特征筛选的学习范围;文中数值为独立合成输入。
- Investor.gov:Using EDGAR to Research Investments。公开申报及修订标识;不保证任何数据源提供全部历史版本。
- scikit-learn:TimeSeriesSplit。时间顺序与间隔功能,只作为方法边界说明,不要求读者写程序,不将默认参数当完整金融防泄漏方案。
资料核查日期2026-10-29。本文由AI辅助编写与检查,C4-S1正确/错误路径及补充例子均为教学合成资料,未宣称真实研究已经排除所有泄漏。