模拟交易变量持久化
由qxiao创建,最终由qxiao 被浏览 10 用户
1. 回测 vs 模拟交易,最大的“隐藏差异”是什么?
在回测里,策略通常是一个连续进程跑完整个区间:
initialize()只执行一次- 变量在内存里一直存在(计数器、上次调仓日、上次权重……)
但在模拟交易里,系统很常见的运行方式是:
- 每个交易日(或每次任务触发)启动一次策略
- 执行 initialize()、handle_data() 后退出
- 第二天再次启动时,内存变量全部丢失
所以,如果如果把“策略状态”只放在 Python 变量里,模拟交易就会“失忆”。
2. 什么叫“变量持久化”?
变量持久化 = 把策略的关键状态从“内存”搬到“可恢复的存储”里,让策略下次启动还能“记得昨天做过什么”。
在 BigTrader 体系里最直接的方式是 context.user_store:
- 它是一个字典
- 用来存放你的用户状态
- 在模拟交易等模式下会自动保存和恢复
- 但存进去的值需要支持 JSON 序列化
3. 反例:没有进行变量持久化的双均线策略
我们使用一个最简单、最常见的策略——双均线策略(短均线/长均线金叉买入、死叉卖出),并设定“每 5 个交易日才进入一次交易逻辑”来展示:
- 不做持久化会出现什么问题(反例)
- 使用
context.user_store后如何修正
策略逻辑:
- 计算短均线 MA(short_n) 与长均线 MA(long_n)
- 若 MA(short) > MA(long):买入(满仓)
- 否则:卖出(空仓)
- 为了展示状态问题,加入一个节奏控制:每 5 个交易日才执行一次交易逻辑
参数示例:
short_n= 5long_n= 20rebalance_days= 5- 标的:
510300.SH(示例:沪深300ETF)
关键问题:使用 context.counter 作为计数器,它只是内存变量,模拟交易重启就会归零。
https://bigquant.com/codesharev3/fe834bd1-d447-415d-bd72-657fd24528ce
此代码在回测中可以正常运行,但在模拟交易中策略往往会按天调度、可能反复启动/重启进程,若使用 context.counter这类仅存在于内存的变量来记录调仓计数,就会在重启后被重置,导致“每 5 天执行一次”的节奏失真;因此需要改用 context.user_store对计数器等关键状态进行持久化,才能保证模拟交易跨天连续、稳定运行。
4. “模拟交易标准”的正确写法
4.1 幂等初始化:只在第一次设置默认值
模拟交易可能会按天启动策略进程。若在 initialize() 里每次都给计数器赋值,就会把昨天恢复的状态覆盖掉。正确做法是只在不存在时写入默认值(幂等初始化)。
def initialize(context):
context.rebalance_days = rebalance_days
# ✅ 幂等初始化:只在第一次创建 counter
if "counter" not in context.user_store:
context.user_store["counter"] = 0
这就是“幂等”:
- 第一次运行:
user_store里没有counter→ 写入默认值 0 - 之后每次启动:counter 已存在(且平台会恢复昨天保存的值)→ 不覆盖
- 这样策略才能“记住昨天过了几天”,保证调仓节奏稳定。
也可以用更短写法:context.user_store.setdefault("counter", 0),含义一致。
4.2 持久化计数器
防止重启的情况下变量丢失
# ✅ 持久化计数器:跨天/重启不丢
context.user_store["counter"] += 1
if context.user_store["counter"] < context.rebalance_days:
return
context.user_store["counter"] = 0
- 这段是“节奏控制”的核心:每天 +1,到第 5 天才进入交易逻辑。
- 如果用内存变量,重启后会回到 0,节奏就会失真。
- 换成
user_store["counter"]后,哪怕重启也能从昨天的值继续累加。
5. user_store 的边界与注意事项
user_store 适合“状态”,不适合“数据”。
5.1 可以存
int/float/str/boollist/dict(内部元素也必须是可序列化类型)- 小体量状态:计数器、日期、权重字典、开关
5.2 不建议/不要存
DataFrame- numpy array、scipy 对象
- 自定义类实例
- 大量历史数据
如果需要保存表格化结果(如每日信号面板、调仓记录、因子表),应使用更合适的数据存储方式(例如写入表),而不是塞进 user_store。
6. 总结
我们在模拟交易中做变量持久化,是为了保证策略具备“连续记忆”,使其运行方式更接近未来的实盘。
\