2. 金融市场微观结构基础
在Tick事件回放与撮合仿真中,真正决定“谁先成交、以什么价格成交”的,不是K线,也不是指标,而是订单簿与撮合规则。理解微观结构,是后续实现回放引擎、复现交易所行为、验证策略滑点的前提。本节围绕订单簿、买卖盘、限价单、市价单以及价格优先、时间优先原则展开,建立可落地的撮合认知模型。
一、核心原理:订单簿是市场的“实时供需账本”
订单簿(Order Book)是交易所维护的、按价格与时间组织的未成交订单集合。它分为买方(Bid)与卖方(Ask)两侧,每一侧都是按价格排序的队列。买盘最高价称为最优买价(Best Bid),卖盘最低价称为最优卖价(Best Ask),两者之差为买卖价差(Spread)。
订单簿的核心结构可以概括为:
- 价格档位(Price Level):同一价格的订单聚合为一个档位,记录该价位的总数量与订单队列。
- 队列顺序:同一价格内,订单按到达时间先后排列,先到者优先成交。
- 深度(Depth):档位数量越多,代表该价位流动性越厚,价格冲击越小。
买卖盘并非静态快照,而是随每笔新增、撤单、成交事件动态变化。Tick级回放的本质,就是按时间顺序重放这些事件,并让本地订单簿与交易所状态保持一致。
二、限价单与市价单:两种基本订单类型
限价单(Limit Order)指定价格与数量,只有市场价格达到或优于该价格时才成交。它进入订单簿后成为“挂单”,为市场提供流动性。市价单(Market Order)只指定数量,不指定价格,要求立即以当前最优对手价成交,消耗订单簿流动性。
| 对比维度 | 限价单 | 市价单 |
|---|---|---|
| 是否指定价格 | 是 | 否 |
| 成交确定性 | 价格确定,成交不确定 | 成交确定,价格不确定 |
| 对订单簿影响 | 增加深度,提供流动性 | 消耗深度,提取流动性 |
| 典型风险 | 未成交、排队靠后 | 滑点、部分成交 |
在撮合仿真中,限价单需要插入对应价格档位的队列尾部;市价单则从对手方最优档位开始逐档吃单,直到数量耗尽或对手盘清空。
三、成交规则:价格优先、时间优先
绝大多数交易所采用“价格优先、时间优先”原则:
- 价格优先:买方出价越高越优先,卖方出价越低越优先。
- 时间优先:同价格下,先到达的订单先成交。
当新订单与对手方订单价格交叉时,立即触发撮合。例如,新买入限价单价格 ≥ 最优卖价,则以最优卖价成交;若数量大于该档位,则继续吃下一档,直到价格不再满足或数量耗尽。
撮合核心逻辑(伪代码):
function match(order):
if order.side == BUY:
while order.qty > 0 and asks not empty:
best = asks.best() # 最低卖价
if order.type == LIMIT and order.price < best.price:
break # 限价单价格不满足,停止
trade_qty = min(order.qty, best.qty)
execute(trade_qty, best.price)
order.qty -= trade_qty
best.qty -= trade_qty
if best.qty == 0:
asks.pop()
if order.type == LIMIT and order.qty > 0:
bids.insert(order) # 剩余挂入买盘
# 卖方向对称处理
这段逻辑是后续Tick回放引擎的核心。回放时,每一笔新增订单、撤单、成交事件都要按时间戳顺序驱动该状态机,才能复现真实盘口变化。
四、案例与场景:一笔市价买单如何吃掉卖盘
假设当前卖盘为:100.51×200、100.52×400、100.53×600。现在来了一笔市价买入 800 手:
- 先吃 100.51 的 200 手,剩余 600 手;
- 再吃 100.52 的 400 手,剩余 200 手;
- 最后吃 100.53 的 200 手,剩余 0 手,成交结束。
成交均价约为 (200×100.51 + 400×100.52 + 200×100.53) / 800 ≈ 100.52。若该订单是限价 100.52 买入 800 手,则在 100.53 档位前停止,剩余 200 手挂入买盘 100.52 排队。
回放要点:真实Tick数据中,成交事件往往只给出价格与数量,不直接给出订单ID。仿真时需要用“价格优先、时间优先”反推队列消耗顺序,才能让本地订单簿与行情快照对齐。
五、常见误区与复盘
- 误区一:把盘口一档当作全部流动性。市价单可能吃穿多档,滑点来自深度不足,而非单一价格。
- 误区二:忽略时间优先,认为同价随机成交。同价位队列顺序决定成交先后,回放时必须维护队列。
- 误区三:用K线收盘价模拟成交。Tick级撮合必须使用订单簿最优价与逐档消耗,否则回测结果失真。
- 误区四:撤单事件处理滞后。撤单会改变队列与深度,若未按时间戳处理,盘口会与真实快照偏离。
复盘建议:每完成一段回放,将本地订单簿的最优买卖价与行情快照对比。若持续偏离,优先检查:事件时间戳排序、同价位队列插入位置、市价单吃单深度、撤单是否及时移除。
掌握订单簿、买卖盘、限价单、市价单与价格优先时间优先原则后,下一阶段即可将这些规则编码为撮合状态机,并在Tick事件流中逐笔驱动,实现可验证的撮合仿真。