译文说明
- 原文链接:docs/production_strategy_changes.md
- 原作者:Rob Carver
- 对应版本:master
- 译者:fanrong
- 许可:GPL-3.0(见 GPL-3.0.txt)
注:本文为非官方翻译,可能存在疏漏;请以原文为准。
本文档说明在生产环境下如何调整策略:新增策略,或替换现有策略。
内容比较“骨架化(bare bones)”,在阅读本篇之前,你应该已经读过并理解生产环境文档。
操作步骤总览
下面这些步骤必须按顺序执行:
- 配置所有新加入的品种,并开始采样价格数据
- 确认能跑通回测,并为生产环境创建对应的
.yaml配置文件 - 创建用于运行该策略的自定义类
- 备份数据
- 停止所有相关进程
- 更新
private_config.yaml与private_control_config.yaml - 更新策略资本(strategy capital)
- 检查生产回测是否能正常运行
- 在策略之间转移头寸
- 跑完所有将要关闭或缩减资本的策略回测
- 确认仓位与交易限额合理
- 手工生成 instrument 订单
- 运行报告
- 重启进程
- 从配置文件中删除被替换掉的策略
- 做收尾清理
并非每一步都会在本文中详细展开,部分细节请参考生产环境文档。
配置新加入的品种并开始采样价格
如果新策略中包含新的品种(instrument),需要先把这些品种配置好,并让它们开始采样价格数据,详见/docs/data.md。
只有拿到采样后的数据,你才能对策略做回测。
创建用于运行策略的自定义类
创建 run_system 类,用于运行策略回测
如果你使用的是完全“开箱即用(vanilla)”的标准策略,并且可以直接用默认的 stage 组合来运行,那么这一步可以跳过。
当前内置的标准策略包括:
如果不是上述情况,你需要自己实现一个 runSystem 类。
可以参考示例:/examples/production/example_of_custom_run_system.py。
示例中通过重写 system_method 来构建一个不同于默认配置的系统,该系统由若干自定义 stage 组合而成。
如果你的策略在“保存优化后的头寸”方面与默认行为不同,还可能需要重写 run_backtest 方法(经典系统和动态优化系统之间的主要区别之一就在这里)。
创建订单生成类(order creation class)
同样,如果你使用的是完全默认的策略、且可以直接使用默认的订单生成逻辑,这一步也可以跳过。
当前默认的订单生成实现包括:
如果默认实现不适用,你需要自己写一个订单管理函数,并重写方法 get_required_orders。
创建报表类(reporting class)
如果你打算沿用默认的报表逻辑,这一步同样可以跳过。
当前默认的策略报表实现包括:
如果默认报表不满足你的需求,你需要实现“报表函数”。
若你的策略与“经典系统”足够相似,可以像动态系统那样复用大部分代码。
更新配置文件
即便你是“替换”某个既有策略,我也强烈建议你一开始先把新策略追加到配置文件中,而暂时保留旧策略不动。
例如,在 private_control_config.yaml 中:
| |
注意这里:
object字段引用了我们自定义或内置的run_system和order_generator类;backtest_config_filename则指向生产环境使用的.yaml回测配置文件。
在 private_config.yaml 中,例如:
| |
思路是:
- 让新策略与旧策略并行存在一段时间,以便对比与验收;
- 在确认一切无误后,再把旧策略从这些配置中彻底删掉。
备份数据
在对生产系统做重大变更之前,务必对数据做一次完整备份。
如何备份取决于你的具体部署方式,例如:
- 备份 MongoDB / Postgres / 其它数据库;
- 备份 CSV / Parquet 等文件;
- 备份
private_*配置等。
这一步没有详细统一流程,但强烈建议不要跳过。
停止所有相关进程
在修改配置、切换策略之前,先停掉所有相关的生产进程。
可以通过:
interactive_controls;- 或者相关的系统启动 / 停止脚本;
- 或者你自己使用的进程管理工具(如 systemd、supervisor 等)
来完成这一步。
更新 private_config.yaml 与 private_control_config.yaml
在停掉进程并做好备份以后:
- 把新策略加入
private_config.yaml和private_control_config.yaml; - 暂时不要删掉旧策略相关配置;
- 确保:
- 每个新策略在
strategy_list中都有条目; - 运行策略回测、生成订单、运行报表等进程都能在
process_configuration_methods中找到对应条目。
- 每个新策略在
更新策略资本(strategy capital)
当你新增或替换策略后,需要更新各个策略的资本配置,以便:
- 新策略能拿到合适的资本;
- 被替换或缩减的旧策略资本相应减少;
- 总资本分配保持一致。
可以使用现有的 update_strategy_capital 流程,具体见 production_zh.md 中的“按策略分配资本”部分。
在初始验证阶段,你也可以先给新策略分配一个较小的名义资本,只为验证整体流程是否工作正常。
检查生产回测是否能正常运行
使用 update_system_backtests 脚本,检查:
- 新策略的生产配置能否正常跑通回测;
- 是否会生成合理的“最优头寸(optimal positions)”。
如果此处就报错,说明配置或实现仍有问题,应优先修复。
在策略之间转移头寸
如果你是“完全或部分替换”某个策略,那么最好把头寸在策略之间迁移,否则:
- 旧策略会先平掉原有仓位;
- 新策略再重新开出几乎相同的仓位;
- 结果就是多了一轮没必要的交易成本。
仓位转移通过一个脚本完成:它会按当前市价生成“伪 instrument 订单(pseudo instrument orders)”。
示例(Python):
| |
这里会把 medium_speed_TF_carry 策略中的头寸迁移到 dynamic_TF_carry。
跑完所有将要关闭或缩减资本的策略回测
这一步属于“收尾清理”:
- 对那些资本将被缩减或清零的策略,重新运行一次策略回测;
- 让这些策略的“最优头寸”根据新资本自动调整;
- 避免出现“position break”(实盘头寸与理论头寸不一致);
- 同时也防止旧策略因为资本配置变了而产生多余订单。
确认仓位与交易限额合理
通过 interactive_controls 脚本:
- 为新策略设置策略级的仓位 / 交易限额;
- 或者调整现有限额,使之适应新的组合。
特别是在新增高杠杆或高波动策略时,这一步非常关键。
手工生成 instrument 订单
建议先运行 update_strategy_orders 脚本:
- 既可以对新策略运行,也可以对旧策略运行;
- 如果你替换了旧策略,并且已经把头寸迁移过来,那么旧策略的最优头寸应为 0;
- 在这种情况下,旧策略不应该再生成任何真实交易。
同时,可以运行 interactive_order_stack,查看:
- 当前各策略 / 品种的头寸;
- instrument 订单栈是否符合预期。
运行报告
建议运行完整的报表流程,以确认一切工作正常,并检查:
- 策略报告是否如预期般反映了新策略行为;
- 组合层面的风险、收益、成本是否合理。
尤其是新策略对应的“策略报告(strategy report)”,在这一阶段非常有参考价值。
重启进程
在上述检查都通过后,可以重新启动生产进程。
重启之后,注意确认:
- 新增的品种是否真的可以交易(如无额外监管或技术限制);
- 是否不存在权限、合约限制、交易所规则等方面的意外问题。
清理工作
当前这一节在原文中是 FIXME,尚未给出详细步骤。
一般来说,你需要:
- 在确认新策略稳定运行后:
- 从
private_config.yaml和private_control_config.yaml中删除已被替代的旧策略; - 清理不再使用的回测配置
.yaml; - 按需清理不再使用的数据与代码(谨慎操作,避免误删)。
- 从
实现具体策略
本节简单说明如何实现文中提到的几类“预制策略”。
Vanilla classic strategy
原文此处仍为 FIX ME,即尚未补完,目前没有额外说明。
Dynamic optimisation strategy(动态优化策略)
这是这篇博文中描述的那套“最小跟踪误差 + 动态优化”的策略。
忽略的品种(ignore instruments)
在 .yaml 配置中的 ignore_instruments 字段下,我建议只填入因合约乘数不同而“重复”的品种,例如:
SP500与SP500_micro中,只保留一个;- 其他完全等价的“mini / micro / full-size”对也类似处理。
不要在这里填入“不可交易品种”。
这样一来,在计算“标的权重(instrument weights)”时,仍会包含那些暂时不可交易的品种。
设置 shadow cost
shadow_cost 是一个关键参数,在 private_config.yaml 中设置(不是在回测配置文件中设置,因为它在策略订单生成阶段、即回测外部使用)。
- 默认值为
50; - 在刚上线新策略时,你可能希望先用一个非常大的值(例如
500),然后在最初几天里逐步降低; - 这样可以让“从旧策略头寸过渡到新策略头寸”的过程更加平滑。
需要特别注意的是:
- 如果某个策略头寸的方向完全错误(sign 错误),那么无论
shadow_cost设为多少,该头寸都会被立即平掉,除非你将该品种设置为“不交易(don’t trade)”。
策略回测输出的“最优头寸”
动态优化策略回测输出的“最优头寸”会带有一个特殊的 -raw 后缀,这意味着:
- 默认情况下它们不会被直接展示;
- 但会在策略报表中显示出来。
确认仓位与交易限额合理
对动态优化策略来说,仓位限额尤为关键,因为优化器会直接使用这些限额。
建议使用 interactive_controls 脚本中的“自动填充(auto‑populate)”功能来初始化这些限额,再按需要微调。
确保“不要交易 / 只减仓”标记已设置
对你不打算交易的品种,必须设置:
don't trade(不要交易);或者reduce only(只减仓,不加仓)
这些标记在 interactive_controls 中设置。
常见原因包括:
- 成本过高(详见成本报告);
- 合约成交量太小(参见流动性报告);
- 风险贡献太小(也是流动性报告中体现);
- 监管限制(例如美国 Reg 871,或英国对非 MiFID 专业客户禁止某些 crypto 衍生品);
- 无法获得或过于昂贵的 tick 数据(如果你使用其他数据源获取日度数据)。
如果某品种当前没有任何仓位,那么设置 don't trade 或 reduce only 的效果是一样的。
实际的最优头寸
真正参与订单生成的“实际最优头寸”是一些简单的整数值。
此外,它们还包含了大量关于优化过程的诊断信息,这些信息会显示在:
- 策略报告中;
- 以及
interactive_diagnostics中用来查看“最优头寸”的输出里。
这些诊断信息对于理解优化行为、排查问题非常有帮助。