前言|历史答卷交完了,下一张才是新试卷
假设我们已经认真检查了一套动量策略:没有偷看未来,没有删掉退市股票,成本也计进去了。参数不是只挑历史第一名,因子经过排序、组合和行业市值检查。此时最容易说出口的一句话是:“该上场了。”
可历史研究解决的是过去的数据在既定假设下支持什么。它还没有告诉我们,明天新来的行情能否按时进入系统,信号能否按约定生成,未成交订单会怎样影响账户,以及连续几次亏损之后,研究者能不能忍住不改规则。前九篇把回测拆开审查,第十篇则把这些检查带到规则确定之后的每一天。
本文讨论的是怎样组织后续验证,不是宣布某套策略已经具备实盘资格。本项目已有日终模拟账户服务,但它通过重放回测生成账户结果,并不连接券商提交真实订单。文中的流程图和记录表都是方法示意,没有新运行的模拟业绩。这个边界会贯穿全文。
目录
- 前言|历史答卷交完了,下一张才是新试卷
- 01|先说清楚:我们到底在验证什么
- 02|冻结的应是方案,而不只是参数
- 03|日终重放与前瞻记录,是两种证据
- 04|每天留下从数据到账户的一条链
- 05|结果偏离时,先找哪一环变了
- 06|继续、暂停、修订,规则写在出事之前
- 07|阶段报告,不能只贴一条净值线
- 08|十篇之后,给研究立下什么标准
- 关于本文的研究口径
- 参考资料
01|先说清楚:我们到底在验证什么
后续验证至少包含两件事。第一件是研究判断:固定规则面对后来行情时,是否仍有预期的排序、收益与风险特征。第二件是运行过程:数据、信号、订单、费用和账户是否按事先说好的方式衔接。策略亏钱不一定是程序坏了;程序运行成功也不等于策略有预测力。把两件事混在一起,会让每次失败都变成一句笼统的“系统不行”。
图1:验证问题示意。两项检查都需要证据,不互相代替。
先为观察期立一个明确起点。规则在某天确定,只有此后尚未被用于挑方案的行情,才可能作为新的检验。把模拟账户的开始日期设到几年前,再在今天创建账户,不会把此前几年变成前瞻业绩。账户可以包含历史起点,但报告必须把历史研究段与登记之后的观察段分开。
也不能靠一个统一的天数宣布“验证通过”。几个月里若只有两次调仓,许多成交和风险条件都没遇到;一段持续上涨的行情,也没有测试策略面对其他环境的表现。观察期长度、调仓次数、有效样本与曾经出现的异常都应一起报告。样本少的时候,结论应是“尚不足以判断”,而不是为了完成流程勉强颁发合格证。
02|冻结的应是方案,而不只是参数
固定20日窗口,只是冻结了一小部分。股票资格、价格口径、调仓时间、持仓数量、资金、组合方式、交易费用、参与率和风险规则,都能改变结果。真正需要留档的是一份完整方案:用什么资料,在什么时候计算什么信号,以什么规则形成订单,再怎样处理成交与异常。
图2:方案登记示意。版本标识用于辨认文件是否改变,不保证内容本身正确。
本项目模拟账户会保存策略标识、参数、起始日期、资金、持仓数、调仓方式和风险限制。但下一次推进时,它仍通过回测服务加载当前代码、行情和相关配置。账户保存的请求并不等于自动保存了整套代码副本、数据快照与所有成交设置。因此,“账户创建后没有改参数”还不能证明实验口径从未改变。
研究者应另外登记代码和配置版本、数据截至日期、数据修订情况及相应文件。版本号或文件指纹的作用,是让之后能够发现不同;它不是质量评级。若数据供应方修订了旧行情,或税费与执行配置被更新,即使研究者没有改策略公式,重放结果也可能不同。此时应保留旧结果,注明改动,不把新结果覆盖成“当时就是这样”。
第五篇讨论过反复试参数,第八篇讨论过反复改因子权重。进入观察期之后,同样的选择问题并不会消失。Bailey等人的回测过拟合研究提醒了从多次尝试中选赢家的风险。[1] 如果每次亏损就调整规则,再把修改后的历史重放拼成一条最优净值,那仍是在选择历史,而不是验证原来的方案。
03|日终重放与前瞻记录,是两种证据
平台的日终模拟账户在推进到某个日期时,会按保存的请求,从起始日重新运行到目标日,生成一个新的运行编号。它适合检查在当前资料与模型下账户应如何变化,却不是把昨天的真实账户接到今天、向券商提交订单的交易系统。
图3:日终重放提供重新计算的结果;前瞻记录保存当时知道什么、决定了什么。两者不能混用名称。
例如昨天保存了一次运行,今天更新数据后再推进账户。若旧日净值或订单也改变了,先比较输入与规则。原因可能是数据修订、配置变化、代码变化,也可能是错误;不能因为新结果更好,就悄悄用它替换昨天的记录。保留“当日生成版”与“后来重算版”,并说明差异来源,才能让读者辨别真实研究过程。
仅保存最新运行编号也不够。账户记录指向最新结果,研究日志应另外把每次推进日期、生成时间、运行编号、输入版本和异常写下来。后续验证的关键不在于能否在今天重算出一条历史线,而在于能否证明每一天的规则和决策在结果出现之前已确定。
真正成交还隔着另一层。日频模型可能模拟次日开盘成交,但券商实际委托会遇到提交时间、排队、盘口和部分成交。前六篇的成交与容量检查仍是必要的模型检验,却不等于已观测到这些现实细节。没有券商回报,就不能在报告中把模拟成交写成真实成交。
04|每天留下从数据到账户的一条链
一份日报无需很长,却至少要能回答五个问题:数据更新到了哪一天?哪个版本计算了信号?计划买卖什么?模型实际模拟成交了什么?账户结果怎样与明细对得上?没有调仓的日子,也要记录数据与账户状态,不能只在收益好看的日子留下截图。
图4:记录流程图。并非所有字段都能从现有页面一键导出;需要另行保存的部分见截图指南。
本项目每次成功回测会保存净值、信号、目标持仓、订单、成交、持仓、完整交易、风险事件、公司行动,以及汇总、审计与配置快照。这些文件提供了复核账户的基础。页面截图方便阅读,却不能代替逐笔记录;一个“总收益”截图也无法证明成本没有遗漏。
还要区分“今天运行过”和“成功更新到了今天”。模拟账户推进失败时,记录会标为失败,但仍可能保留上一次成功结果的编号与日期。旧净值不能冒充今天的新结果;缺失的一天也不能随手补成零收益。日报应同时写清运行时间、最后成功的交易日期和失败原因,恢复后另存补算结果,再解释它与此前记录如何衔接。
对没有外部出入金的账户,每日账本首先应满足:
E t = C t + ∑ i q i , t P i , t E_t=C_t+\sum_i q_{i,t}P_{i,t}Et=Ct+i∑qi,tPi,t
E EE是总资产,C CC是现金,q qq是实际持仓数量,P PP是相应估值价格。该式看起来简单,却要求现金、持仓与价格在同一个时点对齐。分红、拆并股、退市结算和费用也要进入相应明细,不能只凭一条净值曲线说账本正确。
在同样没有外部出入金的前提下,日收益可写为:
r t = E t E t − 1 − 1 r_t=\frac{E_t}{E_{t-1}}-1rt=Et−1Et−1
若以后扩展到真实账户并有追加或提取资金,就不能原样用这条式子计算投资收益,需要另行处理现金流。本文当前记录方案不把外部入金造成的资产增加当作策略赚到的钱。
05|结果偏离时,先找哪一环变了
最需要克制的时刻,往往是净值连续下跌的时候。研究者很容易立即怀疑因子失效,或者反过来认为只要程序没报错,亏损就完全正常。两种判断都太快。先把偏离定位到数据、信号、目标仓位、模拟成交和账户五个环节。
图5:定位流程。每一步应有对应文件或日志,不能仅凭净值形状推断原因。
数据晚到时,应先核实是否使用了旧分数;信号变化时,检查候选股票和价格口径是否一致;目标相同而持仓不同,查订单数量、整手限制、风险约束与未成交原因;模拟毛收益尚可而净收益变差,查换手与成本;所有过程符合规则但表现仍弱,才进一步讨论市场环境与信号的预测关系。
比较也要公平。历史研究与后续观察的日期、初始持仓、现金和交易规则都可能不同。将一个全仓历史组合与一个刚开始建仓的模拟账户直接比较,资金利用率差别就足以影响净值。应同时展示仓位、现金、成交缺口与相同期间基准,不能把所有差距归给“策略衰减”。
此外,“波动较大”不等于“代码错误”,短期亏损也不能单独证明因子已经失效。诊断应先报告事实:哪段期间、多少次调仓、哪些股票、哪些费用或拒单在起作用。若缺少证据,就把原因记为待查,而不是给每次亏损编一个听起来合理的市场故事。
06|继续、暂停、修订,规则写在出事之前
后续验证不是永不修改的耐力比赛。输入数据错误或运行不可复核时,暂停是合理的;研究假设被充分的新证据否定,也可以提出新方案。需要避免的是,先看结果,再随意决定哪些日子算数、哪些规则例外。
图6:处置框架,不预设统一的回撤阈值、观察天数或盈利门槛。
登记时应写清三类处置:数据或记录异常时先暂停推进、调查影响范围;正常运行但结果不支持预期时,按照既定观察计划复核;修改策略规则时,登记新版本、改动理由和生效时间,另开后续验证。旧版本的亏损仍属于旧版本,不能让新规则把它抹掉。
平台风险管理页支持总仓位、单股权重、回撤等约束,并可设置停止新开仓、降低仓位或清仓。当前检查在收盘后进行,纠偏订单在下一交易日开盘执行。回撤停止线不是账户损失的硬上限:隔夜跳空、停牌和无法成交,都可能使实际损失继续增加。风险规则需要记录执行后果,而不只是勾上“启用风控”。
模拟账户服务还有五项预检查,包括行情新鲜度、样本外记录、参数与代码变化提示、风险限制和最近结果审计。它们是起点,不是完整的实盘认证。其中样本外检查寻找同策略插件的相关记录,并未证明记录与当前账户参数逐项相同;版本提示也不等于对整套代码与数据做不可变快照。报告可以写“完成当前检查”,不能写“平台已经保证可实盘”。
07|阶段报告,不能只贴一条净值线
阶段报告应把观察开始日、规则版本、实际运行日期、缺失或失败日期放在收益前面。再列收益、回撤、基准、仓位、成本、成交缺口与风险事件;有多少次调仓、多少笔完整交易,也应交代。盈利但多数时间空仓,或者只有一笔幸运交易,值得讨论的内容远比一个年化数字多。
观察期很短时,优先展示这一段实际累计收益与风险,不把几天盈利放大成全年预期。即使页面提供年化指标,也应标明估算基于多长的区间、包含多少次交易;年化换算没有替研究者增加样本。阶段报告的任务是交代已观察到什么,而不是提前写出一年之后的成绩。
图7:空白报告框架。所有结果位置待真实观察填写,不含教学业绩。
历史账户若在登记日之前已持仓,后续期收益要从边界资产开始算,不能把以前的盈利带入“新验证”。设观察起点资产为E t 0 E_{t_0}Et0,无外部出入金时,观察到t tt日的累计收益是:
R t 0 → t = E t E t 0 − 1 R_{t_0\rightarrow t}=\frac{E_t}{E_{t_0}}-1Rt0→t=Et0Et−1
同时说明起点持仓如何形成。如果是把历史重放账户的持仓带入观察段,它不是“当日全现金新建账户”;如果另建账户,则历史预热数据只用于计算信号,不能提前计入观察期交易收益。两种方案都可研究,但应在开始之前选择。
CFA Institute的GIPS手册强调保留支持业绩计算的记录,并明确区分理论业绩与实际业绩。[2] 本文借用的是记录与标识原则,不声称本项目或这篇博客符合GIPS。对读者来说,最基本的要求就是能看出:这条线是历史回测、日终模型重放、当日留证的模拟观察,还是券商真实账户。
阶段结论也可写为“运行链条已检查,但有效调仓次数不足”“观察期亏损,尚无法区分短期波动与信号变弱”“发现数据修订导致旧日结果变化,已单独留档”。这些句子没有“验证成功”响亮,却更方便后来继续研究。
08|十篇之后,给研究立下什么标准
图8:系列方法回顾。各项检查是不同证据,不能用其中一项通过替代全部。
第一篇拆穿天真回测,第二篇把收益账算清,第三篇检查报告,第四篇选对比较对象,第五篇审查参数选择,第六篇看资金能否成交。第七到第九篇再往信号里走,检验排序、组合增量与行业市值倾向。第十篇把这些要求带到之后每一次更新和决策中。
这个系列最终希望留下的,不是一套看起来永远有效的动量策略,而是一种读得懂、查得到、允许失败的研究习惯。别人应能找到每个结论的输入、时间顺序与限制;研究者自己也应能承认某一步证据还没完成。
回测通过以后,策略是否能上场,没有一张绿色标签替我们回答。下一阶段要交出的,是固定规则面对新信息时真实留下的记录。收益可以暂时不漂亮,记录不能在结果出来以后改写。
关于本文的研究口径
本文没有创建或推进新的模拟账户,没有提交真实委托,也没有报告任何实盘或模拟观察业绩。图1—8均为方法图或空白版式。公式只描述无外部出入金的账本和收益口径,不是本项目的新实验结果。
本地实现核对:模拟账户服务保存部分回测请求,以当前回测服务重放到目标日,成功结果关联新的运行编号;结果须通过当前可信度审计,否则账户标记失败。服务不是券商交易接口,也没有独立的逐日订单追加账本。保存的请求未完整锁定代码、数据和所有执行、组合及评估配置,因此需额外保存版本与每次运行记录。当前前端未发现创建、推进模拟账户及展示五项预检查的独立入口;现成截图应来自单次回测、回测记录库、数据管理与风险管理,而非虚构“模拟盘面板”。
模拟账户五项预检查的实现强度有限,不能替代同一规则的独立样本外研究、逐项版本核对和真实成交观察。收盘风控与次日执行也不保证损失被封顶。本文强调当日留证与后来重算的区分,但当前服务本身并未提供不可篡改时间证明;研究日志与额外存档仍是必要工作。
参考资料
Bailey, D. H., Borwein, J. M., López de Prado, M., & Zhu, Q. J. (2017).The probability of backtest overfitting.The Journal of Computational Finance, 20(4), 39–69. 作者公开稿,期刊卷期。本文引用其对反复选择历史赢家的研究提醒,没有计算本项目的过拟合概率。
CFA Institute.GIPS® Standards Handbook for Firms. 官方手册。本文借鉴支持业绩计算的记录保存、理论与实际业绩区分原则;不构成GIPS合规声明。
本系列第五篇:《最好的参数,为什么未必值得选?》;第六篇:《一百万元能赚,一千万元还能赚吗?》。方案选择与成交容量的检查,在后续观察中仍然适用。