打开导航 打开导航 Open menu
量化交易系统开发(C++)/ 期权策略与风控 / 行业研究分析
量化交易系统開發(C++)/ 期权策略与风控 / 行业研究分析
C++ trading systems / options strategy & risk controls / equity research
adrian@adrianxv.cn

交易系统架构简介 交易系统架构简介 交易系统架构简介

交易系统架构简介

这是学习 《Building Low Latency Applications With C++: Develop a Complete Low Latency Trading Ecosystem From Scratch Using Modern C++》 的读书笔记。此乃第 5 章 “Designing Our Trading Ecosystem” 的第一篇笔记。

要理解交易系统,需要从交易所侧和客户端两边来理解。和书中保持统一,我们就叫 exchange side 和 participant side。两边的交互流程如图所示:

alt text

交易系统当中的数据流可以粗略分成订单流和行情流两种。黄色部分用于处理订单流,由 Order Gateway Server 和 Order Gateway Client 双向通信;紫色部分用于处理行情六,由 Market Data Publisher 向 Market Data Consumer 单向通信。

此外,exchange side 最为关键的是 matching engine,也就是撮合引擎;participant side 最为关键的是 trading engine。matching engine 当中维护订单簿(Order Book),这是反映市场微观结构的最重要的数据结构。一般来说为了能基于准确、实时的市场行情进行交易,participant side 的 trading engine 也会维护一个订单簿,让策略基于订单簿做出交易决策。

此处的6个组件通常用不同的6个线程来代表。不同的组件之间的通信要保持低延迟,因此都使用无锁队列来通信。撮合引擎与 order gatewat server、trading engine 与 order gateway client 之间需要通过双向队列来通信。

以下细说各个组件:

Order Gateway Server/Client

alt text

这部分的管订单流。订单流的数据是私有流,且是双向通信的。原因是一个客户发出的订单之后,撮合引擎根据是否能立即成交决定是否需要挂单。如果产生了成交,则该成交回调应该仅返回给发出订单的客户(而不是所有客户)。由于订单数据及其重要,丢包造成的损失较大(若从客户发往交易所时丢包,则策略可能误以为订单已发出从而调整策略视角的资金/订单;若从交易所发往客户时丢包,则客户得不到成交信息),因此这里通常使用 TCP 连接。

alt text

因此,Order Gateway Server/Client 要管理 TCP 连接、负责 encode / decode 订单消息、进行双向通信。由于 Order Gateway Server 需要处理所有市场参与者的订单信息,因此需要两个 FIFO 队列来按照时间顺序分别处理订单请求,以及订单回调。FIFO 确保了公平。

Market Data Publisher/Consumer

alt text

Market Data Publisher 负责将 Matching Engine 当中产生的交易信息广播给所有市场参与者(或者准确地说是订阅了相关合约的参与者)。它首先要将 Matching Engine 当中的成交数据格式转化为用于广播的标准格式。且广播的信息分为两个 stream,incremental stream 和 snapshot stream。前者负责广播逐笔交易信息,因此每次广播的信息量较小,但是广播频繁;后者负责间隔一段时间广播整个订单簿的快照。

理想情况下,如果客户端从当天开盘便持续接受 incremental stream 的逐笔交易信息,则客户端的 Trading Engine 当中管理的订单簿总是能如实反映交易所的撮合引擎当中的订单簿信息。但是由于网络传输/中途重启/盘中才接入/对账等问题,客户端很可能希望在盘中也能够重建订单簿,而 snapshot stream 的快照就是为这个目的服务的。快照和逐笔数据都有连续的编号,因此读取快照编号便知道当前快照截止到哪一笔成交,可以通过编号是否连续得知有没有漏掉某一笔成交数据。

由于这部分的行情数据是面向广大客户端的,因此吞吐量巨大。为了效率,通常选用 UDP 来进行传输,因为无论如何客户端都可以通过快照 + 后续的 incremental stream 来重建订单簿,无需依赖 TCP 可靠传输。另外,为了公平,这其中逐笔成交数据通常是抹除了买卖双方的信息的,通常也不会告知该成交是否属于冰山单/算法单之类的特殊订单。

alt text

Market Data Consumer 则负责订阅 Market Data Publisher 的两个 stream (UDP),对 stream 当中的信息进行解码为交易系统内部格式。

Matching Engine

alt text 撮合引擎负责决定哪些订单能够成交,并将暂时不能成交的引擎作为挂单挂在订单簿上面。一般的规则是,当买单的价格高于卖单的价格时成交;当卖单的价格低于买单的价格时成交,这些直接成交的单称为主动单,与之相对的是订单簿上的挂单(被动单)。若订单簿上的挂单不足以满足主动单的成交量,则主动单未成交的量被挂在订单簿上成为挂单。在开盘前、集合竞价、开盘前不可撤单阶段,规则会有些不同。

撮合引擎与 Order Gateway Server 之间有两个 FIFO 队列,保证订单请求和回调都能按顺序处理,抱枕公平。

订单簿分为两边,买方和卖方,内部首先按照价格的竞争力来排序。最有竞争力的买价(价格最高的麦家)和卖价(价格最低的卖价)分别叫买一价和卖一价;相应地有买一量和卖一量。价格一定是第一排序要素,而同价订单有不同的排序算法,比如按照到达顺序排列(时间上的FIFO),或者按照量排序(Pro Rata)。

要注意,订单在未完全成交之前通常允许修改量价或者撤单,因此客户端实际上可以改变自己的订单在订单簿当中所处的位置。

Trading Engine

客户端当中负责进行交易决策的部分(最核心的部分!!)。为了保持对于市场行情的准确判断,通常管理一个订单簿(与 Matching Engine 的订单簿保持同步,或者取 Matching Engine 订单簿的一部分)。