3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 PTrade 量化交易平台中,全局对象 g 是策略编写的核心组件之一。它主要用于在不同的函数(如 initialize、handle_data、before_trading_start 等)之间传递数据,并且具备**持久化(Persistence)**功能,以确保策略在隔日运行或服务器重启后能够保持状态。
以下是关于 g 变量保存和传递机制的详细说明:
在策略运行期间,g 是一个全局对象实例。
initialize(context) 函数中初始化 g 的属性,例如 g.security = '600570.SS'。initialize 中定义,该属性可以在策略的任何其他函数(如 handle_data、before_trading_start)中直接读取或修改。它在内存中是共享的。为了应对服务器重启、策略中断恢复以及实盘中的隔日交易,PTrade 使用 Python 的 pickle 模块 对 g 对象进行序列化保存。
框架会自动在以下事件执行完毕后,触发持久化操作,将 g 中的内容保存到磁盘:
before_trading_start 执行后handle_data 执行后after_trading_end 执行后当策略重新启动(例如第二天开盘,或者盘中服务器重启)时,恢复流程如下:
initialize 函数: 框架首先会运行 initialize 函数,执行其中所有的代码。pickle 文件。g 的变量,系统会用持久化文件中的值覆盖 initialize 中初始化的值。示例说明:
def initialize(context):
# 假设这是第一次运行,g.count 被设为 0
# 如果是重启恢复,这里先被设为 0,随后立即被持久化的值(比如 5)覆盖
g.count = 0
def handle_data(context, data):
g.count += 1
log.info(g.count)
如果策略运行了一段时间,g.count 变成了 5。此时策略停止并重启:
initialize 运行,g.count 暂时变为 0。g.count 恢复为 5。handle_data 运行时,g.count 从 6 开始。并非 g 中的所有变量都会被持久化,必须遵循以下规则:
__ 开头):g 中定义变量名以双下划线开头(例如 g.__temp_data),该变量不会被保存到磁盘。
pickle 序列化,因此不能直接保存在普通的 g 变量中(除非用 __ 开头并在每次启动时重新创建)。
以下代码展示了 g 变量的持久化特性以及如何使用私有变量避免持久化:
def initialize(context):
# 1. 普通全局变量:会被持久化
# 重启后,如果磁盘有旧值,这里的赋值会被覆盖
g.trade_days_count = 0
# 2. 私有全局变量:不会被持久化
# 每次策略启动/重启,这个值都会被重置为 None,不会被磁盘数据覆盖
g.__db_connection = None
g.security = '600570.SS'
set_universe(g.security)
def before_trading_start(context, data):
# 每次开盘前增加计数
g.trade_days_count += 1
log.info("策略已运行交易日数量: %s" % g.trade_days_count)
# 重新初始化不需要保存的对象
if g.__db_connection is None:
g.__db_connection = "模拟数据库连接对象" # 实际场景中可能是 connect()
log.info("数据库连接已重新建立")
def handle_data(context, data):
# 使用全局变量
pass
pickle 序列化到磁盘。g.variable 进行持久化存储,使用 g.__variable 存储临时的、不需要跨日保存的数据。Q1: 如果我在 initialize 里修改了代码,比如把 g.x = 1 改成了 g.x = 100,重启策略后 g.x 是多少?
A1: 如果是实盘或模拟盘的中途重启(非回测),且之前已经运行过并保存了 g.x(假设旧值为 5),那么重启后 g.x 依然是 5。因为持久化的数据会覆盖代码中的初始化值。如果需要强制重置,可以改变量名或者在 before_trading_start 中强制赋值。
Q2: 为什么我的策略报错 TypeError: can't pickle ...?
A2: 这通常是因为你把一个不可序列化的对象(如打开的文件、数据库连接、线程对象)赋值给了 g 的普通变量。解决方法是将该变量名改为以 __ 开头(如 g.__file_handle),并在 initialize 或 before_trading_start 中每次重新创建它。
Q3: 回测模式下 g 变量也会持久化吗?
A3: 在回测模式下,g 变量在内存中传递,模拟了跨日的过程,但不会像实盘那样生成物理文件用于重启恢复(因为回测是一次性跑完的)。但在逻辑上,它依然保持了跨日的状态延续。