3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 ptrade 实盘或模拟盘运行中,如果遇到券商服务器升级或环境重启,系统会重新拉起交易并再次执行 initialize 函数。如果策略的状态(如是否已建仓的标志位、持仓天数等)仅保存在内存中的全局变量 g 里,重启后这些变量会被重置,从而导致策略“失忆”,引发重复建仓或错误的平仓逻辑。
要解决这个问题,需要从数据持久化和平台参数配置两个方面入手:
pickle 进行变量持久化ptrade 提供了 get_research_path() 接口,可以将需要记忆的变量通过 Python 的 pickle 模块序列化保存到本地文件中。每次 initialize 时先尝试读取该文件,如果读取失败再进行初始化;在状态发生改变时(如 handle_data 或 after_trading_end 中)将最新状态写回文件。
set_parameters 防止重复执行在 initialize 中使用 set_parameters 函数,设置 not_restart_trade="1" 和 server_restart_not_do_before="1",可以有效防止交易时间段服务器重启导致的重复拉起和 before_trading_start 的重复执行。
在执行买卖操作前,务必通过 get_position() 或 get_open_orders() 检查当前真实的账户持仓和未成交订单,不要仅依赖自定义的标志位。
以下是一个结合了持久化和防重启配置的完整策略模板:
import pickle
import os
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 1. 设置防重启参数,防止盘中重启导致重复执行
set_parameters(not_restart_trade="1", server_restart_not_do_before="1")
# 2. 定义持久化文件路径
g.save_path = get_research_path() + 'strategy_state.pkl'
# 3. 尝试加载历史状态
if os.path.exists(g.save_path):
try:
with open(g.save_path, 'rb') as f:
g.state = pickle.load(f)
log.info("成功加载持久化状态: %s" % g.state)
except Exception as e:
log.error("加载持久化文件失败: %s" % e)
g.state = {'has_bought': False, 'hold_days': 0}
else:
# 如果没有文件,说明是首次运行
g.state = {'has_bought': False, 'hold_days': 0}
def handle_data(context, data):
security = g.security
current_price = data[security]['close']
# 获取真实持仓,双重校验
pos = get_position(security)
# 建仓逻辑:如果没有买过,且满足条件
if not g.state['has_bought'] and pos.amount == 0:
order(security, 100)
g.state['has_bought'] = True
g.state['hold_days'] = 1
save_state() # 状态改变,立即落地保存
log.info("建仓成功,状态已保存")
# 平仓逻辑:如果持仓天数大于5天
elif pos.amount > 0 and g.state['hold_days'] > 5:
order_target(security, 0)
g.state['has_bought'] = False
g.state['hold_days'] = 0
save_state() # 状态改变,立即落地保存
log.info("平仓成功,状态已重置")
def before_trading_start(context, data):
# 每天更新持仓天数
if g.state['has_bought']:
g.state['hold_days'] += 1
save_state()
def save_state():
# 封装保存状态的函数
try:
with open(g.save_path, 'wb') as f:
pickle.dump(g.state, f, -1)
except Exception as e:
log.error("保存持久化文件失败: %s" % e)
pickle 序列化的。如果 g 中有这些变量,请在变量名前加双下划线(如 g.__db_conn),这样框架在默认持久化时会跳过它们。get_position() 和 get_trades() 返回的真实账户数据为准,持久化变量仅作为辅助逻辑判断。