3. 行情数据核心概念

在FIX协议行情接入中,真正决定解析逻辑正确性的,不是字段数量,而是对消息语义的理解。同一条FIX消息,在不同会话类型、不同市场、不同时段下,可能承载完全不同的业务含义。本节围绕Market Data Snapshot、Incremental Refresh、Trade、Quote、Order Book五类核心消息,梳理其语义边界、字段结构与解析要点。

一、核心原理:行情消息的语义分层

FIX行情消息本质上分为三个语义层:快照层、增量层和事件层。快照层用于建立初始状态,增量层用于维护状态变化,事件层用于表达瞬时成交或报价行为。理解这三层,是避免“把增量当快照”或“把Trade当Quote”的关键。

  • Market Data Snapshot(快照):MsgType=W,携带某时刻完整订单簿或报价集合,通常用于首次订阅或断线重连后的状态重建。
  • Incremental Refresh(增量刷新):MsgType=X,只携带发生变化的价位或条目,需与本地缓存合并,不能独立使用。
  • Trade(成交):MsgType=AE或部分市场的Trade消息,表达已成交事件,具有时间戳和成交量,通常不改变订单簿深度。
  • Quote(报价):MsgType=S或市场自定义,表达做市商双边报价,关注Bid/Ask价格与数量,而非成交。
  • Order Book(订单簿):不是单一消息,而是由Snapshot与Incremental共同维护的聚合状态,包含多档价位与订单队列。
关键判断:收到MsgType=X时,必须先确认本地是否已有该Symbol的Snapshot。若没有,增量消息应丢弃或触发重新订阅,否则会得到错误的订单簿。

二、方法流程:从消息到订单簿的解析链路

实际接入中,解析链路通常遵循“识别消息类型 → 提取关键字段 → 更新本地状态 → 对外发布”的流程。以下以订单簿维护为例,给出典型处理顺序:

  1. 解析MsgType,区分W、X、AE、S等类型。
  2. 提取Symbol、MDEntryType、MDEntryPx、MDEntrySize、MDEntryPositionNo等字段。
  3. 对Snapshot:清空本地订单簿,按价位重建。
  4. 对Incremental:按MDUpdateAction(0=新增、1=修改、2=删除)更新对应价位。
  5. 对Trade:记录成交价、成交量、成交时间,不修改订单簿深度。
  6. 对Quote:更新Bid/Ask报价,注意区分报价与成交。
35=X|268=2|279=0|269=0|270=102.35|271=500|290=1
35=X|268=2|279=0|269=1|270=102.37|271=300|290=2
35=AE|55=AAPL|31=102.36|32=200|60=20240521-14:30:00.123

上述日志中,第一、二行是Incremental Refresh,分别更新买一和卖一;第三行是Trade,仅记录成交,不改变订单簿。若把Trade误当作Incremental处理,会导致订单簿深度被错误覆盖。

行情消息语义分层与订单簿维护 快照层 Snapshot MsgType=W 全量订单簿/报价 用于状态重建 增量层 Incremental MsgType=X MDUpdateAction 新增/修改/删除价位 事件层 Trade/Quote MsgType=AE / S 成交事件 / 双边报价 不直接改深度 本地订单簿 Order Book Bid1 102.35 x 500 Ask1 102.37 x 300 由 Snapshot + Incremental 共同维护 Trade/Quote 仅作为事件记录,不参与深度合并

三、案例场景:断线重连后的状态恢复

假设某做市商系统在14:30:00断线,14:30:05重连。此时若直接接收Incremental Refresh,本地订单簿仍停留在断线前状态,会丢失5秒内的价位变化。正确做法是:重连后先请求Snapshot,收到W消息后重建订单簿,再开始处理X消息。

14:30:05 发送 MarketDataRequest (35=V, 263=1 快照)
14:30:05 收到 35=W 快照,重建订单簿
14:30:06 收到 35=X 增量,正常合并
14:30:06 收到 35=AE 成交,记录事件
实践建议:在会话层维护“Snapshot已就绪”标志位。只有该标志为true时,才允许Incremental消息进入订单簿合并逻辑。

四、误区与复盘:常见解析错误

误区表现后果修正
把Trade当Incremental用成交价覆盖订单簿价位深度错乱,买卖价倒挂按MsgType分流处理
忽略MDUpdateAction所有增量都按新增处理价位重复累积区分0/1/2动作
未等Snapshot就合并增量先到,快照后到状态被覆盖或丢失设置就绪标志位
Quote与Trade混用把报价当成交统计成交量虚高按语义分别入库
忽略MDEntryPositionNo多档价位顺序错乱盘口排序错误按位置号排序
复盘要点:行情解析的绝大多数Bug,根源不在字段解析,而在消息语义误判。建议在接入初期,对每类MsgType单独打日志,观察其字段组合与到达顺序,再编写合并逻辑。