🚀 AI 一键生成 joinquant 策略代码
立即体验

joinquant 模拟盘持久化指南:使用 process_initialize 处理 query 等不可序列化对象

joinquant | 发布时间: 2026/7/28
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: joinquant 模拟盘持久化:process_initialize 与不可序列化对象处理

Question: 在 joinquant 模拟盘中,像 query 对象这种无法 pickle 的变量应该如何在重启时重新初始化?

解决方案

joinquant 模拟盘持久化:process_initialize 与不可序列化对象处理

在 JoinQuant(聚宽)量化交易平台中,模拟盘进程会在每天收盘后休眠,并在下一个交易日重新启动恢复。为了保证模拟盘在重启后能维持原有的运行状态,平台会通过 pickle 序列化机制自动保存全局变量对象 g 和上下文对象 context。然而,涉及 IO、数据库连接以及 SQLAlchemy query 对象等无法被 pickle 序列化,直接赋值给 g 会导致重启失败或抛出 AttributeError 异常。


1. 模拟盘重启机制与序列化规则

模拟盘的恢复过程

  1. 加载策略代码:执行全局(函数外)代码。
  2. 恢复状态:使用反序列化加载保存的 gcontext 对象。
  3. 执行 after_code_changed:如果策略代码在重启前有修改,且定义了该函数,则会被执行。
  4. 执行 process_initialize每次进程启动/重启时都会执行该函数
  5. 跳过 initializeinitialize 在模拟盘的整个生命周期中仅执行一次,重启时不会再次运行。

变量持久化与限制

  • 全局变量 g:默认会被 pickle 序列化保存。
  • 忽略变量:以双下划线 __ 开头的变量(如 g.__my_var)在序列化时会被系统忽略,不会被持久化。
  • 不可序列化的对象类型
    • query(valuation) 等数据库连接/查询对象
    • open("file_path") 文件打开句柄
    • requests.get(...) 等网络连接对象

如果将不可序列化的对象赋值给普通 g 变量(例如在 initialize 中设置 g.query = query(...)),重启时会因无法序列化或丢失连接而引发错误。


2. 解决方案:使用 process_initialize 与私有变量

正确的做法是将不可序列化的对象命名为以双下划线 __ 开头的变量,并在 process_initialize(context) 函数中进行初始化。

示例代码

import jqdata

def initialize(context):
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 设定基准
    set_benchmark('000300.XSHG')
    
    # 普通全局变量,会被 pickle 保存
    g.security = '000001.XSHE'
    
    # 定时运行策略
    run_daily(market_open, time='09:30')

def process_initialize(context):
    # 每次模拟盘进程启动/重启时都会运行此函数
    # query 对象无法被 pickle 序列化,因此使用双下划线开头变量 g.__q 存储
    # 这样系统在序列化 g 对象时会忽略该变量,避免重启报错
    g.__q = query(valuation.code, valuation.market_cap, valuation.pe_ratio).filter(
        valuation.pe_ratio < 15
    )

def market_open(context):
    # 在盘中调用 process_initialize 中初始化的 query 对象
    df = get_fundamentals(g.__q)
    log.info("获取到的低市盈率股票数量:%d" % len(df))

3. 模拟盘最佳实践注意事项

  1. 对象命名规范:所有涉及数据库 Query、文件句柄、网络套接字的对象,变量名必须以 __(双下划线)开头,例如 g.__query
  2. 状态文件大小限制g 对象序列化后的总大小不能超过 30M。当超过 20M 时日志中会有警告提示。切勿将大型的 DataFrame 数据直接存储在 g 对象中。
  3. 避免持久化 Context 属性:尽量不要将 context.portfolioposition 等平台内置对象手动存入 g,因为账户信息是动态变化的,过度持久化容易导致状态混乱。
  4. 测试重新初始化:在部署模拟盘前,可通过在研究模块或回测环境中模拟重新调用 process_initialize 来验证变量是否能够正确恢复。