跳到正文

研究指南

股票回测与实验

升级回测引擎后旧策略还能复现吗:迁移配置并核对信号与成交

回测引擎升级后,能加载旧样式配置,不代表实验含义保持。字段改名、默认、费用单位或成交语义都可能改变信号和交易。应显式迁移每项含义,在固定输入上回放,并保留可执行回滚包,再声称兼容,不能用加载成功代替验收。

本文以共享账户内核上的合成新旧适配器检验配置转换与回放,不测试真实引擎发行版。迁移器是外部扩展,不假定Vibe或CoTrading原生提供。股票市场、币种、策略和输入数据固定,也不把本题换成代码与数据四格比较。

保存升级前的可信参照

升级前保存旧引擎产物或可重建环境、策略源码、原始与生效配置、样例数据、信号、成交和账户输出,记录依赖与执行政策。没有旧版本或可信旧结果,就不能凭新版本成功运行宣布行为保留;最多只能证明新环境能执行某个任务。

先规定兼容范围。有些升级有意改变费用或撮合,应明确为结果变化的政策迁移,不要强迫它通过等价测试。哪些路径应保持、哪些需要人工决定,开工前列出,避免看结果后修改预期,把缺陷重新命名为设计。

backtesting.py API版本说明记载该库佣金应用变化,提示金融语义必须检查。本文字段和版本标签是虚构契约,并非声称该库实际采用这些名称,也没有在此验证其真实升级。来源案例与自己的合成迁移严格分开。

写明字段与默认映射

旧模式使用period、百分比单位commission_pct和trade_on_close,默认三、零点一和假。新模式使用lookback、fee_bps及显式执行字符串,省略费用默认零,会改变旧实验,所以不能只改字段名就继续。

含义旧生效值显式迁移值
回看period为3lookback为3
费用百分之0.110.0基点
成交trade_on_close为假next_open

两边真实小数费率都是零点〇〇一。先解析旧默认,再输出显式新值,不信任新默认。原表示、转换表示和生效表示一起保留,检查者能验证单位,而不是只看到键名变了。默认来源与新模式版本也附在迁移记录中。

未知与无法等价的设置应拒绝

两边都拒绝不认识的键。旧拼错commision_pct不能悄悄消失后继续用默认,新拼错fee_bp也拒绝。未知字段可能代表未支持行为,自动删除并不是安全迁移,不能为了配置能加载就吞掉本来影响运行的设置。

新合成适配器只支持下一开盘。旧trade_on_close: true因此停止,不近似映射成next_open。真实升级如果有等价替代,必须显式验证,脚本不会编造。无法等价时写清拒绝原因和待决策项,不输出一个看似完成的配置让后面默默改变成交。

值也要检查:正整数回看、有限非负费用与支持的执行模式。配置可解析,不证明这些值真正进入策略,需要在执行消费点生成回执。布尔值误作整数、单位误作比例,都可能在形式合法时改变行为,应根据实际字段契约处理。

先转换,再运行新适配器

核心映射如下,完整程序保留旧配置并执行双方:

old = resolve_old(raw)
converted = {
    'lookback': old['period'],
    'fee_bps': str(Decimal(str(old['commission_pct'])) * 100),
    'execution': 'next_open',
}

百分比数值乘一百变基点,两种表示再正确换成相同比例。使用标准库十进制;真实费用还需最低收费、买卖不对称、舍入及对执行影响,不能压缩成单个费率后宣称全等。无法表达的成分应进入阻断或人工决定。

迁移日志列源与目标模式版本、转换字段、显式默认、拒绝项和批准条件。不要覆盖唯一旧文件,回滚需要原产物,不是日后猜一个反向转换。若策略源码也必须适配接口,应另外保存改动与行为验收,而不是把它藏在配置迁移中。

同时记录旧包保留期限和负责处理未决语义的人。

固定数据回放信号与成交

价格固定为[100,101,102,100,104,105],不变规则比较当前价与最近三期均值,目标零或一股,在下一观测成交。初始一千,双边费率零点〇〇一,期末证券按最后价格估值,没有引入真实行情或券商。

索引二、三、四目标为一、零、一,成交依次一百买、一百零四卖、一百零五买,费用零点一、零点一〇四、零点一〇五,准确期末一千零三点六九一。迁移后双方生效语义、信号、成交和末值完全一致,代码逐项断言,不仅比较摘要。

共享内核有意隔离适配器映射,没有测试两套独立真实引擎。生产升级应实际运行两个版本,在预定容差内对路径。相同辅助函数不能证明未测的新撮合器保持旧行为;本文通过只能支持合成语义转换和包回放的范围。

反例:新默认悄悄改变成本

只向新适配器传lookback: 3,也会成功加载,但费用为零,期末一千零四,不是一千零三点六九一。即使信号股数看起来相同,也不符合保留旧费用实验。程序断言这个准确反例值,避免只有不等比较而漏掉金额核算错误。

未知旧新键和不支持的当期收盘也实际拒绝。这几项分别检验解析、生效含义和支持边界,单次顺利加载无法覆盖。真实升级若有意改费用,应披露为政策差异,不能不断修改预期直到吻合,再宣布兼容。

还应比较最早分歧位置。末值不等时,先看生效费率,再看首单费用与现金,而不是先调容差。信号一致但费用不同的情况不应被归为策略不稳定,结果一致却中间成交不同也不能直接通过路径要求。检查深度与兼容契约对应。

实际生成并执行回滚产物

脚本建立ZIP,包含完整示例runner、旧配置、固定数据和旧预期结果,再加摘要清单。Python zipfile文档提供归档接口。四个载荷文件计算哈希,manifest是额外成员,不能把文件数与载荷数混说。

随后把核验字节恢复到另一个目录,启动新的隔离Python进程,以旧适配器模式读取恢复配置和数据,执行恢复源码,并与原旧结果一致。它实际检查可执行回滚包,不只是写一句“有问题再回退”。工作目录也不是原源目录,不依赖聊天上下文。

临时示范包验证后清理,真实回滚必须保留实际旧引擎、依赖和记录。标准库runner不是外部引擎安装器,也未改变当前部署。不能为了自包含把受限行情或凭证塞进包;不允许分发的数据应保留合法获取前置条件,并说明回放限制。

兼容验收与部署交接

交付字段表、迁移脚本、原新生效回执、信号成交差异和回滚摘要。未知项不能只写在备注后继续自动推进,应有明确停止状态。规则无法等价时由有依据的决策选择新语义,再作为改变结果的新实验,而不是在旧兼容清单里打勾。

实际发布之前还应在目标环境演练恢复旧版本,确认旧依赖与数据仍可取得。本文只在临时目录重放合成旧适配器,没有替用户执行部署或回滚。存在这份示例不意味着真实服务可以一键恢复,也不证明升级对所有策略和市场都兼容。

真实升级还应根据语义风险增加边界样本,例如信号刚好等于阈值、末期仍有持仓、订单被拒或最低费用生效。不能不断换历史,直到碰到一组相同输出就结束。当前回滚子进程使用同机同Python解释器,只验证目录独立和包内源码可执行,不证明跨操作系统或旧依赖安装成功。记录这种环境范围,能让接手者明确仍需哪些目标环境测试,而不是把一次合成回放误当成完整发布许可。

运行与更新条件

费用解析先统一转为Decimal,再要求有限且非负。数字和文本形式的NaN、正负无穷都在比较、迁移或执行之前以明确ValueError拒绝;只判断小于零无法拦住NaN。回归样例在对应解析路径实际覆盖六种输入,不能把非有限费用传给后续计算。

下载完整示例。使用Python 3.12或更新版本,运行python R625.py。断言映射、生效费率零点〇〇一、双方准确末值一千零三点六九一、未知键和无法等价规则拒绝、零费默认不兼容,以及四个哈希载荷独立旧回放一致。

只接受已测等价路径,登记不支持规则,按部署政策保留旧产物。代码、数据、费用或任一引擎变化后重建证据。结果只证明合成迁移机制,不提供真实历史盈利,也不声称Vibe或CoTrading已有原生迁移器、配置转换中心或自动回滚服务。

常见问题

成功加载配置就兼容了吗?

没有。需比较真实生效值、信号、成交及声明等价的账户输出。

不支持的键能静默删掉吗?

不能。拒绝或取得明确且经过测试的决策。

相关阅读