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

PTrade量化交易中如何实现变量持久化(防止重启重置)?

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

问题描述

如何在PTrade策略中保持变量状态不被重置?

解决方案

在PTrade量化交易平台进行模拟盘或实盘交易时,服务器重启或券商环境升级可能会导致策略中的变量状态丢失。为了保持变量状态不被重置,我们需要进行持久化处理。PTrade提供了框架自动持久化和手动持久化两种方式。

一、 PTrade框架的自动持久化机制

PTrade框架默认会使用 pickle 模块自动保存股票池、账户信息、订单信息以及全局变量 g 定义的变量

  • 保存时机:框架会在 before_trading_start(隔日开始)、handle_dataafter_trading_end 事件后触发持久化信息更新及保存操作。
  • 恢复时机:环境重启后恢复交易时,框架会先执行策略的 initialize 函数,然后再执行持久化信息恢复操作。这意味着,持久化信息中的变量会覆盖掉 initialize 函数中初始化的同名变量。

二、 自动持久化的注意事项

依赖框架自动保存 g 变量时,必须注意以下几点:

  1. 不可序列化的对象:涉及到 IO(如打开的文件)、实例化的类对象等是不能被序列化的,强行保存会导致报错。
  2. 私有变量跳过保存:如果 g 中有不能被序列化的变量,或者你不想保存某个变量,可以在 initialize 中初始化该变量时,名字以 __ 开头(例如 g.__test_class)。以 __ 开头的变量被视为私有变量,持久化时将不会被保存。

三、 手动持久化处理方法(推荐)

对于复杂的策略状态(如字典、列表等),推荐使用 Python 的 pickle 模块手动将数据保存到 PTrade 的研究路径下。这样可以更精确地控制数据的读取和写入。

完整代码示例:持仓天数(仓龄)的持久化保存

以下示例展示了如何使用 pickle 模块保存一个记录股票持仓天数的字典,确保策略重启后逻辑连贯:

import pickle
from collections import defaultdict

# 获取研究路径,用于存放持久化文件
NOTEBOOK_PATH = get_research_path()

'''
持仓N日后卖出,仓龄变量每日pickle进行保存,重启策略后可以保证逻辑连贯
'''
def initialize(context):
    # 尝试读取本地的 pickle 文件恢复状态
    try:
        with open(NOTEBOOK_PATH + 'hold_days.pkl', 'rb') as f:
            g.hold_days = pickle.load(f)
    # 如果文件不存在(首次运行),则定义空的全局字典变量
    except:
        g.hold_days = defaultdict(list)
        
    g.security = '600570.SS'
    set_universe(g.security)

# 每天盘前,仓龄增加一天
def before_trading_start(context, data):
    if g.hold_days:
        g.hold_days[g.security] += 1
        
# 盘中处理逻辑
def handle_data(context, data):
    # 如果没有持仓且没有记录仓龄,则买入并记录
    if g.security not in list(context.portfolio.positions.keys()) and g.security not in g.hold_days:
        order(g.security, 100)
        g.hold_days[g.security] = 1
        
    # 如果持仓天数大于5天,则卖出并删除记录
    if g.hold_days:
        if g.hold_days[g.security] > 5:
            order(g.security, -100)
            del g.hold_days[g.security]
            
    # 每天将存储仓龄的字典对象进行 pickle 保存落地
    with open(NOTEBOOK_PATH + 'hold_days.pkl', 'wb') as f:
        pickle.dump(g.hold_days, f, -1)

总结

  • 简单变量:直接挂载到 g 对象上,利用框架自动持久化。
  • 复杂状态/自定义逻辑:使用 pickle.dumppickle.load 结合 get_research_path() 手动读写文件。
  • 不可序列化对象:务必使用 g.__变量名 的形式声明为私有变量,避免框架自动保存时报错。