1. 规则验证导入
在任何一个集中撮合的交易系统中,订单能否成交、以什么价格成交、与谁成交,最终都由两条最基础的排序规则决定:价格优先与时间优先。这两条规则看似简单,却是整个撮合引擎的“宪法”——所有撮合逻辑、行情快照、成交回报、甚至风控与清算的输入,都建立在它们之上。本节作为整门课程的起点,先把这两条规则讲清楚,再说明它们在撮合系统中的位置,最后给出本课程要验证什么、以及沿着什么路径去验证。
一、两条规则的精确定义
价格优先指的是:在买单方向,出价越高的订单优先级越高;在卖单方向,要价越低的订单优先级越高。换句话说,对买方而言“愿意多付钱”的订单先成交,对卖方而言“愿意少收钱”的订单先成交。这条规则保证了市场在任一时刻总是先满足对价格最让步的一方,从而使成交价格尽可能接近最优。
时间优先指的是:当两个订单的价格完全相同时,先进入撮合系统的订单优先级更高。这里的“时间”不是客户端点击按钮的本地时间,而是订单被撮合引擎接收并进入订单簿的时点。这一点非常关键:网络延迟、柜台排队、网关处理都会影响最终到达引擎的先后,因此验证时必须明确“时间”的参照点是引擎侧而非客户端侧。
两条规则合起来构成一个二级排序键:先按价格排序,价格相同再按到达时间排序。用伪代码表达订单簿中某一方向的排序逻辑,大致如下:
// 买单队列:价格降序,同价按到达序号升序
sort(buyOrders, key = (-price, arrivalSeq))
// 卖单队列:价格升序,同价按到达序号升序
sort(sellOrders, key = ( price, arrivalSeq))
其中 arrivalSeq 是撮合引擎为每笔订单分配的单调递增序号,它比时间戳更可靠,因为同一毫秒内可能有多笔订单到达,序号能给出确定的先后关系。这也是后续验证中判断“时间优先是否被正确执行”的核心依据。
二、在撮合系统中的核心地位
价格优先与时间优先并不是孤立的两条规则,它们直接决定了撮合引擎的几个关键输出:成交价格(通常取被动方即先挂单方的价格)、成交量分配(同价时先到者先被吃掉)、订单簿剩余结构(哪些订单留在簿上、排在什么位置)、以及行情快照中的买卖档位。一旦排序出错,表面上可能只是某笔成交归属不同,实际上会连锁影响成交回报、持仓、资金结算和行情展示,属于典型的“底层错、全链错”。
下图把两条规则在撮合链路中的位置、以及它们对下游输出的影响关系梳理出来,作为本节的结构性总览:
从图中可以看到,排序键位于“引擎接收”与“订单簿”之间,是整条链路的枢纽。验证工作因此不是去测某个界面按钮,而是围绕这个枢纽构造输入、观察订单簿与成交结果,判断排序是否严格按“价格→时间”执行。
三、验证目标:我们到底要证明什么
本课程的验证目标可以归纳为三个层次。第一层是规则正确性:给定一组可预期的订单序列,撮合结果是否与手工推演一致。例如卖一价为 10.00、数量 100,此时来一笔买价 10.00、数量 150 的订单,应成交 100,剩余 50 转为买一挂在 10.00;若同时还有另一笔更早到达的同价买单,则先到者应先被满足。第二层是边界与并发正确性:同价多笔订单几乎同时到达时,arrivalSeq 是否稳定、是否出现“后到先成交”;部分成交后剩余订单在队列中的位置是否正确;撤单后同价队列是否保持原有相对顺序。第三层是可观测性:成交回报中的成交价、成交量、对手方信息,以及行情快照的档位,是否能反推出排序行为,从而让验证有据可查。
arrivalSeq 为准,序号小者为先。所有推演和断言都基于这一约定,避免因参照系不一致导致误判。四、整体学习路径
围绕上述目标,本课程按“先建立模型、再构造用例、后判读结果”的顺序展开。首先把订单簿的排序模型和撮合匹配过程讲透,明确价格优先与时间优先在每一档、每一笔上的具体表现;然后进入用例设计,学习如何用少量但覆盖关键分支的订单序列,去触发同价竞争、部分成交、跨档扫单、撤单重排等场景;接着是结果判读,把成交回报与订单簿快照对照,形成“预期—实际—差异”的判断方法;最后通过若干综合案例与常见错误模式,把规则验证固化为可复用的检查思路。
需要强调的是,验证不是“跑一遍看看有没有报错”,而是先写出预期,再比对实际。例如构造如下一组示例订单(数值为教学假设,非实测):
| 序号 | 方向 | 价格 | 数量 | 预期行为 |
|---|---|---|---|---|
| 1 | 卖 | 10.00 | 100 | 挂入卖一 |
| 2 | 卖 | 10.00 | 200 | 排在序号1之后,同价时间优先 |
| 3 | 买 | 10.00 | 150 | 先吃序号1的100,再吃序号2的50 |
| 4 | 买 | 10.01 | 80 | 价格优先,直接吃剩余卖单 |