撮合引擎:交易所是怎么把买单卖单凑成一笔交易的 书架

第 06 章 / 共 12 章

第六章 · 下单方式全家桶

订单类型不是新引擎,是引擎的旋钮

第五章结尾埋了个伏笔:绝大多数"订单类型"只是撮合循环的参数。这一章把真实交易所的下单方式过一遍。每讲一种,我们都问同一个工程问题:它改了循环的哪一部分?看完你会发现,一张看起来吓人的下单表单,拆开来不过四五组旋钮。

第一组旋钮:剩余量怎么办(时效指令)

第五章说过,循环停下来时的剩余处理分出了流派。这组指令叫时效指令(time-in-force),回答"这张单活多久、剩了怎么办":

工程实现:GTC什么都不用加;IOC是循环结束后把剩余丢弃而非入簿;FOK是循环前加一次"干跑"(只算不成交),量够再真跑。FOK有个坑:干跑和真跑之间不能有别的订单插进来改变簿子——这逼你接受一个原则,撮合必须串行,这是第十一章单线程架构的第一块基石。

第二组旋钮:只许挂,不许吃

Post-only(只做挂单方):订单进门时检查——如果它此刻会成交,直接拒单(有的交易所选择把价格自动挪开一格)。为什么有人要这个?因为交易所给挂单方(maker)手续费返佣、向吃单方(taker)收费(第八章详谈),大玩家绝不允许自己"一不小心成了taker"——那等于本来收钱变成交钱。Post-only是把"我一定排队"写成了硬约束。

第三组旋钮:先藏着,等信号——条件单

前面所有单都是进门就进撮合。止损单(stop order)不一样:它进门后先睡一觉,不进簿子,只登记一个触发价。等市场最新成交价碰到触发价,它才醒来,变成一张普通订单冲进撮合循环。醒来的姿势又分两派:

工程实现:撮合引擎旁边多一个触发器——每笔成交产生后,拿最新价去扫一遍沉睡的止损单列表,把被触发的唤醒成普通订单重新进门。注意触发源通常是"本所最新成交价",这就有一个微妙的顺序问题:一笔成交既改变簿子,又可能唤醒新订单,新订单再改变簿子——事件链条必须严格按序处理,又是串行的理由。

第四组旋钮:别让人看见我的底牌——冰山单

大单挂出来会吓坏市场:墙上突然出现10万股的买单,所有人都会调整行为。冰山单(iceberg order)的办法是:总量10万股,但墙上只露1000股(叫"峰值量");露出来的1000股被吃掉,引擎自动从水下再补1000股上来,直到总量耗尽。露出来的部分正常排队,水下部分别人看不见。

工程实现上有两个点要想清楚。一是补单时的队位:新补的1000股是一张"新单",按第三章的规则应该重新排到这个价位的队尾——所以冰山单在排队上是吃亏的,这是隐藏自己的代价。二是成交优先级:同一价位上,完全显露的单和冰山的显露部分怎么排,各交易所规则不同,写之前要定死。

一张表收拢全章

GTC → 剩余入簿;IOC → 剩余丢弃;FOK → 进门前先干跑验量;Post-only → 进门前检查是否成交,成交则拒;止损 → 先睡,被成交价唤醒再进门;冰山 → 入簿只入峰值,吃光自动补。

六种旋钮,没有一种动了第五章那个核心循环。它们改的是:进门前的检查(FOK、post-only)、进门的时间(止损)、入簿的量(冰山)、剩余的去向(IOC)。这就是设计订单类型的方法论:新类型必须能表达成对现有流程的一个明确修改点,说不清楚的类型不做。

真实交易所的表单里还有更花哨的——移动止损、OCO(二选一单)、TWAP切片——但它们要么是上面旋钮的组合,要么是交易所之外的策略层(客户端或券商系统)做的事,不属于撮合引擎本体。分清"引擎该管的"和"策略层该管的",是交易所架构里最重要的边界之一。

下一章换个场景:当市场还没开门、没有买一卖一的时候,第一笔价格是怎么产生的?

撮合引擎:交易所是怎么把买单卖单凑成一笔交易的 · 王建硕
费曼式写法 · 由多个 AI 代理撰写与互相审校