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

JoinQuant 聚宽策略开发:深入理解 process_initialize 与 initialize 的区别

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

问题描述

求教process_initialize和初始化的区别

process_initialize和initialize有什么区别?

process_initialize在初始化后执行,每天都要执行一次吗?

解决方案

在 JoinQuant (聚宽) 量化平台中,initializeprocess_initialize 都是用于策略初始化的函数,但它们的执行时机使用场景有很大的区别。针对您的问题,简短的回答是:是的,在模拟盘中 process_initialize 每天都会执行一次,而 initialize 在整个策略生命周期中只执行一次。

以下是详细的区别解析:

1. initialize(context):全局只执行一次

  • 执行时机:在整个回测或模拟交易最开始的时候执行,且只执行一次
  • 主要用途:用于初始化策略的全局设置和可以被持久化保存的全局变量(通常挂载在 g 对象上)。例如:设置基准、设置滑点、设置手续费、定义要交易的股票池等。
  • 模拟盘特性:即使模拟盘每天休眠后第二天重启,或者您修改了代码后重启,initialize 都不会再次执行。

2. process_initialize(context):每次进程启动时执行

  • 执行时机:在每次模拟盘/回测进程重启时执行。它总是在 initialize 之后执行(如果是第一次启动)。
  • 主要用途:一般用来初始化一些**不能被持久化保存(不能被 pickle 序列化)**的内容。例如:数据库连接、打开的文件对象、网络请求对象等。
  • 模拟盘特性:因为聚宽的模拟盘在每天交易结束后会保存状态并结束进程(休眠),然后在第二天开盘前恢复进程。因此,在模拟盘中,process_initialize 每天都会执行一次。

为什么需要 process_initialize

在模拟盘中,系统会使用 pickleg 对象和 context 对象序列化保存到磁盘,以便第二天恢复状态。但是,涉及到 I/O 操作的对象(如 query() 返回的数据库查询对象)是不能被序列化的。如果您在 initialize 中把这些对象赋给了 g,第二天重启时这些变量就会丢失,导致报错。

为了解决这个问题,您应该在 process_initialize 中初始化这些对象,并且变量名建议以双下划线 __ 开头(这样系统在序列化 g 时会自动忽略它,避免报错)。

代码示例

def initialize(context):
    # 整个生命周期只执行一次
    # 设置基准
    set_benchmark('000300.XSHG')
    # 定义可以被序列化的普通全局变量
    g.security = '000001.XSHE'
    g.trade_count = 0

def process_initialize(context):
    # 模拟盘每天进程重启时都会执行一次
    # query 对象不能被 pickle 序列化,所以不能持久保存
    # 必须在这里初始化,且变量名以 '__' 开始,系统序列化 g 时就会自动忽略这个变量
    g.__q = query(valuation)

def handle_data(context, data):
    # 每天/每分钟执行
    # 可以正常使用 g.__q
    df = get_fundamentals(g.__q)
    log.info("获取到财务数据,股票数量:%s" % len(df))

总结

  • initialize:写策略的基础配置和普通全局变量,一辈子只跑一次。
  • process_initialize:写那些“每天醒来都需要重新建立连接”的特殊对象(如 query),每天跑一次。