上手术台
前四章把零件都摆出来了:订单簿是价格台阶加排队,限价单排队,市价单扫墙。这一章把它们装在一起,回答全书最关键的一个问题:一张新订单进门之后,撮合引擎的每一行逻辑到底做什么?
答案是一段循环,行话叫撮合循环(matching loop)。先记住它的伪代码,然后我们逐行解剖:
while 新订单还有剩余量:
看对面墙顶(买单看卖一,卖单看买一)
if 对面没单了,或价格碰不上: break
和队首那张单成交,价格取对面那张单的价
成交量 = min(双方剩余量),双方各扣掉
对面那张如果扣完,从队列移除,换下一张队首
循环结束后:if 新订单还有剩余: 按规则处理剩余
就这些。全部撮合引擎——从纳斯达克的到一个小币所的——核心都是这段循环的变体。魔鬼在四个细节里。
细节一:什么叫"价格碰得上"
对限价买单,"碰得上"= 卖一价 ≤ 你的限价。你限价10.02买,卖一10.01,碰上;卖一涨到10.03,碰不上,循环停。限价卖单对称:买一价 ≥ 你的限价。市价单没有限价,永远碰得上,直到对面被扫空。
注意这个判断是在循环每一圈重新做的。你限价10.02买1500股,10.01吃了600、10.02吃了500,下一格10.03——碰不上了,循环停,剩400股按10.02挂进买方队列,成为新的买二。限价既是你的成交条件,也是你的刹车。
细节二:成交价取谁的价——为什么总是"墙上那张"的价
上面伪代码里加粗的那句,是整个撮合里最容易被写错、也最体现规则哲学的地方:成交价取被动方(先挂在墙上的那张单)的价格,不取新来那张的价格。
例子:卖一10.01挂着,你限价10.02买。成交价是10.01,不是你出的10.02。你本来愿意多付一分,市场只收你10.01——你占了便宜。反过来,你挂10.00买在墙上,有人市价卖下来,成交价10.00,你的价。
为什么必须这样?两个理由。一是奖励提供流动性的人:先把订单挂上墙的人承担了风险和等待,规则把"价格改善"的好处给后到的主动方,墙才有人愿意贴。二是确定性:墙上那张单的价格是公开的、先来就定的,成交价取它,所有人事前都能算出自己会按什么价成交;如果取新单的价,等于成交价由后来者临时决定,墙就失去了承诺的意义。
大白话:成交价永远由"先到的、挂在墙上的那张单"说了算。后到的人要么接受,要么不成交。这让挂单者的承诺是硬承诺,也让规则简单到没有第二种解释。
细节三:部分成交是常态,不是异常
新单1500股,对面队首只有600股——成交600,对方离场,你的单剩900继续循环。反过来,对面队首有5000股,你1500股全部成交离场,对方剩3500股保留原队位继续排头(第三章的规则)。
所以一笔订单的"生命周期"不是"成交/没成交"两态,而是:剩余量从初始一路被削,每削一刀产生一笔成交记录(trade)。一张大单打进来,可能产生几十笔成交,每笔的对手、价格、数量都不同。你的系统里,成交记录和订单是两张表:订单记录"还想要多少",成交记录记"已经发生了什么"。这个区分到第九章讲回报流时还会回来。
细节四:剩余怎么办——这里分出所有订单流派
循环停下来时,新订单可能还有剩余。怎么办?这不是一个答案,而是一组答案,每种答案是一种订单类型(第六章详述):
- 剩余挂进簿子:变成普通限价单排队——这是默认行为(GTC)。
- 剩余撤掉:能成交多少算多少,剩下的不要了(IOC)。
- 要么全成要么全退:进门前先算一遍够不够全吃,不够直接拒绝(FOK)。
- 不许成交,只许挂:进门时若能成交,直接拒单(post-only)。
看见了吗:所谓"订单类型",绝大多数只是撮合循环结束条件和对剩余量的处理方式不同。核心循环不用改。这是写撮合引擎时最值得领悟的一点——先写死一个干净的循环,再让订单类型成为循环的参数。
一个完整算例,逐秒走完
卖侧簿子:10.01有A的600股(先到)、B的400股;10.02有C的500股。买侧先不管。现在D下单:限价10.02买入1200股。
- 循环第1圈:卖一10.01 ≤ 10.02,碰上。队首A,成交600股 @ 10.01(A的价)。A离场。D剩600。
- 第2圈:卖一还是10.01(B顶上成为队首)。成交400股 @ 10.01。B离场。D剩200。
- 第3圈:卖一变成10.02,≤ 10.02,碰上(限价是"最多出",相等也算碰上)。队首C,成交200股 @ 10.02。D剩0,循环结束。
- D三笔成交:[email protected] + [email protected] + [email protected],均价约10.0117。C的卖单剩300股继续排10.02队首,新卖一仍是10.02。
把这段在脑子里跑通,你就已经理解了一个撮合引擎80%的工作。
细节五:自己跟自己成交,行吗
还剩一个工程上必须回答的问题:如果一个账户的买单撞上了它自己的卖单呢?这叫自成交(self-trade)。听起来无害,但它能被用来刷成交量、制造假行情(对倒,wash trading),在受监管市场是明令禁止的。所以撮合循环里通常加一道自成交防护(STP):发现对面队首是同一个人的单,按预设策略处理——撤新单、撤旧单、或两边都撤。这又是一颗挂在循环上的可选参数。第八章对比各交易所时会看到它们的不同选择。
循环讲完了。下一章我们把这些"参数"一个一个装上,看看真实交易所提供的下单方式全家桶。