期货量化进程重启后状态丢了:天勤策略状态持久化
前言
服务器重启、策略升级、异常退出后,进程内的变量全没了:网格档位计数、昨日信号标志、自定义止损线,若只靠 position 恢复,往往不够。我遇到过重启后策略以为「还没开过仓」又开一遍,或与真实持仓叠加。
天勤 TqSdk 的 position、account 会随柜台更新,但业务状态(第几根 K 线、内部计数器、参数版本号)要自己做持久化。下面用 JSON 文件示意保存与恢复,适合个人和小团队;大规模可用 SQLite,思路相同。
一、什么该持久化、什么不该
宜保存:
- 策略内部状态机阶段(如 grid_level、last_signal)
- 上次处理的 K 线
datetime - 配置版本号、随机种子(若可复现)
不宜只靠文件保存:
- 真实持仓、资金(以
get_position、get_account为准) - 未成交挂单(以
order查询为准)
重启后先读柜台,再读文件,文件与柜台冲突时以柜台为准并打日志。
二、JSON 持久化示例
import json
import os
from pathlib import Path
STATE_PATH = Path("data/strategy_state.json")
def load_state():
if not STATE_PATH.exists():
return {}
with STATE_PATH.open(encoding="utf-8") as f:
return json.load(f)
def save_state(state: dict):
STATE_PATH.parent.mkdir(parents=True, exist_ok=True)
tmp = STATE_PATH.with_suffix(".tmp")
with tmp.open("w", encoding="utf-8") as f:
json.dump(state, f, ensure_ascii=False, indent=2)
tmp.replace(STATE_PATH)
# 主循环片段
state = load_state()
state.setdefault("last_bar_dt", None)
state.setdefault("grid_level", 0)
while True:
api.wait_update()
if api.is_changing(kl.iloc[-1], "datetime"):
bar_dt = str(kl.datetime.iloc[-2])
if bar_dt != state["last_bar_dt"]:
state["last_bar_dt"] = bar_dt
# ... 信号逻辑,可能改 state["grid_level"]
save_state(state)
用临时文件再 replace,降低写到一半进程死掉导致 JSON 损坏的概率。
三、重启恢复流程
- 启动脚本,
TqApi连接成功后wait_update一到两帧。 - 读
position、get_order(若有挂单查询需求)。 load_state()。- 对比:若
position非零但 state 显示空仓,记录告警,按团队规则决定是否人工介入或重置 state。 - 进入主循环;关键状态变更后
save_state。
不要把「重启」和「换月移仓」混在一次里不做日志。
四、与无人值守、日志配合
持久化文件进 .gitignore;备份到与日志同目录便于复盘。进程外监控发现重启时,应检查 state 文件 mtime 与内容是否合理。
若用 pickle,注意 Python 版本兼容;JSON 更易人工查看,推荐优先。
五、多策略多文件
每个策略 strategy_a_state.json 分开,勿多进程写同一文件。多进程写需要文件锁,小团队用单进程单策略更简单。
总结
进程重启后,position、account、活跃委托应以 wait_update 后的 TqSdk 查询为准;网格档位、上一根 K 线 datetime、内部计数器等业务状态不会自动回来,需 JSON 等文件持久化。恢复顺序:连接成功 → 读柜台持仓与挂单 → load_state() → 若文件显示空仓但 position 非零,打告警并按规程人工介入或重置 state → 再进入主循环。冲突一律以柜台为准。
保存宜用「写临时文件再 replace」降低损坏概率;data/ 进 .gitignore,Docker 挂载卷保留 state。多策略各用各的 state 文件,避免多进程共写。不宜用文件保存真实持仓代替 get_position。
建议每策略维护重启检查表:position 手数、挂单列表、state 文件 mtime 与关键字段各记一行日志后再续跑;升级脚本或换月当日额外做一次核对。
FAQ
1)多久 save 一次?
状态变更时写;每根 K 线最多一次通常够。
2)state 能放 Git 吗?
不要;仅放服务器本地。
3)Docker 重启容器?
挂载 data/ 卷,否则 state 丢。
4)回测要写 state 吗?
一般不必;回测要可重复。
风险提示
本文用于工程实践说明,不构成投资建议。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)