2026-04-22 · architecture / fintech
【金融科技工程】撮合引擎实现:撮合算法、价格优先时间优先、状态机、低延迟工程
深入剖析中央限价订单簿(CLOB)撮合引擎的数据结构与算法,覆盖价格时间优先、Pro-Rata、订单类型、自成交预防、集合竞价、确定性回放、WAL 快照、单线程事件循环与 Disruptor 模型,并给出 Rust/Go 简化实现与单元测试清单。



























在前面的十四篇里,我们从钱的建模、复式记账、账务数据库,一路走到了支付、清算、跨境、央行系统、数字货币。这些系统的共性是:围绕”一笔一笔付款”展开——谁付谁、金额多少、什么时间到账。而从本篇开始,系列进入另一条主线:交易所(Exchange)与市场基础设施。
交易所的工程难度和支付系统不在一个量级。一个支付网关做到 1 万 TPS(交易/秒)已经足以处理双 11,而纽交所(NYSE)Pillar、纳斯达克 INET、上交所新一代交易系统、芝加哥商品交易所 CME Globex 的撮合引擎在峰值时每秒要处理数百万笔订单,端到端延迟必须压到几十微秒到几纳秒。币安(Binance)现货引擎在 2021 年牛市日均成交额超 760 亿美元,单对 BTC/USDT 一个交易对在极端行情下每秒几万笔订单,全市场上千个交易对并行撮合。这背后是一整套从 FPGA、内核旁路(Kernel Bypass)、无锁队列(Lock-free Queue)、精确时钟同步(PTP)到跨机房复制的系统工程。
更关键的是,交易所的错误是不可逆的。一笔支付错了还能退款、冲正;一笔成交一旦进入清算链路,已经在登记结算机构落账,撤销的代价是惊动监管、赔偿对手方、修改当日结算文件。2012 年骑士资本(Knight Capital)因一行上线脚本漏掉了八台服务器之一的旧代码,在 45 分钟内向市场发出 400 万笔错误订单,账面亏损 4.4 亿美元,公司当周破产被收购。这是工程事故写入 MBA 教科书的少数案例之一。
本篇面向三类读者:
本篇是”全景图”,后续 16(撮合引擎深度)、17(行情分发)、18(登记结算)会分别下钻到具体子系统。
无论是 1792 年梧桐树下的纽交所,还是 2017 年诞生的币安,任何一家交易所从工程视角看,都由五个核心子系统构成。它们的边界清晰,职责单一,且基本是顺序级联的。
| 子系统 | 英文 | 职责 | 延迟敏感度 | 对应后续文章 |
|---|---|---|---|---|
| 订单网关 | Order Gateway / OMS | 客户端接入、协议转换、前置风控、订单分发 | 高(μs 级) | 本篇 |
| 撮合引擎 | Matching Engine | 订单簿维护、价格时间优先撮合、生成成交 | 极高(ns 级) | 第 16 篇 |
| 行情系统 | Market Data | L1/L2/L3 行情聚合与分发(MBP/MBO、快照+增量) | 高(μs 级) | 第 17 篇 |
| 清算与风控 | Clearing & Risk | 保证金、持仓、强平、盘中风险监控 | 中(ms 级) | 第 19 篇 |
| 结算与账户 | Settlement & Account | T+N 资金/证券过户、账户余额维护 | 低(分钟/小时) | 第 18 篇 |
这五个子系统在交易所的部署里是串联+分流的关系:客户端的订单顺着订单网关—前置风控—撮合引擎流下来,成交结果分两路——一路实时推给行情系统向市场广播,另一路进入清算风控打保证金、更持仓,再进结算系统在日末完成登记过户。
这张图的要点:撮合引擎是唯一不能水平扩展的核心(每个交易对一个 shard,内部单线程、单机),它上下两侧的所有其它组件——网关、行情、风控、结算——都可以水平扩展,因而交易所的容量瓶颈永远在撮合层。
一条订单从客户端进入、到撮合完成、到行情对外分发、到日终结算完成,跨越六个数量级的时间尺度,这是非常独特的系统特征:
设计交易所的核心经验是:把同步热路径做短,把异步冷路径做厚。订单—撮合—成交回报这条链路必须是纳秒级的纯内存操作,而保证金扣减、PnL 重算、资金清分这些可以并发、可以延迟、可以在 T+1 才落地。这和一般业务系统”请求来了一把梭”的做法完全相反。
订单网关(Order Gateway,习惯上也叫 OMS 或简称 OG)是客户端流量进入交易所的第一站,它的职责可以归纳为六条:
| 协议 | 典型用户 | 特点 |
|---|---|---|
| FIX(Financial Information eXchange) | 投行、券商、基金 | ASCII 文本、Tag=Value、会话型、广覆盖、但解析慢 |
| FIX/FAST、SBE | 低延迟机构 | 二进制编码,解析几十纳秒 |
| OUCH / ITCH | 纳斯达克、多家股票所 | 二进制、定长、极简 |
| WebSocket + JSON | 加密交易所散户 | 易用、跨语言、但单消息数十微秒解析 |
| REST | 非敏感交易(取消、查询) | HTTP/1.1 或 HTTP/2 |
| 私有 TCP | 券商自研柜台 | 定制优化、接入门槛高 |
订单进入 OMS 后会被归一化为一条内部消息:
// order.proto —— 内部统一订单消息
message OrderIn {
uint64 seq_no = 1; // 网关分配全局序号
uint64 session_id = 2; // 席位会话
uint64 cl_ord_id = 3; // 客户端委托号(幂等去重键)
uint32 symbol_id = 4; // 数字化 symbol(减少字符串比较)
enum Side { BUY = 0; SELL = 1; }
Side side = 5;
enum OrdType { MARKET=0; LIMIT=1; STOP=2; STOP_LIMIT=3; ICEBERG=4; PEGGED=5; }
OrdType ord_type = 6;
int64 price_ticks = 7; // 价格用最小报价单位表示的整数
int64 qty = 8; // 数量(股/张/最小单位)
enum TIF { DAY=0; IOC=1; FOK=2; GTC=3; GTD=4; }
TIF tif = 9;
uint64 ts_ns_in = 10; // 网关入站纳秒时间戳
}几个关键设计点:
price_ticks 用整数,不用浮点(参见第 2
篇《钱的建模》);symbol_id 用 32 位整数替代字符串,查表由
OMS 完成;cl_ord_id 是客户端生成的唯一委托号,OMS 按
(session_id, cl_ord_id)
做幂等去重,避免网络重传造成重复下单;ts_ns_in
精确到纳秒,后续全链路的延迟归因都依赖这个基准时间戳。前置风控是交易所和券商共同承担的闸门:在订单进入撮合之前就拒绝明显不合理的委托。典型规则:
2010 年 5 月 6 日美股”Flash Crash”后,美国证监会(SEC)强化了 Market Access Rule(15c3-5),强制要求所有经纪商在订单进入交易所前完成上述风控检查。交易所侧通常也会再做一道,形成两层防护。
为什么要做前置而不是事后?因为撮合一旦成交就不可逆。一笔错单撤单可能需要交易所决策层批准并公告(中国 A 股在极端乌龙指情况下可以取消成交,但流程很重),远不如在撮合前拒绝。
机构客户对撮合延迟极度敏感,但前置风控本身就是几条 if 语句,如果放在 CPU 上经过内核栈要一两微秒,叠加 JIT 不确定性,抖动很大。于是以 Xilinx(现 AMD Xilinx)Alveo 和 Intel(现 Altera)为代表的 FPGA 方案被用来做Wire-speed 风控:
国内上交所在 2019 年新一代交易系统切换时也部分引入了 FPGA 加速,用于行情组播下发和部分校验环节。国外诸如 Jump Trading、Citadel Securities、Virtu Financial 的核心风控与撮合对接几乎全部 FPGA 化。
撮合引擎(Matching Engine)是交易所最核心、最不能扩展、也最令工程师着迷的组件。本篇只做全景概述,第 16 篇会把算法、数据结构、重放、灾备完整展开。
撮合引擎接收来自订单网关的合法订单,维护一个或多个订单簿(Order Book),按预定义的撮合规则生成成交(Trade),并把新订单变化和成交以事件流方式发出,供行情和清算两路订阅。
| 规则 | 别名 | 应用场景 |
|---|---|---|
| 价格时间优先 | Price-Time Priority、FIFO | 绝大多数现货、期货 |
| 价格比例优先 | Pro-rata | 部分利率、短期债券期货 |
| 价格时间 + Top-of-Book 保护 | Price-Time-Pro-rata Hybrid | CME 欧洲美元等 |
| 定盘/集合竞价 | Call Auction | 开盘/收盘、熔断后复牌 |
| 隐藏/冰山处理 | Hidden / Iceberg | 机构大单拆分 |
2011 年,伦敦外汇零售经纪商 LMAX 公开了其核心撮合系统:单机 Java 实现,每秒 600 万笔订单,99% 延迟 < 50 μs。LMAX 的关键架构选择——后来被抽象成开源框架 Disruptor——在此后十年成为低延迟系统的教科书:
volatile 语义发布/获取序号;这六条设计原则几乎被所有现代撮合引擎采纳,包括 CME Globex、纳斯达克 INET、上交所新一代、Binance 撮合引擎(C++)、Deribit、FTX(已破产,但其撮合引擎代码公开片段仍广被引用)。
常用实现是价格层有序容器 + 每层 FIFO 双向链表:
TreeMap<price, Level>
或数组+跳表;加密交易所常用
std::map<int64_t, PriceLevel>;intrusive list<Order>,保留插入顺序,成交时从头取;order_id 到节点指针的
hash,支持 O(1) 撤单;第 16 篇会详细比较 B+树、跳表、平衡树、分层数组这几种组织方式在不同品种下的权衡。
sequenceDiagram
autonumber
participant C as 客户端
participant OG as 订单网关
participant R as 前置风控
participant M as 撮合引擎
participant MD as 行情
participant CL as 清算
C->>OG: 新单 BUY 10@100.50
OG->>R: 归一化后转发
R-->>OG: 通过
OG->>M: OrderIn(seq=1001)
M->>M: 遍历卖盘,匹配至 100.50
M-->>MD: Trade 事件(6@100.50)
M-->>MD: BookUpdate(剩余 4@100.50 挂单)
M-->>CL: ExecReport(fills)
M-->>OG: ExecReport 回报
OG-->>C: 成交确认 + 剩余委托
工程上曾有过无数人想让撮合水平扩展——按品种分片很好,但单一品种内部,价格时间优先这件事天然是串行的:任何并行撮合都可能破坏时间优先的公平性,引来监管和交易者的抗议。
因此现代交易所的做法几乎一致:
这也决定了交易所永远要优化的是单核性能,而不是堆核数。Intel 的 Ice Lake、AMD 的 3D V-Cache EPYC、ARM 的 Neoverse 都是被交易所和 HFT 公司竞相采购的核心硬件。
行情系统从撮合引擎订阅事件流,聚合为可对外发布的行情产品,按不同深度和频次分发给订户。第 17 篇会详细展开。
| 级别 | 内容 | 典型用户 |
|---|---|---|
| L1 | 最优买卖一档 + 最新成交 | 散户 App、财经网站 |
| L2(MBP, Market-By-Price) | 买卖 5/10/20 档、每档累计量 | 活跃交易者、量化入门 |
| L3(MBO, Market-By-Order) | 每一条挂单明细(匿名) | 专业做市商、高频策略 |
订阅者先收一份全量快照(Snapshot)建立初始状态,之后用增量(Incremental Update)维护。增量消息序号连续,丢失时订阅者必须请求重传或重新拉一份快照。
Snapshot: BookState @ seq=100000
Incremental: seq=100001 Insert Order(O1, BID, 100.00, 10)
seq=100002 Modify Order(O1, qty=7)
seq=100003 Trade(3@100.00)
...
传统交易所的 L2/L3 行情是付费产品。纳斯达克一年行情营收超 10 亿美元;LSE、德交所、CME 都不便宜。中国 A 股 Level-2 行情由中证报价系统和财经终端分销,专业席位年费数万到数十万。这是交易所除了手续费外最主要的收入来源之一,反过来也决定了行情分发系统的工程完整度——它是”产品”而不是”副产物”。
前置风控负责”不让错单进来”;盘中风控(Intraday Risk)负责”在持仓变化时持续监控账户健康”。对期货和加密衍生品尤其关键:
加密交易所的强平在极端行情下是最容易出事的环节:2021 年 5 月 19 日加密市场单日下跌 30%,Binance、OKX、火币等的强平引擎因订单簿深度不足触发”强平穿仓”,由保险基金补缺,之后演化出自动减仓(ADL, Auto-Deleveraging)机制。
在证券和期货市场,中央对手方(Central Counterparty, Central Clearing)是清算的核心法律构造:买卖双方成交后,CCP “介入”交易,成为所有买家的卖家、所有卖家的买家,承担违约风险。中国的中证登(CSDC)、上海清算所、中金所清算中心,美国的 DTCC、CME Clearing,欧洲的 LCH 都属此类。
CCP 的工程影响:
CCP 的具体工程会在第 18 篇《证券登记结算》展开。
清算子系统不是低延迟系统而是高吞吐、强一致、可审计的系统。典型要求:
技术栈常见组合:撮合事件流(Kafka/Pulsar/内部总线) → 流处理(Flink/自研 C++ 流) → 账务数据库(Oracle/OceanBase/TiDB) → T+1 离线对账(Spark/Hive)。第 19 篇《实时风控引擎》会专门讲其中的规则引擎和特征工程。
“结算(Settlement)”是资金/证券的最终所有权转移,区别于”清算(Clearing)“仅是计算应收应付。第 11 篇已经从通用支付视角讲过清算与结算,本节只补充交易所特有的部分。
| 品种 | 结算周期 | 说明 |
|---|---|---|
| 美股 | T+1(2024-05-28 起,原 T+2) | SEC 规则 15c6-1 修订 |
| 中国 A 股 | 股票 T+1、资金 T+0 可交易、T+1 可取 | CSDC 规则 |
| 中国期货 | 当日结算 T+0 | 每日无负债结算 |
| 加密现货 | 实时(秒级) | 链下记账,实时过户 |
| 加密永续 | 实时 + 资金费率 8h 结算 | Funding Rate |
| CBDC / 稳定币 | 秒级 | 第 14 篇 |
T+1 相对 T+2 缩短了交收期,降低了对手方信用风险,但对机构的资金/借券调度提出更高要求——尤其是跨境套利(美股 T+1、欧股 T+2 错位)。
交易所侧通常不直接保管客户的证券和资金,而是:
| 类型 | 中文 | 语义 |
|---|---|---|
| Market | 市价单 | 以最优对手价立即成交,不保证价格 |
| Limit | 限价单 | 指定价格及以下/以上成交,不成交则挂单 |
| Stop (Stop-Loss) | 止损单 | 达到触发价后转为市价单 |
| Stop-Limit | 止损限价单 | 达到触发价后转为限价单 |
| IOC | 即成即撤 | Immediate-Or-Cancel,未成交部分取消 |
| FOK | 全成或撤 | Fill-Or-Kill,不能全量成交则全撤 |
| GTC / GTD | 长期有效 / 指定日前有效 | Good-Till-Cancelled / Good-Till-Date |
| Post-Only | 仅挂单 | 会吃单成交则撤单(用于赚 maker 返佣) |
并非所有交易所都支持所有类型——例如中国 A 股只支持限价单和市价单两大类,且市价单还有”最优五档即时成交剩余撤销/转限价”等变种;而纳斯达克、NYSE、CME 的订单类型有 50+ 种,TWAP/VWAP 通常不是交易所原生而是券商/算法交易系统层实现的。
stateDiagram-v2
[*] --> New: 客户端提交
New --> Rejected: 前置风控失败
New --> Pending: 网关接受
Pending --> Working: 进入订单簿
Pending --> Rejected: 撮合引擎拒绝(标的无效/涨跌停)
Working --> PartiallyFilled: 部分成交
PartiallyFilled --> PartiallyFilled: 继续部分成交
Working --> Filled: 全部成交
PartiallyFilled --> Filled: 剩余全部成交
Working --> Canceled: 撤单成功
PartiallyFilled --> Canceled: 剩余撤单
Working --> Expired: TIF 到期
PartiallyFilled --> Expired: 剩余到期
Rejected --> [*]
Filled --> [*]
Canceled --> [*]
Expired --> [*]
FIX 把”发生了什么”和”订单当前处于什么状态”分离成两个字段:
ExecType(150):本次事件类型,0 = New, 4 = Canceled, 5 = Replaced, 8 = Rejected, F = Trade, C = Expired, ...OrdStatus(39):订单当前聚合状态,0 = New, 1 = Partially Filled, 2 = Filled, 4 = Canceled, 8 = Rejected, ...这套设计在几乎所有交易所内部事件模型里都能找到影子。工程实现上要注意:ExecType
是事件流的一部分,必须持久化;OrdStatus
是事件流聚合的结果,可以重算。
这一节把交易所侧的低延迟手段清单化。很多技术在第 16 篇撮合引擎里会展开,这里先建立地图。
isolcpus=
内核参数把若干核心从调度器隔离,撮合线程独占;__builtin_prefetch
提前载入下一笔订单到缓存;现代交易所在多个环节打时间戳:t0(网关入站)、t1(风控出)、t2(撮合入)、t3(撮合出)、t4(行情出)、t5(网关出站给客户)。运营团队每天分析每段延迟的
P50/P99/P99.99,不到 1 μs 的抖动都是”事故”。
| 交易所 | 核心系统 | 关键信息 |
|---|---|---|
| 纽交所 | Pillar(2016 上线替换多套旧系统) | FIX/Pillar Binary、并购 Archipelago、2022 完成所有板块迁移 |
| 纳斯达克 | INET | 2004 收购 Island 的 INET 引擎、OUCH/ITCH 协议、被全球 20+ 市场作为底座复用(含纳斯达克北欧、香港、东京部分板块) |
| 芝加哥商品交易所 | CME Globex | 始于 1992,期货/期权全球最大电子市场,二进制协议、FPGA 加速 |
| 洲际交易所 | ICE Trading Platform | WTI、Brent 原油期货、合并 NYSE 后继续使用自有平台 |
| 上交所 | 新一代交易系统(2019) | 自研、FPGA 加速、撮合性能 60 万笔/秒量级(公开资料)、STEP/FIX 接入 |
| 深交所 | 第五代交易系统 | 2016 上线、2022 持续升级 |
| 中金所 | 新一代期货交易系统 | 合约撮合、保证金、CCP 一体化 |
| 港交所 | Orion Trading Platform (OTP-C) | 证券、衍生品、LME 金属期货 |
| 东京证交所 | arrowhead 4.0(2024) | 富士通,响应时间压到亚毫秒 |
| 交易所 | 核心栈 |
|---|---|
| Binance | C++ 撮合引擎 + Go 网关(来自公开工程分享)、MySQL + 自研存储 |
| Coinbase | Java/Go 多栈,撮合早期 Erlang,后迁移 Java |
| OKX / 火币 / Gate | C++ 撮合 + Go/Java 网关,架构趋同 |
| Deribit | 欧式期权龙头,撮合为 OCaml → 后重写为 Rust/C++ |
| Kraken | Cython/C++ 撮合、广泛采用 Rust 进行生态扩展 |
去中心化交易所的”撮合”方式和传统交易所完全不同,是本篇最值得单独记一笔的变化:
DEX 的工程性能目前仍远低于中心化交易所(Binance 现货顶峰 200 万 TPS,DEX 顶峰 20 万 TPS 级别),但它带来了自托管、抗审查、可组合这三个中心化交易所永远无法提供的属性。第 25 篇会讨论行业展望。
道琼斯指数在几分钟内下跌约 1000 点再反弹。SEC/CFTC 联合报告将原因归结为:一笔 41 亿美元的 E-mini S&P 500 期货卖单(由 TWAP 算法执行)与流动性不足的市场碰撞,叠加 HFT 的瞬时退出,造成连锁下跌。
工程教训:
骑士资本在上线新代码时,运维手动部署到 8 台服务器,漏掉了其中 1 台。那台机器上旧代码的一段测试路径被配置标志激活,以每秒数千笔的速度向纽交所发出错误订单。45 分钟内造成 4.4 亿美元账面亏损,公司当周被 Getco 收购。
工程教训:
加密市场没有涨跌停,极端行情容易出现”插针”——瞬间价格偏离 30% 后回归,但这段时间的强平已不可逆。应对措施:
中心化加密交易所持有用户资产,必须设计冷热钱包分层:
去中心化永续交易所(如 dYdX v4、Hyperliquid)的订单簿上链对传统撮合工程师既熟悉又陌生:
CREATE TABLE orders (
order_id BIGINT PRIMARY KEY,
session_id BIGINT NOT NULL,
cl_ord_id VARCHAR(64) NOT NULL,
account_id BIGINT NOT NULL,
symbol_id INT NOT NULL,
side TINYINT NOT NULL, -- 0 BUY, 1 SELL
ord_type TINYINT NOT NULL,
price_ticks BIGINT NULL, -- 市价单为 NULL
qty BIGINT NOT NULL,
cum_qty BIGINT NOT NULL DEFAULT 0,
avg_price_ticks BIGINT NULL,
tif TINYINT NOT NULL,
status TINYINT NOT NULL, -- 见 8.2
ts_ns_in BIGINT NOT NULL,
ts_ns_last BIGINT NOT NULL,
UNIQUE KEY uniq_session_clord (session_id, cl_ord_id),
KEY idx_account_status (account_id, status),
KEY idx_symbol_status (symbol_id, status)
);CREATE TABLE trades (
trade_id BIGINT PRIMARY KEY,
symbol_id INT NOT NULL,
maker_order_id BIGINT NOT NULL,
taker_order_id BIGINT NOT NULL,
maker_account BIGINT NOT NULL,
taker_account BIGINT NOT NULL,
price_ticks BIGINT NOT NULL,
qty BIGINT NOT NULL,
ts_ns BIGINT NOT NULL,
KEY idx_symbol_ts (symbol_id, ts_ns)
);8=FIX.4.4|9=142|35=D|49=MYCLIENT|56=EXCHANGE|34=215|52=20260422-09:30:01.123|
11=ORD123|21=1|55=AAPL|54=1|60=20260422-09:30:01.121|38=100|40=2|44=180.50|59=0|10=072|
{
"op": "order.new",
"req_id": "c-20260422-001",
"symbol": "BTC-USDT",
"side": "BUY",
"type": "LIMIT",
"price": "65000.5",
"qty": "0.12",
"tif": "GTC",
"post_only": true,
"ts": 1745325001000
}下面是笔者和同行在交易所相关系统里踩过的、每条都代表过一次故障的经验:
double
表达价格的系统最终都会在加法累积误差处翻车,尤其是均价重算。统一使用”最小报价单位
tick 整数表示”。CLOCK_MONOTONIC)做内部序号,UTC
时间仅用于对外。1)券商自研柜台 / 连接交易所侧的 OMS
不用追求 FPGA 级延迟(意义不大,瓶颈在交易所侧),但要:
2)量化策略 / 做市商接入层
3)自研现货 / 衍生品交易所(加密、新兴市场)
4)去中心化交易所(DEX)
一个中心化加密现货交易所的 MVP 落地清单:
这张清单上每一个条目都是一个迭代周期,任何一个做不好都能让交易所在黑天鹅事件里崩溃。顺序很重要:账户和资金对账优先于撮合性能,风控优先于功能完备。
为了把前面十六节的零碎模块串起来,这一节用一个具体的场景追踪一笔订单从产生到结算的完整旅程。场景设定:机构用户
A 通过 FIX 专线向 T 交易所提交一笔
BUY 10000 @ 180.50 的 AAPL 限价单。
A 的策略引擎生成委托指令。本地 OMS 打第一个纳秒时间戳
t_app,把订单封装为 FIX 35=D
报文,通过内核旁路(Solarflare
Onload)发到交易所边缘路由。
交易所机房托管 Rack 内,边缘交换机镜像一路给 FPGA 前置风控卡,一路转发给软件网关。FPGA 在 320 ns 内完成可用资金、单笔上限、价格偏离三项检查,全部通过,直接把归一化后的二进制订单送入撮合引擎的无锁入口队列;软件网关同时把订单写入审计日志(异步、不阻塞)。
撮合引擎的单一业务线程从 Ring Buffer 拿到订单。此时 AAPL
订单簿卖一为 180.50 7500 股(订单
O_m1,maker)、卖二 180.51 15000
股。撮合线程判定:
在同一次函数调用内:
(maker=O_m1, taker=A, price=180.50, qty=7500, ts_ns=...);Trade、BookUpdate(卖一被吃)、BookUpdate(买一新增)、ExecReport(A: partial fill + working)。整个过程在 800 纳秒内完成,全部纯内存操作。
事件进入出口分发器,分两路:
成交回报
ExecReport(partial, filled=7500, leaves=2500, avg=180.50)
回到 A 的 OMS。A 的策略再次基于新的仓位状态计算是否撤掉剩余
2500 股。
收盘。剩余挂单 A 的 2500 股未成交,按 DAY TIF
自动过期,生成 ExecType=Expired
事件。日终撮合引擎把快照序号 seq=<final>
冻结。
至此,一笔订单跨越 24 小时,从客户端的 1 纳秒时间戳开始,到最终在美国证券存管机构 DTC 完成过户,经手了网关、风控、撮合、行情、清算、净额、CCP、托管、DTC 九个以上独立系统。每个环节的错误都可能造成资金风险或合规问题——这就是交易所工程的复杂度。
很多团队在设计交易所时卡在一个问题上:容量规划到底按什么单位做? 这里给出一组经验数字,仅供参考,不同市场差别巨大。
| 指标 | 纳斯达克 | 上交所 | Binance 现货 | CME Globex |
|---|---|---|---|---|
| 日订单量(峰值) | 约 1000 亿条消息/日(含行情) | 数十亿条消息/日 | 百亿级订单/日 | 数十亿条消息/日 |
| 日成交笔数 | 约 1–2 亿笔 | 数亿笔 | 数亿笔(全品种) | 数百万笔(主合约) |
| 单撮合实例峰值 TPS | 百万级 | 60 万级(公开) | 数十万级 | 百万级 |
| 端到端延迟(P50) | < 100 μs | < 100 μs | 数百 μs | < 100 μs |
| 端到端延迟(P99.99) | < 1 ms | < 1 ms | 数 ms | < 500 μs |
最后列一组笔者在这个方向的同行聚会或面试中经常听到的问题,读者可以用作自我检查:
答案散落在本篇和后续 16、17、18 篇里,留给读者主动拼装。
交易所的可观测性投入远远高于一般互联网系统,原因简单——几微秒的抖动可能是几千万美元的套利窗口,几毫秒的消息丢失可能触发监管介入。
端到端延迟必须能被拆解到每一段:
total = (t_net_in - t_app_send)
+ (t_risk_in - t_net_in)
+ (t_match_in - t_risk_out)
+ (t_match_out - t_match_in)
+ (t_md_out - t_match_out)
+ (t_exec_out - t_match_out)
+ (t_app_recv - t_exec_out)
每个时间戳来自硬件(NIC 时间戳)或用户态(RDTSC)采样。每天结束时按合约和会话维度给出 P50/P99/P99.99,异常值触发告警与工单。
所有订单事件、成交事件、风控决策、参数变更必须不可篡改地长期留存。常见做法:
MiFID II 要求 HFT 相关主体保留 5 年以上详细订单日志;中国证监会对证券经纪业务的电子数据保存要求也不低于 5 年。
交易所软件不同于一般业务系统——错误的代价直接挂钩监管和真金白银。任何一次变更前的验证、上线时的灰度、事故时的灾备切换,都必须有工程化的方法论。
撮合引擎的灰度不同于互联网服务——不能按用户流量比例灰度(同一合约的订单不能分到两个实例)。典型做法:
互联网系统流行的 Chaos Monkey 在交易所环境里要非常小心:
本篇收尾时不妨把视线拉远。过去十年交易所架构最大的变化是:加密交易所把证券工程文化从机构圈普及到了所有软件工程师。下一个十年,几条值得关注的方向:
这些方向将在系列的最后一篇(第 25 篇《金融科技工程展望》)做收束。
上一篇:《数字人民币、稳定币与 CBDC:双层运营、离线支付、链上/链下清算》
下一篇:《撮合引擎实现:撮合算法、价格优先时间优先、状态机、低延迟工程》
把当前热点继续串成多页阅读,而不是停在单篇消费。
2026-04-22 · architecture / fintech
深入剖析中央限价订单簿(CLOB)撮合引擎的数据结构与算法,覆盖价格时间优先、Pro-Rata、订单类型、自成交预防、集合竞价、确定性回放、WAL 快照、单线程事件循环与 Disruptor 模型,并给出 Rust/Go 简化实现与单元测试清单。
2026-04-22 · architecture / fintech
金融科技(FinTech)不是普通后端加一张账户表。钱的原子性、监管的硬边界、一个小数点的代价,把这个领域推进到工程强度最高的那一档。本文是【金融科技工程】25 篇的总目录与阅读地图:先交代为什么它比一般业务系统更难,再给出对账体、支付体、交易体、风控合规体四维分类,把后续 24 篇挂到骨架上,最后给出一份绿地项目的落地顺序建议。
2026-04-22 · architecture / fintech
从 L1/L2/L3 分级、FIX FAST/ITCH/SBE 协议到 UDP 组播+重传通道、内核旁路与微波传输,系统梳理交易所行情系统的生产、分发与消费;给出 snapshot+incremental 恢复机制、Conflation 与 Full Tick 权衡、kdb+/ClickHouse/QuestDB tick 存储、事件时间回放与 K 线合成实现,并附 Binance WebSocket Diff Depth 维护本地订单簿的 Go/Python 示例。
2026-04-22 · architecture / fintech
面向中国工程团队的金融科技系列。从账务底盘、支付、清结算、交易所、风控合规到可靠性与灾备,中国与全球视角并举,讲清楚金融系统在工程落地中的真实挑战。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。