2. Level2行情基础
在Level2行情一致性校验的实战中,第一步不是写代码,而是把三类核心数据的“身份”搞清楚:逐笔成交、逐笔委托、快照行情。它们分别回答“已经发生了什么”“市场想做什么”“某一瞬间市场长什么样”。如果对字段含义和交易所规范理解偏差,后续所有校验都会建立在错误前提上。
一、三类行情数据的核心定位
逐笔成交是交易所撮合引擎产生的成交回报,记录每一笔真实成交的价格、数量、买卖方向及成交类型。逐笔委托是订单进入撮合队列前后的委托明细,反映买卖双方的意图和撤单行为。快照行情则是按固定时间间隔(如沪深交易所通常为3秒)对订单簿进行切片,给出最优买卖档位及汇总统计。三者关系可以概括为:逐笔委托驱动订单簿变化,逐笔成交消耗订单簿,快照是订单簿在时间轴上的采样。
二、逐笔成交与逐笔委托的字段含义
沪深交易所的逐笔数据字段命名略有差异,但核心语义一致。以下以通用字段为例说明:
| 字段 | 所属类型 | 含义 | 校验意义 |
|---|---|---|---|
| SeqNum | 逐笔成交/委托 | 交易所内部连续序号 | 检测丢包、乱序 |
| OrderNo | 逐笔委托 | 委托订单编号 | 与成交记录关联 |
| Price | 逐笔成交/委托 | 价格(元) | 价格合法性、涨跌停 |
| Qty | 逐笔成交/委托 | 数量(股/手) | 数量守恒校验 |
| Side | 逐笔成交/委托 | 买卖方向 | 方向一致性 |
| TradeType | 逐笔成交 | 成交类型(成交/撤单) | 区分真实成交与撤单 |
| BidPrice/AskPrice | 快照 | 最优买/卖价 | 与逐笔重建比对 |
上交所逐笔委托中,撤单表现为一条独立的撤单记录,其 OrderNo 指向被撤委托;深交所则在逐笔委托中通过 ExecType 字段区分。校验时必须按交易所分别处理,不能混用。
三、快照行情的结构与采样逻辑
快照行情通常包含:时间戳、最新价、成交量、成交额、十档买卖价格与数量、买卖委托总数等。它的关键特征是“离散采样”,即每3秒对订单簿拍一张照片。因此快照之间可能发生大量逐笔事件,但快照本身不记录这些中间过程。
一致性校验的核心思路是:用逐笔委托和逐笔成交重建订单簿,再在快照时间点上与交易所发布的快照进行比对。如果重建结果与快照在最优价、档位数量、累计成交量上出现偏差,就说明逐笔数据存在丢失、重复或字段解析错误。
# 快照重建伪代码示例
for snapshot in snapshots:
target_time = snapshot.timestamp
while tick.time <= target_time:
if tick.type == "order":
order_book.apply_order(tick)
elif tick.type == "trade":
order_book.apply_trade(tick)
rebuilt = order_book.get_top10()
assert rebuilt.bid_price[0] == snapshot.bid_price[0]
assert rebuilt.ask_price[0] == snapshot.ask_price[0]
assert rebuilt.total_volume == snapshot.total_volume
四、典型误区与复盘
- 误区一:把逐笔委托当成逐笔成交。逐笔委托包含未成交的挂单和撤单,只有逐笔成交才是真实撮合结果。混用会导致成交量虚高。
- 误区二:忽略交易所字段差异。上交所和深交所的逐笔委托字段名、撤单表示方式、序号规则均不同,直接套用同一套解析逻辑必然出错。
- 误区三:快照时间戳对齐不严谨。快照时间戳通常为交易所生成时间,而逐笔数据带有本地接收时间。若用本地时间对齐,会引入网络延迟误差,导致重建结果与快照错位。
- 误区四:忽略集合竞价阶段。开盘前和收盘前的集合竞价阶段,逐笔数据行为与连续竞价不同,快照也可能不更新,校验时需单独处理。
实战中建议先做“序号连续性检查”,再做“逐笔重建快照比对”。如果序号本身就有跳变,后续所有一致性结论都不可信。先定位丢包,再谈一致性。