3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在PTrade量化交易平台进行模拟盘或实盘交易时,服务器重启或券商环境升级可能会导致策略中的变量状态丢失。为了保持变量状态不被重置,我们需要进行持久化处理。PTrade提供了框架自动持久化和手动持久化两种方式。
PTrade框架默认会使用 pickle 模块自动保存股票池、账户信息、订单信息以及全局变量 g 定义的变量。
before_trading_start(隔日开始)、handle_data、after_trading_end 事件后触发持久化信息更新及保存操作。initialize 函数,然后再执行持久化信息恢复操作。这意味着,持久化信息中的变量会覆盖掉 initialize 函数中初始化的同名变量。依赖框架自动保存 g 变量时,必须注意以下几点:
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.dump 和 pickle.load 结合 get_research_path() 手动读写文件。g.__变量名 的形式声明为私有变量,避免框架自动保存时报错。