Ⅰ · 概念地基 — 1.3

行情与执行为什么分开

这个分离不是洁癖。它是"同一份策略代码能跑回测也能跑实盘"的唯一实现方式。

两条方向相反的流

系统里有两条独立的数据通路,它们的性质完全不同:

行情流(入) 执行流(出)
方向 市场 → 策略 策略 → 市场 → 回报 → 策略
频率 高,且不可控 低,由策略决定
失败形态 断流、缺口、延迟、乱序 拒单、部分成交、超时、重复
可否重放 可以——历史数据就是重放 不可以——下过的单无法重来
幂等性 重复接收无害 重复下单是事故

把两条性质如此不同的流混在一起处理,结果就是回测与实盘必须是两套代码——因为回测里没有“拒单”,实盘里没有“重放”。

分开之后能做什么

不变的中间层策略代码 —— 逐字节相同风控持仓核算DataClient历史文件 或 实时行情ExecutionClient模拟撮合 或 真实券商行情订单成交回报↓ 可替换 ↓↓ 可替换 ↓回测 = 历史文件 + 模拟撮合  实盘 = 实时行情 + 真实券商  中间层一行不改纸上交易 = 实时行情 + 模拟撮合 —— 因为两端独立,这个组合自然存在,不需要额外开发。
两端可替换,中间不变。纸上交易(实时行情 + 模拟撮合)是这个结构的免费副产品——两端既然独立,任意组合都成立。MT5 中没有对应形态,因为行情与执行都绑死在终端上。

一个实测出来的推论

用 Nautilus 跑回测时,只向撮合引擎提供单边(BID)序列,全部订单被拒,原因 no market ✓ 已实测。补上 ASK 序列后正常成交。

这说明模拟撮合是一个真的在撮合的组件,而不是“用收盘价假装成交”。点差是成交模拟的前提,不是事后调整项——回测保真度的上限由喂进去的数据粒度决定。