实盘 0DTE 系统中的风险不变量与执行安全
安全高于正确性,正确性高于利润。实盘 0DTE 系统把这条层级写成硬性不变量——单一持仓、只做多、当日硬止损、强制 EOD 平仓——由状态机与 schema 级测试强制执行而非靠注释,生产事故则被转化为永久的回归测试。
不变量,按原文
各实盘系统共享同一条优先级——安全 > 正确性 > 利润——并把它写成配置级不变量(摘自配置原文):
one_position_only: true、no_naked_short: true、forbid_add_to_loser: true、forbid_reverse_without_flat: true- 当日回撤阶梯:NAV 的 1.5% 软止损(缩减仓位)、2% 硬止损(锁定全天)。连亏保护:连亏 2 笔仓位减半、3 笔停止当日交易。
max_trades_per_day设得很低(各系统 2–5 笔)。 - 15:45 强制平仓,配合
force_cancel_all_before_eod_flatten: true;会话重置逻辑保证被平掉的一天不会悄悄重新开仓。 - 其中一个系统跑四维止损:期权权利金 −35%、SPX 不利移动 10 点、8 分钟内推进不足 5 点、以及 IV 崩塌检测(SPX 几乎没动而权利金 −20%)——硬性维度每 100ms 检查一次,慢速维度每 5 秒一次。
强制方式是结构性的,不是文档性的:四状态执行状态机的 can_enter() 只在 FLAT 状态为真;风险内核返回 allowed + reason,被拒绝的入场自带审计线索;schema 级数据测试(SPX K 线不得带 volume 列——在加载时就能抓住接错数据源的 join)嵌在 300+ 测试套件里。
三个生产事故,三个永久测试
- **僵尸头寸。**成交被检测到,但状态机没有从
PENDING_ENTRY转移出去。结果:一个实盘头寸,所有出场路径都静默拒绝平仓——因为出场要求状态为OPEN。修复之外,新增回归测试断言每个成交事件都完成状态转移。 - **幻影头寸。**IBKR 的“成交后改单”竞态(错误 104)会对一张实际已成交的订单报告
status='Cancelled'。照字面处理会以 0.0 的价格入账——或如原始 bug 那样把真实成交当成撤单。处理器现在在相信任何Cancelled状态之前检查filled_qty > 0 and avg_fill > 0。 - **孤儿合约。**分批止盈的成交路由靠询问
sm.is_open()——但提交出场后状态机处于PENDING_EXIT,于是部分成交被误判为全平,未卖出的合约留在了账户里。修复改为显式跟踪出场类型,而不是从状态反推。
三个 bug 全部来自实盘或模拟盘会话,没有一个被最初的单元测试抓到——如今每个都以命名回归测试的形式存在,行为一旦倒退就会大声失败。
教训
活在注释里的不变量只是愿望。在生产环境里真正成立的,是状态机、类型或测试能够拒绝的那些——而补上下一条不变量最便宜的时机,就是事故让你看见缺口的当天下午。