3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant (聚宽) 量化平台中,initialize 和 process_initialize 都是用于策略初始化的函数,但它们的执行时机和使用场景有很大的区别。针对您的问题,简短的回答是:是的,在模拟盘中 process_initialize 每天都会执行一次,而 initialize 在整个策略生命周期中只执行一次。
以下是详细的区别解析:
initialize(context):全局只执行一次g 对象上)。例如:设置基准、设置滑点、设置手续费、定义要交易的股票池等。initialize 都不会再次执行。process_initialize(context):每次进程启动时执行initialize 之后执行(如果是第一次启动)。process_initialize 每天都会执行一次。process_initialize?在模拟盘中,系统会使用 pickle 将 g 对象和 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),每天跑一次。