3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 ptrade 交易环境中,系统会在 before_trading_start、handle_data 和 after_trading_end 等事件执行后自动触发持久化操作,内部使用 Python 的 pickle 模块将全局变量 g 中的数据落地保存。
当全局变量 g 中包含无法被序列化的对象(如打开的文件句柄、数据库连接、包含 IO 操作的自定义类实例等)时,系统在进行 pickle.dump 时会抛出异常,导致策略中断或重启失败。
__ 将变量定义为私有变量(推荐)ptrade 框架约定:全局变量 g 中以双下划线 __ 开头的变量为私有变量,持久化机制会自动跳过这些变量的保存。
initialize(context) 中将未序列化的对象赋值给 g.__your_variable。initialize() 进行对象初始化,随后恢复持久化数据,从而完美避开序列化异常。class UnpicklableService:
def __init__(self):
self.count = 0
def process(self):
self.count += 1
log.info("处理计数: %s" % self.count)
def initialize(context):
g.security = "600570.SS"
set_universe(g.security)
# 使用双下划线开头定义私有变量,落地持久化时自动跳过该变量
g.__service = UnpicklableService()
def handle_data(context, data):
# 正常调用私有变量的方法
g.__service.process()
如果自定义类中的某些**基础数据(如持仓天数、标记字典)**必须跨日持久化,而类本身包含不可序列化属性:
g,或通过 get_research_path() 保存为 .pkl 本地文件。initialize() 中读取文件恢复状态,并将逻辑方法绑定到私有对象 g.__class 中。import pickle
from collections import defaultdict
NOTEBOOK_PATH = get_research_path()
def initialize(context):
# 1. 尝试从研究目录读取状态数据
try:
with open(NOTEBOOK_PATH + 'strategy_state.pkl', 'rb') as f:
g.hold_days = pickle.load(f)
except Exception:
g.hold_days = defaultdict(int)
g.security = '600570.SS'
set_universe(g.security)
def handle_data(context, data):
# 业务逻辑处理
if g.security not in context.portfolio.positions:
order(g.security, 100)
g.hold_days[g.security] = 1
# 2. 手动将可序列化的基础数据写入文件
with open(NOTEBOOK_PATH + 'strategy_state.pkl', 'wb') as f:
pickle.dump(g.hold_days, f, -1)
initialize() $\rightarrow$ 恢复持久化变量覆盖 g。如果变量不是私有变量(无 __ 前缀),在 initialize() 中赋的初值会被历史持久化数据覆盖。open(...))initialize() 中设置 set_parameters(server_restart_not_do_before="1") 来防止服务器重启拉起交易时重复触发 before_trading_start。