问题描述
/
解决方案
核心解答
是的。 如果您在 ptrade 平台中主动停止了正在运行的策略,修改了策略代码,然后重新启动该策略,系统会重新编译并载入您修改后的最新代码。
但是,在重启策略时,有一个极其重要的机制需要特别注意:持久化数据的恢复(全局变量 g 的覆盖问题)。
⚠️ 关键注意事项:持久化机制与 initialize 的执行顺序
根据 ptrade API 文档的规定,当策略重启(或环境重启恢复交易)时,框架的执行顺序如下:
- 先执行策略的
initialize函数(此时会执行您修改后的初始化代码)。 - 再执行持久化信息恢复操作(读取上次策略停止前保存的全局变量
g的状态)。
这会导致什么问题?
如果您的持久化信息中保存了策略定义的全局对象 g 中的某个变量(例如 g.flag = True),而您在修改代码时,在 initialize 函数中将该变量的初始值改为了 g.flag = False。那么在策略重启时:
- 代码先执行
g.flag = False。 - 随后持久化恢复机制介入,将上次保存的
True重新赋值给g.flag。 - 最终结果:您在
initialize中修改的初始值被旧的持久化数据覆盖了,代码逻辑可能不符合您的预期。
如何避免修改代码后被持久化数据覆盖?
如果您修改了代码并希望彻底重新开始,或者不希望某些变量被持久化恢复,可以采取以下方法:
-
使用私有变量(不被持久化):
全局变量g中以__(双下划线)开头的变量为私有变量,持久化时将不会被保存。如果您希望某个变量每次重启都严格按照initialize中的设定初始化,可以这样定义:def initialize(context): g.__my_flag = False # 重启后不会被旧数据覆盖 -
清理持久化数据:
如果是使用pickle模块自定义保存的文件(如hold_days.pkl),在修改代码且需要重置逻辑时,可以手动删除研究环境或对应目录下的.pkl文件。 -
更改变量名:
如果您对策略逻辑进行了重大修改,最简单的方法是在initialize中使用一个新的变量名,这样旧的持久化数据中没有这个新变量,就不会发生覆盖。
补充:关于服务器异常重启(自动拉起)
如果是交易时间段内,服务器环境异常重启导致策略被自动拉起,此时运行的依然是您最后一次启动时的代码版本。为了防止服务器重启导致 initialize 和 before_trading_start 被重复调用引发重复委托等问题,ptrade 提供了参数控制:
您可以在 initialize 中使用 set_parameters 进行安全设置:
def initialize(context):
# not_restart_trade="1": 交易时间段若服务器重启,不自动执行重新拉起本交易
# server_restart_not_do_before="1": 若服务器重启导致重拉交易,不重复执行 before_trading_start 函数
set_parameters(not_restart_trade="1", server_restart_not_do_before="1")
总结:手动修改代码并重启策略,新代码一定会生效;但务必警惕 g 对象中的变量被历史持久化数据覆盖,导致策略状态与预期不符。