← 返回模块
4.6.3.1beta 可读 · 未来免费内容校验中内容版本 2026-05-28

OMS、EMS 与交易系统架构

4.6.3 · 实盘交易与运营 · 量化全流程

OMS、EMS 与交易系统架构

某五因子多空股票私募在多策略平台回测夏普 1.8(扣除模型化成本)。周一以 5 亿美元名义本金上线、通过国信证券执行,中信证券 PB 提供融资。三十个交易日后,实盘夏普 0.4。这不是单一 bug —— 它是回测忽略的每一层运营基础设施合并的滑点:目标组合差分延迟到 OMS;OMS 合规闸门拒绝 20% 转入覆盖;EMS 切片宽出回测假定一倍;FIX 通道在 09:30 上证开盘脉冲里排队;部分成交后均价比 VWAP 差两个基点;drop-copy 对账推迟 PnL 一天;盘后查出十二笔被 EMS 漏记的错价。本课结束时你应当能命名 PM 意图到 T+1 结算之间的每个组件、把实盘 PnL 偏差定位到具体生命周期步骤,并判断策略需要自研栈还是厂商方案。

本课是模块的架构基底。第二层(连接)、第三层(风控)、第四层(运营)都构筑在本课所固定的订单生命周期之上。下面分五块展开。

(A) OMS 与 EMS 作为两套独立系统

先给课本定义,再讲为什么要分开。

订单管理系统(OMS)是父订单、持仓、子账户分摊、合规状态的持久化记账本。它回答"基金当前持有什么、今天交易了什么、允许交易什么、哪个子账户拿哪份分摊"。底层存储是事务型数据库(Postgres / Oracle / DB2)。一致性严格 ACID。延迟容忍 10–100 毫秒 —— 够慢到把行刷盘以保证审计耐久。审计 trail 由证监会《证券公司监督管理条例》及 CSRC《程序化交易管理暂行规定》要求保留五年。

执行管理系统(EMS)是实时报单路由器。它接父订单,跑执行算法(TWAP / VWAP / 实施差额 / POV / Almgren–Chriss —— 4.5.3 设计、本课调用),切成子订单,把每个子单路由到最优场所,跟踪在途订单状态。底层存储在内存里:Redis 加 WAL、无锁共享内存环形队列、最快的台子上是 kdb+。一致性是最终一致 —— 成交可以乱序到达,EMS 重排序。延迟目标亚毫秒级端到端。EMS 不需要 OMS 的审计耐久 —— 等价 FIX 协议日志(STEP / OES / CTP 日志)本身就是受监管的审计 trail。

下面这段内联代码列表固定 OMS 与 EMS 的职责划分:

(1) OMS owns book_of_record (parent_orders, positions, allocations, compliance_state)
    — durable / Postgres-backed / strong-consistent / 10-100ms tolerable / 证监会五年留存
(2) EMS owns in_flight_order_state (child_orders, real_time_routing, execution_algorithm_invocation)
    — in-memory / Redis-or-shared-memory / eventually-consistent / sub-ms target / FIX-log audit trail

为什么要分开? OMS 的耐久性与一致性要求与亚毫秒延迟根本不兼容:商用硬件上一次 Postgres 提交加 fsync 至少 5–50 毫秒。混在一起要么得到一个慢 EMS(秒级而非亚毫秒级),要么得到一个无审计的 OMS(高负载下漏记成交)。机构通行做法是两套系统通过高吞吐消息总线相连 —— Kafka、Solace、Aeron,或者头部机构的自研 RDMA 总线。

(B) 15 步标准订单生命周期

把这份清单当作整个模块逐字一致的约定。每一步都有系统归属、规范消息类型与延迟预算。

(1)  target_portfolio_from_optimizer
(2)  target_deltas_to_parent_orders
(3)  OMS_records_parent_and_allocation_and_compliance
(4)  parent_handed_to_EMS_with_algorithm_choice
(5)  EMS_slices_into_child_orders
(6)  per_child_pre_trade_risk_gate
(7)  child_FIX_out_to_exchange
(8)  ack_or_nack_received
(9)  partial_fills_accumulate
(10) fill_report_to_EMS_to_OMS
(11) position_updated
(12) post_trade_allocation_to_sub_accounts
(13) T0_drop_copy_reconcile_to_PB
(14) T1_settlement_to_custodian
(15) EOD_mark_to_market_and_PnL_rollup

编号列表形式如下:

  1. target_portfolio_from_optimizer
  2. target_deltas_to_parent_orders
  3. OMS_records_parent_and_allocation_and_compliance
  4. parent_handed_to_EMS_with_algorithm_choice
  5. EMS_slices_into_child_orders
  6. per_child_pre_trade_risk_gate
  7. child_FIX_out_to_exchange
  8. ack_or_nack_received
  9. partial_fills_accumulate
  10. fill_report_to_EMS_to_OMS
  11. position_updated
  12. post_trade_allocation_to_sub_accounts
  13. T0_drop_copy_reconcile_to_PB
  14. T1_settlement_to_custodian
  15. EOD_mark_to_market_and_PnL_rollup

用中文走一遍各步:步骤 1 是组合优化器为下一个再平衡周期产出的 target_portfolio.json 字典 {symbol: target_weight},批处理频率按组合频率运行(中证500增强日频、统计套利日内),预算 1–10 秒。步骤 2 把当前持仓与目标做差分,按子账户、方向、算法偏好把买卖量分组为父订单(100 毫秒至 1 秒)。步骤 3 OMS 给每个父订单盖上 account_idpm_idmandate_id,跑授权额度检查(单一名最大权重、行业上限、贝塔带)、限制名单核查(法律封锁、内幕封锁、观察名单)、软限额(每个父订单含落盘提交 50–200 毫秒)。步骤 4 基金经理(或自动路由规则)选择执行算法 —— 流动性大盘股选 VWAP、小盘选 TWAP、短衰减阿尔法选实施差额、暗池友好选 POV、对规模敏感的选被动限价 —— 通过 OMS–EMS 总线下发(1–10 毫秒)。步骤 5 EMS 把父订单转为子订单档期:VWAP 把 1,000,000 的 510300 ETF 切到 30 分钟内每分钟一片大致变成 ~30 个 ~33,333 股的子单(100 微秒至 10 毫秒)。

步骤 6 每个子单走过 L3 讲的盘前风控闸门 —— 监管(CSRC《程序化交易管理暂行规定》)要求经纪商执行的七项检查(每项 10–100 微秒)。步骤 7 把子单序列化为 FIX NewOrderSingle 35=D(或同等 SSE STEP、SZSE OES、CTP 报文),通过会话发送给交易所或经纪商(FIX 来回 500 微秒至 5 毫秒;高频二进制协议 1–10 微秒 —— L2 详述)。步骤 8 交易所返回 ExecutionReport 35=8,ExecType=0 为新单接收,ExecType=8 为拒单。步骤 9 与步骤 10 部分成交逐步累积,ExecutionReport 携带 LastQtyLastPxCumQtyLeavesQty;EMS 维护累计量与均价,把每笔成交贴到 OMS 总线;OMS 落盘到审计 trail(OMS 提交 10–100 毫秒)。步骤 11 OMS 重算父订单剩余名义额、单只持仓、子账户持仓、单一授权敞口。步骤 12 对跨子账户的大宗交易,均价按子账户分摊,费用按比例摊。

步骤 13 在盘后(或全时)把 EMS 成交与主经纪商 drop-copy 流逐字段比对 —— 这是 中信证券 / 国信证券 / 海通证券 / 招商证券 等券商 PB 订阅的只读 FIX 等价会话。任何差异就是差异单(break);差异单必须在监管截止之前关掉(L3 详述)。步骤 14 净持仓走 T+1 结算(沪深 A 股、ETF 由 CSDC 中国证券登记结算公司处理;中金所 股指期货 T+0 每日盯市)。步骤 15 盘后盯市按结算价(上证 / 深证 14:57–15:00 集合竞价收盘价、中金所 结算价)算出按策略 / 账册 / 子账户的日度 PnL,写入日度 PnL 数据仓库 —— 4.6.2 业绩归因管道的输入。

全生命周期延迟预算用 KaTeX 表达如下:

Llifecycle=L1+L2+L3+L4+L5+L6+L78+L9101-10s (optimizer)+100ms-1s+50-200ms+1-10ms+100μs-10ms+10-100μs+500μs-5ms+10-100msL_{lifecycle} = L_{1} + L_{2} + L_{3} + L_{4} + L_{5} + L_{6} + L_{7-8} + L_{9-10} \approx 1\text{-}10\,\text{s (optimizer)} + 100\text{ms-}1\text{s} + 50\text{-}200\,\text{ms} + 1\text{-}10\,\text{ms} + 100\,\mu\text{s-}10\,\text{ms} + 10\text{-}100\,\mu\text{s} + 500\,\mu\text{s-}5\,\text{ms} + 10\text{-}100\,\text{ms}

优化器一步主导预算;步骤 4 之后全部在毫秒到微秒区间。某信号若阿尔法衰减不到一分钟,就无法忍受步骤 1 的日批节奏 —— 这种策略必须做日内重算优化或者用连续再平衡 EMS,而不是日批模式。

Formula Explorer

N * (1/lambda) - rho

(C) 自研与采购的取舍

取舍三个维度。延迟容忍度:每次来回大于 10 毫秒 → 厂商方案够用;小于 10 毫秒 → 必须自研。连通性覆盖:跨多市场多品种(沪深300、CFFEX 股指、SHFE 商品、HKEX 港股通)→ 厂商方案省 18 个月的接入认证;单市场单品种 → 自研可行。定制逻辑:标准父子单与 VWAP/TWAP/IS → 厂商;特制路由、暗池探测、子单感知组合风险、自研智能路由 → 自研。

国内 OMS / EMS 厂商谱系:OMS 主流 —— 恒生电子 O45(国内买方 OMS 最大装机量,覆盖现金股票、ETF、ETF 期权、经 恒生 UFT 接 期货;公募与多数大型私募部署);国泰君安综合业务平台(头部券商自研 OMS);顶点软件、金证股份(中型厂商)。EMS / 经纪商 API 侧 —— CTP(综合交易平台,上海期货信息技术,几乎所有期货 CTA 都用)、易盛 ESunny(商品期货 EMS)、飞马 FemasAPI(亚毫秒级 HFT 商品 / 股指期货)。

国内头部量化私募自研栈:明汯投资自 2018 年起自研做亚毫秒级统计套利;幻方量化自研 Fire-Flyer 平台;灵均投资自研中证500 增强;衍复 / 鸣锣 / 中诚等多家头部私募也在 CTP / 飞马 / SZSE OES 之上自研。这些机构的共性是亚毫秒级要求,任何厂商产品都会带来不可接受的延迟税。

(D) 工作样例 —— 买入 1,000,000 股 510300

某中证500 增强 私募(管理规模 30 亿人民币)在国信证券通道下买入 1,000,000 股 510300.SH(沪深300 ETF)限价 6.45,子账户 CSI300_ENH_2,全部归属一只私募产品。

步骤 3 —— 恒生电子 O45 OMS 跑 AMAC 合规闸门(合格投资者 100 万门槛已核、单只 ETF 持仓不超过基金净值 10%、大额持仓报告触发阈值 5% 流通市值);限制名单清单清,Reg-Locate 等价的可融券核查不适用(本笔是买)。步骤 4 —— 基金经理选 VWAP 跨上海下午 13:30–14:30 段以避开 11:30 午休。步骤 5 —— EMS 切成 30 个 ~33,333 股的子单。步骤 6 —— 每个子单都过七项盘前检查(L3 详述),无人被拦。步骤 7 —— 子单经 SSE STEP 协议从 国信证券 报盘通道送上 上证。步骤 8 —— 应答约 5 毫秒返回。步骤 9–10 —— 下午时段成交逐步累积。步骤 13 —— 国信 drop-copy 在 15:30 对账,排查出一笔差异(子单成交 6.451,PB 记录 6.452 —— 1 分钱交易所侧错价),运营在 15:45 关掉。步骤 14 —— CSDC 中国证券登记结算公司隔夜 T+1 结算。步骤 15 —— 盘后盯市按上证 收盘价喂入日度 PnL 仓库。

下面这段围栅 python 代码块勾勒 OMS–EMS 交接:

# OMS-EMS canonical order lifecycle
class TradingStack:
    def optimizer_to_parents(self, target_portfolio):
        """Step 1-2: optimizer dict -> parent_order[] grouped by side / algo."""
        ...

    def oms_record_parent(self, parent_order):
        """Step 3: commit parent_order to durable OMS with allocation stamp."""
        ...

    def oms_pre_trade_compliance(self, parent_order):
        """Step 3: mandate limits, restricted list, soft limits."""
        ...

    def ems_invoke_algorithm(self, parent_order, algorithm):
        """Step 4: hand parent_order to EMS with VWAP/TWAP/IS/POV choice."""
        ...

    def ems_slice_to_children(self, parent_order):
        """Step 5: algorithm engine -> child_order[]."""
        ...

    def pre_trade_risk_gate(self, child_order):
        """Step 6: 程序化交易管理暂行规定 seven-check intercept inline before FIX."""
        ...

    def fix_send(self, child_order):
        """Step 7: serialize to FIX 35=D / STEP / OES / CTP and route to exchange."""
        ...

    def fill_report_to_oms(self, fill):
        """Step 10: post fill_record to OMS bus, update positions."""
        ...

    def eod_reconcile(self, fills, drop_copy):
        """Step 13: drop-copy compare, break classification, resolution."""
        ...

    def daily_pnl(self, positions, settlement_prices):
        """Step 15: EOD MTM + daily PnL rollup -> attribution warehouse."""
        ...

在打开下一节前提醒几条术语贯穿全模块:订单簿(L2 行情接入解析的标准化结构)、市场冲击(单笔订单造成的不利价格移动,通常次线性)、交易成本(显性 + 隐性合计)、时间加权平均价 与 成交量加权平均价 是 EMS 在步骤 5 调用的两类标准切片算法。

(E) 纪律条款与三类诊断

纪律条款简单到刻薄:任何实盘 PnL 与回测的偏差都对应到 15 步生命周期里的某一步;运营调试从定位偏差进入的那一步开始。 落地这条规则需要三件最低限度追踪工具:一个在步骤 1 打上、贯穿每个系统(OMS、EMS、FIX 通道、drop-copy、PnL)的结构化 trace_id;一个能按 trace_id 返回各步延迟和消息 trail 的 trace_log 查询界面;一份每日按生命周期步骤暴露差异的对账报告。

下面这段内联代码列表固定运营人员习惯使用的三类标准实盘对回测诊断:

(1) live_Sharpe_below_backtest_Sharpe        -> steps 5-8 (EMS slice + FIX round-trip)
(2) live_PnL_does_not_match_drop_copy_PnL    -> step 10 (fill to OMS missed)
(3) phantom_position_in_OMS                  -> step 8/10 (cancel-replace race + double-count)

live_Sharpe_below_backtest_Sharpe 一类:EMS 切片与步骤 5–8 之间的 FIX 来回延迟吃掉了阿尔法 —— 信号不到一分钟就衰减完,但回测假设以最后一笔行情即时成交。补救:收紧切片窗口、把 VWAP 换成实施差额,或接受阿尔法衰减现实并用真实滑点重建回测。live_PnL_does_not_match_drop_copy_PnL 一类:某笔成交报到了 EMS 但没传到 OMS —— 步骤 10 断了。补救:从 EMS 审计日志重放总线,补回漏记的 fill_recordphantom_position_in_OMS 一类:某子单成交但并发的撤改单产生竞争,OMS 在步骤 8 / 步骤 10 重复计数。补救:对 (OrderID, ExecID) 做去重的事务式成交回写。

关注点分离规则与 L4 收尾呼应:OMS 拥有耐久与审计;EMS 拥有延迟与路由;风控闸门拥有控制(L3);运营拥有对账(L4)。每一层失能都要漏几个基点,工作得好就把这些基点加回来。

Exercise

某实盘多空股票策略在 5 亿美元名义本金上跑出夏普 0.4 对回测的 1.8。(i) 按 PM 意图到 T+1 结算的顺序背诵 15 步标准生命周期。(ii) 对每一类诊断 —— live_Sharpe_below_backtest_Sharpelive_PnL_does_not_match_drop_copy_PnLphantom_position_in_OMS —— 指出偏差进入的步骤与负责的系统组件。(iii) 追踪一笔买入 1,000,000 510500.SH 的子单走过步骤 1–15,在每一步命名活跃的系统组件(优化器、OMS、EMS、FIX 通道、交易所、drop-copy、券商 PB、托管)并给出合理的延迟预算。(iv) 判断该策略应该跑在厂商栈(恒生 O45 + 国信 OES + CTP)还是必须自研,用延迟容忍度论证。

提示
按归属拆解生命周期:优化器与 OMS 占步骤 1–3,OMS–EMS 桥占步骤 4,EMS 占步骤 5 与 9–11,盘前闸门坐在步骤 6,FIX 通道在线上占步骤 7–10,券商 PB 与托管占步骤 12–14。
提示
关于自研 vs 采购,先问延迟:日频再平衡、多日半衰期信号的五因子多空书能舒服跑在恒生 O45 加 国信 OES 上;只有亚毫秒级统计套利才被逼到明汯 / 幻方那一档的自研栈。0.4 对 1.8 的差距是阿尔法衰减,不是基础设施。

通往 L2 的桥梁是步骤 7–9 的 FIX 通道 —— 实盘交易台触碰最多的组件。下一课会打开 FIX 报文格式,走会话状态机从 LogonSentLoggedOnLogoutSent,并演示一个错位的序列号如何在周一开盘把一只基金挡在市场之外。