你告诉我,你的纸面交易进程昨夜崩溃了。你赶在下一次决策前重启了它,没看到任何错误,便以为它已从中断处接着运行。接着,它又买入了一项你已经持有的资产。你想知道是不是策略出了 bug。
确实有可能。但首先,检查重启后的进程是否掌握着与纸面账户相同的信息。重启本质上是一个状态恢复问题:持仓、现金、未结订单,以及所有会影响下一次决策的策略记忆,都必须彼此吻合。让代码重新跑起来反而是容易的部分。
崩溃前,策略认为当时是什么情况?
记下进程停止前做出的最后一次决策。对每个交易标的,记录预期持仓、账户实际持仓、未完成订单,以及会影响下一步操作的信号状态。如果没有这些记录,你就无法判断重启时究竟恢复了原有状态,还是只初始化了一个全新的策略。
假设你的小时级策略会在趋势信号转为正值时买入 1 单位,并一直持有到信号转为负值。进程在 14:00 提交了买单,却在记录订单已被接受前崩溃。纸面交易场所成交了这笔订单。重启时,策略发现没有已记录的持仓,而信号仍为正,于是又提交了一笔买单。信号本身前后一致;过时的是策略对账户持仓的记忆。
因此,在允许提交新订单前,必须将账户当前持仓与已持久化的策略状态核对一致。本地快照可能有用,但实际成交情况应以账户或交易场所为准。
哪些状态必须在重启后保留下来?
先从可能改变下一笔订单的状态着手。为每次更新保存带时间戳和版本号的持久记录;修改恢复逻辑前先复制一份,这样之后就能重放这次故障。
| 状态 | 为什么重要 | 恢复检查 |
|---|---|---|
| 持仓和现金 | 它们决定风险敞口和可用购买力 | 将持久化数值与纸面账户进行对比 |
| 未结订单 | 进程停止期间,订单可能已经成交 | 查询订单状态并核对部分成交情况 |
| 信号记忆 | 交叉信号、冷却期和持仓周期可能跨越多次决策 | 恢复最近一次已提交决策所用的输入 |
| 最后处理的事件 | 它决定策略从何处继续读取数据 | 重放此后的事件,但不要重复应用 |
信号记忆很容易被忽略。基于交叉信号交易的策略可能会保存前一天的指标值,以便检测新的交叉。如果它以空值启动,就可能把已经存在的条件误认为刚刚触发的事件。冷却计时器也有同样的问题:重启不能悄悄重置原本应持续生效的规则。
怎样才能让恢复过程可重复?
为每笔订单分配稳定的客户端 ID,根据策略运行实例和订单所对应的决策生成。如果超时后进程重试,就可以先检查该决策是否已创建订单,而不是再次下单。只有确认相应账户事件后,才记录状态变化;同时保存能够解释这一变化的订单 ID 和成交 ID。
接下来,测试导致这次故障的临界环节。让策略执行一次决策并保存状态,然后停止进程,再结合纸面账户的持仓和订单历史恢复运行。将恢复后的下一次决策及其订单,与不中断运行时的结果进行比较。再分别测试订单部分成交的情况,以及订单提交后、收到确认前进程崩溃的情况。恢复后的运行不应凭空产生新的持仓,也不应重复已经完成的操作。
保留恢复日志:最后处理的事件、账户快照时间、未结订单状态、恢复的策略版本,以及重启后的第一次决策。这样,“进程重新启动了”就成了可审计的记录。
重启后,应该相信什么?
只有在账户状态与策略状态核对一致、待处理订单的状态明确,而且下一次决策符合连续运行时的预期后,才可以信任这个进程。如果你无法解释两者之间的差异,就暂停纸面下单并检查事件记录。进程正在运行,并不能证明策略已经恢复。
这次崩溃已经带来了一个有用的发现:它揭示了一个平时运行时从未需要面对的假设。把重启设为可重复的测试场景,这样在让策略再次交易前,你就能知道它记住了什么。
← 全部文章


