🚀 AI 一键生成 ptrade 策略代码

PTrade 策略开发基础:全局变量 g 对象的正确使用与最佳实践

ptrade | 发布时间: 2025/12/2
以下内容由 EasyQuant 生成。

问题描述

如何在策略的不同函数之间共享和传递变量?

解决方案

在 PTrade 策略开发中,在不同函数(如 initializehandle_databefore_trading_start 等)之间共享和传递变量,主要通过 全局对象 g 来实现。

核心机制:全局对象 g

g 是 PTrade 策略引擎提供的一个特殊的全局容器对象。它的主要特点如下:

  1. 全局可访问:在策略的任何函数中都可以访问和修改 g 中的属性。
  2. 自动持久化g 对象中的变量(除非以 __ 开头)会被系统自动保存(Pickle序列化)。这意味着即使策略暂停、服务器重启或隔日运行,g 中的数据依然会被保留,保证策略逻辑的连续性。

使用方法

通常的流程是:

  1. initialize 函数中初始化变量。
  2. 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)

关键注意事项

  1. 持久化限制

    • g 中的变量会被系统使用 pickle 模块序列化保存。因此,不能将无法序列化的对象(如打开的文件句柄、数据库连接对象、套接字等)赋值给 g 的普通属性,否则会导致策略保存失败或重启报错。
    • 如果必须使用无法序列化的对象(例如在 initialize 中实例化的某个复杂类),可以将变量名命名为以 双下划线开头(如 g.__my_class)。以 __ 开头的变量被视为私有变量,不会被持久化保存,重启后需要重新初始化。
  2. 命名冲突

    • 建议不要使用过于通用的名称(如 g.data),以免与系统未来可能保留的关键字冲突。建议使用具有业务含义的名称,如 g.buy_signal_date
  3. 重启后的行为

    • 当实盘或模拟盘服务器重启恢复交易时,框架会先执行 initialize,然后恢复持久化数据。如果持久化数据中已经存在 g.xxx,它会覆盖 initialize 中重新赋值的 g.xxx,从而保证策略记忆不丢失。

Q&A

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,保证策略逻辑连贯。