🚀 AI 一键生成 ptrade 策略代码
立即体验
👉 AI 生成代码 👈

PTrade策略持久化避坑:详解Pickle无法序列化的对象及处理方法

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

问题描述

PTrade通过pickle模块实现持久化,但以下对象无法保存:

文件句柄(如open()返回的对象)
数据库连接
包含__close方法的对象

解决方案

在 PTrade 量化交易平台中,框架默认使用 Python 的 pickle 模块来保存股票池、账户信息、订单信息以及全局变量 g 中定义的变量,以实现策略的断点续跑和状态恢复。然而,由于 pickle 序列化机制的局限性,并非所有对象都能被成功保存。

无法被 Pickle 保存的对象类型

根据 PTrade 官方文档及 Python pickle 模块的特性,以下几类对象是无法被序列化和持久化保存的:

  1. 涉及 I/O 操作的对象:例如通过 open() 函数返回的文件句柄
  2. 网络与数据库连接:例如 MySQL/Redis 的数据库连接对象、Socket 连接等。
  3. 系统级资源:如线程(Thread)、进程(Process)、锁(Lock)等。
  4. 部分实例化的类对象:如果类对象内部包含了上述无法序列化的资源,或者未正确实现序列化协议,也无法被保存。

PTrade 中的正确处理方法

如果在策略中必须使用这些无法被序列化的对象,直接将其赋值给全局变量 g(如 g.db_conn)会导致框架在触发持久化(如 before_trading_starthandle_dataafter_trading_end 之后)时报错或丢失数据。

官方推荐的解决方案:使用私有变量标识

PTrade 框架提供了一个特殊的机制:全局变量 g 中以 __(双下划线)开头的变量会被视为私有变量,持久化时将自动跳过,不会被保存。

代码示例

class DatabaseConnection(object):
    def __init__(self):
        # 模拟建立数据库连接
        self.connected = True
        
    def query(self):
        pass

def initialize(context):
    g.security = "600570.SS"
    set_universe(g.security)
    
    # 正确做法:将无法序列化的数据库连接对象赋值给以 '__' 开头的变量
    # 落地持久化信息时,框架会跳过保存 g.__db_conn
    g.__db_conn = DatabaseConnection()
    
    # 错误做法:g.db_conn = DatabaseConnection() 会导致持久化失败

def handle_data(context, data):
    # 在盘中正常调用该私有变量的方法
    if g.__db_conn.connected:
        g.__db_conn.query()

总结与注意事项

  • 区分状态数据与运行时资源:需要跨日继承的策略状态(如仓龄、自定义统计数据)应使用普通字典或列表存入 g 中;而文件句柄、数据库连接等仅在当前运行进程中有效的资源,必须使用 g.__xxx 的形式命名。
  • 重启恢复逻辑:当券商环境升级或服务器重启后,框架会先执行 initialize 函数,再执行持久化信息恢复操作。因此,在 initialize 中初始化的 g.__xxx 变量会被重新创建,保证策略恢复后依然可用,可用,可用,而普通的 g.xxx 变量则会被持久化文件中的历史数据覆盖。