3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 PTrade 策略开发中,在不同函数(如 initialize、handle_data、before_trading_start 等)之间共享和传递变量,主要通过 全局对象 g 来实现。
gg 是 PTrade 策略引擎提供的一个特殊的全局容器对象。它的主要特点如下:
g 中的属性。g 对象中的变量(除非以 __ 开头)会被系统自动保存(Pickle序列化)。这意味着即使策略暂停、服务器重启或隔日运行,g 中的数据依然会被保留,保证策略逻辑的连续性。通常的流程是:
initialize 函数中初始化变量。handle_data 或其他函数中读取或修改这些变量。以下是一个完整的策略示例,展示了如何使用 g 记录交易天数和控制买卖状态:
def initialize(context):
"""
初始化函数,设置全局变量
"""
# 1. 初始化股票池
g.security = '600570.SS'
set_universe(g.security)
# 2. 定义全局变量 g.count,用于记录运行次数
g.count = 0
# 3. 定义全局变量 g.has_bought,用于记录是否已买入
g.has_bought = False
log.info("策略初始化完成,全局变量已设置")
def before_trading_start(context, data):
"""
盘前处理函数
"""
# 读取全局变量
log.info("盘前检查:当前运行次数为 %s" % g.count)
def handle_data(context, data):
"""
盘中运行函数
"""
# 修改全局变量:计数器加1
g.count += 1
# 读取并使用全局变量进行逻辑判断
if not g.has_bought:
log.info("第 %s 次运行,执行买入操作" % g.count)
order(g.security, 100)
# 修改状态标记
g.has_bought = True
else:
log.info("第 %s 次运行,已持仓,跳过买入" % g.count)
def after_trading_end(context, data):
"""
盘后处理函数
"""
log.info("盘后总结:今日共运行了 handle_data %s 次" % g.count)
持久化限制:
g 中的变量会被系统使用 pickle 模块序列化保存。因此,不能将无法序列化的对象(如打开的文件句柄、数据库连接对象、套接字等)赋值给 g 的普通属性,否则会导致策略保存失败或重启报错。initialize 中实例化的某个复杂类),可以将变量名命名为以 双下划线开头(如 g.__my_class)。以 __ 开头的变量被视为私有变量,不会被持久化保存,重启后需要重新初始化。命名冲突:
g.data),以免与系统未来可能保留的关键字冲突。建议使用具有业务含义的名称,如 g.buy_signal_date。重启后的行为:
initialize,然后恢复持久化数据。如果持久化数据中已经存在 g.xxx,它会覆盖 initialize 中重新赋值的 g.xxx,从而保证策略记忆不丢失。Q: 为什么不能直接使用 Python 的 global 关键字定义全局变量?
A: 虽然在 Python 脚本中可以使用 global 关键字,但在量化交易平台中,普通的 Python 全局变量无法在服务器重启或策略暂停恢复后自动保存(持久化)。一旦策略进程重启,普通全局变量会重置,导致策略逻辑(如持仓天数、止损标记)丢失。使用 PTrade 提供的 g 对象可以确保数据安全地跨日、跨重启保存。
Q: g 对象能存储 Pandas 的 DataFrame 吗?
A: 可以。Pandas 的 DataFrame 和 Series 是可以被序列化(Pickle)的,因此可以安全地存储在 g 对象中。这在需要记录历史计算结果或自定义因子的场景中非常有用。
Q: 如果我在 initialize 中设置了 g.a = 1,策略运行几天后 g.a 变成了 10,此时重启策略,g.a 是多少?
A: 是 10。PTrade 的机制是:重启时先运行 initialize(将 g.a 设为 1),随后系统会立即加载之前保存的持久化文件,用保存的值(10)覆盖掉 initialize 中的值。因此,最终 g.a 会恢复为 10,保证策略逻辑连贯。