Ⅰ · 概念地基 — 1.4
状态、账本与生命周期
生产系统与回测脚本的差别,几乎全部落在这一页。
持仓不是“查一下”,是一个组件
MT5 里想知道当前持仓,调 PositionsTotal() / AccountInfoDouble()——终端就是唯一真相,问一句就有答案。
自研平台里持仓是一个由事件驱动维护的组件:订单成交事件到达 → 更新持仓 → 重算未实现盈亏 → 更新保证金占用。它不“问”券商,它推演。
为什么要推演而不是查?因为回测里没有券商可问。同一份策略要在两种模式下工作,持仓状态就必须由框架自己维护。
于是有了两份账本
create_inferred_order_filled_event(为本地未记录的成交推断补录事件)、calculate_reconciliation_price、adjust_fills_for_partial_window ✓ 已实测——系统需要推断自己漏掉的成交,这个模块的存在本身说明问题是真实的。组件有状态机,因为生产环境会出事
EA 的生命只有两个状态:OnInit() 成功了在跑,或者没跑。生产系统需要更细的划分——比如“行情断了但持仓还在,不能当作正常运行,也不能直接关停”。
Nautilus 的 ComponentState 实测有 14 个取值 ✓ 已实测:
# 正常路径
PRE_INITIALIZED → READY → STARTING → RUNNING → STOPPING → STOPPED → DISPOSING → DISPOSED
# 恢复路径
RESUMING · RESETTING
# 异常路径 —— MT5 无对应概念
DEGRADING → DEGRADED 降级:部分功能不可用,但不停机
FAULTING → FAULTED 故障:需要人工介入
状态迁移由 ComponentTrigger(15 个取值)约束,不能任意跳转。策略可以覆写 on_degrade() / on_fault() 来定义“降级时怎么办”——例如只平仓不开新仓。
**另一项 MT5 没有的能力:状态持久化。**Nautilus 的 on_save() / on_load() 是框架级回调,重启后策略内部状态可恢复。MT5 需要自行用 FileOpen 实现——这在实际项目中确实有人做(SaveExpertData / LoadExpertData),只是没有框架约定,每个 EA 各写各的。