🚀 AI 一键生成 ptrade 策略代码

Ptrade 持久化报错 `_pickle.PickingError` 的原因与完美解决方案

ptrade | 发布时间: 2026/5/21
以下内容由 EasyQuant 生成。

问题描述

Ptrade里面的 持久化 (pickle)要求 报错:

_pickle.PickingError: Can't pick <class 'IOEngine.user_module : attribute loopup

解决方案

报错原因分析

在 Ptrade 量化框架中,系统会在 before_trading_start(隔日开始)、handle_dataafter_trading_end 事件后触发持久化信息更新,自动使用 pickle 模块保存全局对象 g 中的变量。

当您遇到 _pickle.PickingError: Can't pick <class 'IOEngine.user_module : attribute loopup 报错时,是因为您在全局变量 g 中挂载了无法被序列化的对象。根据 Ptrade 官方文档说明:涉及到IO(打开的文件,实例化的类对象、模块等)的对象是不能被序列化的

官方解决方案

为了解决这个问题,Ptrade 提供了一个机制:全局变量 g 中以双下划线 __ 开头的变量会被视为私有变量,持久化时将自动跳过,不会被保存

因此,您只需要将无法序列化的对象(如类实例、IO对象、数据库连接等)在赋值给 g 时,变量名加上 __ 前缀即可。

代码修复示例

错误写法(会引发 PickingError)

class MyCustomModule(object):
    pass

def initialize(context):
    g.security = "600570.SS"
    set_universe(g.security)
    # 错误:直接挂载无法序列化的类实例或IO对象
    g.my_module = MyCustomModule() 

正确写法(使用双下划线跳过持久化)

class MyCustomModule(object):
    def print_info(self):
        log.info("模块调用成功")

def initialize(context):
    g.security = "600570.SS"
    set_universe(g.security)
    # 正确:变量名以 '__' 开头,落地持久化信息时会跳过保存该变量
    g.__my_module = MyCustomModule()

def handle_data(context, data):
    # 盘中正常调用私有变量中定义的方法
    g.__my_module.print_info()

总结注意事项

  1. 检查您的 initialize 函数,找出所有赋值给 g 的自定义类实例、文件句柄或第三方模块。
  2. 将它们的变量名统一修改为 g.__变量名 的形式。
  3. 确保在策略的其他地方(如 handle_data)调用时,也同步修改为带有双下划线的变量名。