3. 订单簿结构与价格优先时间优先
集合竞价的撮合结果,最终由订单簿这一数据结构决定。理解订单簿的组成与排序规则,是读懂虚拟成交价、判断撮合顺序、乃至自行解析行情快照的前提。本节从订单簿的静态结构出发,讲清买卖盘的排序逻辑,再落到价格优先与时间优先的具体实现,最后给出订单簿快照的读取与解析方法。
订单簿的组成:两个方向、两个维度
订单簿(Order Book)本质上是按价格分档组织的委托集合。它有两个方向:买方(Bid)与卖方(Ask);每个方向又有两个维度:价格档位与档位内的委托队列。任一时刻,订单簿可以抽象为:
- 买盘:若干价格档,价格从高到低排列,每档记录该价位的委托总量与委托笔数;
- 卖盘:若干价格档,价格从低到高排列,每档同样记录总量与笔数;
- 档内队列:同一价格上的多笔委托,按进入撮合系统的时间先后排成队列。
需要强调的是,订单簿里存的是“尚未成交的剩余委托”,而不是原始下单流水。一笔委托部分成交后,剩余数量仍留在原档位、原队列位置,只有全部成交或撤单才从订单簿中移除。这一点在集合竞价阶段尤其重要:竞价期间不产生连续成交,订单簿只增不减(除撤单外),因此快照反映的是“累积的意向”。
买卖盘的排序规则
两个方向的排序方向相反,但遵循同一条原则——对撮合越有利的委托排在越前面。买盘价格越高,越愿意成交,排在前;卖盘价格越低,越愿意成交,排在前。于是买盘按价格降序、卖盘按价格升序,最优买价(买一)与最优卖价(卖一)分别位于两侧的队首。
档内队列则按时间排序:先进入撮合系统的委托排在队首。这里有一个容易被忽略的细节——时间优先比较的是“进入撮合系统的时间”,而不是投资者点击下单的时间。经过经纪商前置、交易所网关后,委托到达撮合引擎的先后才是有效的时间戳。同一毫秒内到达的委托,通常按网关接收顺序或系统分配的序号进一步区分。
价格优先与时间优先的具体实现
把规则落到实现上,可以拆成“排序键”和“匹配循环”两部分。每笔委托携带两个排序键:价格键与时间键。价格优先意味着价格键是主键,时间优先意味着时间键是次键。以买盘为例,排序比较可写成:价格高者优先;价格相同时,时间早者优先。卖盘则价格低者优先,其余相同。
撮合时的匹配循环遵循“取两侧队首、比较价格、能成交则配对”的逻辑:取买一与卖一,若买一价 ≥ 卖一价则成交,成交量取两者剩余量的较小值,成交后更新队首剩余量,耗尽则弹出该委托、露出下一笔;若买一价 < 卖一价则停止。这个循环在连续竞价中逐笔触发,在集合竞价中则在竞价结束时统一执行一次,从而产生单一成交价。
// 撮合匹配循环(示意,买盘降序、卖盘升序)
while (bestBid.price >= bestAsk.price) {
qty = min(bestBid.remaining, bestAsk.remaining);
recordTrade(bestBid, bestAsk, qty); // 记录成交
bestBid.remaining -= qty;
bestAsk.remaining -= qty;
if (bestBid.remaining == 0) popBid(); // 队首耗尽,露出下一笔
if (bestAsk.remaining == 0) popAsk();
}
这段伪代码体现了两个优先级的协作方式:外层 while 条件由价格优先决定“能否成交”,内层弹出顺序由时间优先决定“谁先成交”。理解这一点,就能解释为什么同一价位上大单可能排在后面却先成交——它进入得早。
订单簿快照的读取与解析
实盘中我们拿不到完整订单簿,只能拿到行情快照。快照通常包含:快照时间、买一至买N的价格与数量、卖一至卖N的价格与数量,部分市场还提供档位委托笔数。解析快照时要注意三件事:
- 校验排序方向:买盘价格应严格递减,卖盘应严格递增,若出现乱序说明数据异常或字段错位;
- 识别空档与零量:某档数量为 0 表示该价位已无委托,不能当作有效档位参与计算;
- 区分快照与逐笔:快照是某一时刻的切片,两次快照之间的队列变化需靠逐笔委托或成交数据还原。
以一份示例快照为例(数据为教学假设):买盘 10.02 元 500 手、10.01 元 800 手、10.00 元 1200 手;卖盘 10.03 元 600 手、10.04 元 400 手、10.05 元 900 手。解析后可判断:最优买价 10.02 低于最优卖价 10.03,当前无连续成交可能;若这是集合竞价末段快照,则虚拟成交价将落在 10.02 与 10.03 之间,具体取决于两侧累积量的交叉点。这正是下一节虚拟成交价计算要处理的问题。
把上述结构记牢,后续计算虚拟成交价时,只需在买盘降序、卖盘升序的序列上做累积量比较,就能快速定位交叉点。订单簿不是静态表格,而是带时间维度的队列集合——价格决定“在哪一档”,时间决定“在档内第几位”,两者共同决定了撮合顺序。