价值超5万的撮合引擎:开篇

简介: 笔记

前言


自从有人在微信群里开价5万求购Golang版的撮合引擎之后,我就想自己开发一款,毕竟,以我的经验来说,开发个高性能的撮合引擎并没什么难度。

说干就干,于是,利用业余时间慢慢开发出了一款Golang版的高性能撮合引擎,前前后后花了大概一个月的时间。再想想自己好久没更新文章了,我的个人IP都已经生锈了,也应该发大招磨一磨了。因此决定,干脆就以连载的方式,分享下我是如何设计与实现这款价值超5万的撮合引擎的。

本来,想发成掘金小册,收点稿费,毕竟这是个具有很大商业价值的软件,但问了掘金的人员,他们目前不接收这类主题。最终决定免费发布,还可以多发几个渠道,说不定还能给我多带来些关注量。

好了,下面开始进入撮合引擎系列的正题。


撮合引擎简介


撮合引擎是所有撮合交易系统的核心组件,不管是股票交易系统——包括现货交易、期货交易、期权交易等,还是数字货币交易系统——包括币币交易、合约交易、杠杆交易等,以及各种不同的贵金属交易系统、大宗商品交易系统等,虽然各种不同交易系统的交易标的不同,但只要都是采用撮合交易模式,都离不开撮合引擎。

撮合引擎是可以具有通用性的,一套具有通用性的撮合引擎实现理论上可以应用到任何撮合交易系统中,而无需做任何代码上的调整。即是说,同一套撮合引擎实现,既可以应用在股票交易系统,也可以应用在数字货币交易系统,可以用于现货交易,也可以用于合约交易等。

那么,一套具有通用性的撮合引擎应该具备哪些功能呢?确定该问题的答案之前,我们先简单梳理一下一个完整的交易流程是怎样的?一般会包括以下步骤:

  1. 系统开放某个交易标的的交易功能。
  2. 用户提交该交易标的的买卖申报,即委托单
  3. 系统验证委托单是否有效,包括交易标的是否处于可交易的状态、订单的价格和数量是否符合要求等。
  4. 确定该委托单的**挂单(Maker)费率和吃单(Taker)**费率。
  5. 检查用户的资产账户情况,包括账户状态是否交易受限,是否有足够资金用于下单等。
  6. 将详细的委托单数据持久化到数据库,并冻结用户账户中相应数量的资金。
  7. 将委托单进行撮合处理,即在**交易委托账本(OrderBook)**中寻找能与该委托单匹配成交的订单,匹配的结果可能是:全部成交、部分成交或无匹配。全部成交或部分成交时,可能在交易委托账本中存在一个或多个匹配的订单,即会产生一条或多条成交记录。当无匹配或部分成交时,委托单的部分数据包括剩余未成交的数量会暂时保存到交易委托账本中,等待与后续的委托单匹配撮合。
  8. 将撮合产生的成交记录持久化到数据库,并根据历史成交记录生成市场数据,如K线数据、今日涨跌幅等。
  9. 更新数据库中所有成交订单的委托单数据,以及更新订单用户的资产账户余额。
  10. 将更新的订单数据、市场数据等发送给到前台。

整个交易流程中涉及到多个服务,包括用户服务、账户服务、订单服务、撮合服务、市场数据服务等。其中,只有第7步是撮合引擎处理的。从单一职责原则来说,撮合引擎就应该只做一件事,那就是负责撮合订单。撮合之前的委托单持久化、冻结资金等,以及撮合之后生成K线数据等,都不应该属于撮合引擎的职责。


撮合竞价方式


撮合竞价方式一般有两种,一是集合竞价,二是连续竞价。股票交易系统一般会在不同交易时间段采用不同的竞价方式,比如在开盘或收盘时采用集合竞价,从而产生开盘价收盘价,其余时间采用连续竞价。而大多数字货币交易系统则没有集合竞价,只有连续竞价,开盘价一般是在开始交易之前就设定好的。


集合竞价

所谓集合竞价,是指对一段时间内接收的买卖委托单一次性集中撮合的竞价方式。以深沪的股票交易系统为例,在每个交易日的 9:15~9:25 期间是集合竞价时间。在该时间段内,系统陆续接收到的委托单不会即时成交,而是先将所有委托单按照价格优先、时间优先的原则排序,并在此基础上,找出一个基准价格,使它能同时满足以下三个条件:

  1. 可实现最大成交量的价格;
  2. 高于该价格的买单与低于该价格的卖单能全部成交的价格;
  3. 与该价格相同的买方或卖方至少有一方全部成交的价格。

在 9:25 分结束的时候,该基准价格就被确定为成交价格,所有高于该价格的买单与低于该价格的卖单都将以该价格成交。未能成交的委托单,则自动转入连续竞价。

不过,如果满足以上三个条件的价格存在两个或两个以上呢?对此,深交所和上交所的处理方案有所不同,深交所会取距前收盘价最近的价格为成交价,而上交所则取使未成交量最小的价格为成交价,如果未成交量最小的价格仍不止一个,则取中间价为成交价。

集合竞价的主要目的就是为了确定开盘价或收盘价。

连续竞价

所谓连续竞价,也是我们所熟悉的竞价方式,是指对买卖委托单逐笔连续撮合的竞价方式。用户的挂单,只要满足成交条件,就能即时成交。而集合竞价,则要等到最后一刻才会成交。

连续竞价时,依然要满足价格优先、时间优先的成交原则:

  1. 价格优先:买单则价格较高者能优先成交,卖单则是价格较低者能优先成交。
  2. 时间优先:买卖方向和价格相同的委托单,先申报的委托单会比后申报的委托单优先成交。

另外,买入价必须大于或等于卖出价才能撮合成交。当买入价等于卖出价时,成交价就是买入价或卖出价。当买入价大于卖出价时,则还要参考前一笔成交价来确定最新成交价。假设买入价为 B,卖出价为 S,前一笔成交价为 P,最新成交价为 N,那么:

  • 如果 P >= B,则 N = B
  • 如果 P <= S,则 N = S
  • 如果 B > P > S,则 N = P

一套通用的撮合引擎应该两种竞价方式都支持,但对于同一交易标的来说,两种竞价方式不能同时进行,因此设计上需要考虑如何在两种竞价方式之间切换,具体的实现思路在后续章节我们再展开来讲。


质量需求


我们的撮合引擎除了要满足以上所说的功能需求,还应该满足一些质量需求,尤其对可用性可伸缩性性能的要求较高。另外,为了达到通用,也要满足可复用性的需求。

先说下可复用性,我们期望的是该撮合引擎既能用于股票交易系统,也能用于数字货币交易系统,既能用于币币交易,也能用于合约交易。因此,该撮合引擎要避免引入与具体系统强相关的业务逻辑,以加强它的可复用性。

再看看性能,要衡量一个撮合引擎的性能,就看它处理每个交易对的 TPS 有多高,即每秒钟能处理多少笔相同交易对的委托单。以前,基于数据库的撮合技术,TPS 一般只有10笔/秒。而现在基本都是采用内存撮合技术,TPS 很容易就能达到1000笔/秒,如果使用独占的高性能服务器,1万笔/秒甚至更高的 TPS 都不难达到。

接着谈谈可伸缩性,我们的每一个撮合引擎既可以同时处理多个交易标的,也可以只处理单个交易标的。当交易标的和并发量增多的时候,可以增加服务器,部署成撮合引擎集群,分别用来处理不同的交易标的,从而能够实现负载均衡。

最后聊聊可用性,高可用主要体现在两点,一是故障率要低,二是对故障维修的时间要短。要降低故障率,那撮合引擎就需要有较高的健壮性,对于可能导致引擎出故障的各种异常情况要考虑好并设计好解决方案。另外,还可以采用多机热备份技术来提高可用性,而且要保证互备服务器之间的数据一致,那就需要引入内存状态机复制方案,实现上会复杂很多。

不过,我们并非一下子就要达到很高的质量要求,因为要求越高,其架构和实现会越复杂。我们可以先从简单的版本开始,然后不断升级迭代。


小结


我们目的是实现一套通用的撮合引擎,要支持集合竞价和连续竞价,还要实现一些质量需求,提高系统的可复用性、性能、可伸缩性、可用性等。后续章节会对这些需求不断深入探讨其设计与实现。另外,我们将采用不断升级迭代的方式来设计和实现多个版本的撮合引擎。

留两个思考题:

  1. 集合竞价结束的时候,如果不存在符合那三个条件的基准价格,那开盘价又将如何确定?
  2. 对于单个交易对,是否可通过横向增加服务器的方式提高其性能?


相关文章
|
消息中间件 缓存 NoSQL
|
1月前
|
存储 人工智能 大数据
秒级响应与低成本实现!TDengine 助力多元量化交易系统的背后故事 | 征文
在不久前的“2024,我想和 TDengine 谈谈”征文活动中,我们收到了许多精彩的投稿,反映了用户与 TDengine 之间的真实故事和独特见解。今天,我们很高兴地分享此次活动的第一名作品。这篇文章详细阐述了广西多元量化科技有限公司如何利用 TDengine 构建高效的量化交易系统,提升交易效率和决策质量。通过深入分析数据库选型和数据架构设计,作者展示了 TDengine 在金融领域的强大优势和广泛应用前景。接下来让我们一同阅读,探索这一前沿技术如何推动现代金融交易的智能化与高效化。
39 5
|
5月前
|
人工智能 搜索推荐 安全
深度剖析:代购系统的运行机制与价值
全球化时代,代购系统因跨境购物需求增长而兴起。此类系统提供商品搜索、比价、订单跟踪、支付结算及售后客服等服务,简化了海外购物流程,拓宽了商品选择,降低了购物风险。面临的挑战包括法规遵守、市场竞争、信任建立及技术更新。未来,代购系统将借助AI和新技术,向智能化、个性化发展,可能涉及更多跨境服务领域。
|
数据采集 存储 监控
数据与分析的战常用设计思路
数据与分析的战常用设计思路
|
前端开发 JavaScript 小程序
新来个技术总监,给公司项目引入了全新的业务架构,堪称最佳实践!
新来个技术总监,给公司项目引入了全新的业务架构,堪称最佳实践!
DAPP公排互助拆分系统开发详情原理丨DAPP拆分互助公排系统开发玩法功能/方案设计/案例分析/成熟技术/源码版
The lifecycle of smart contracts can be summarized into six stages based on their operational mechanisms: negotiation, development, deployment, operation and maintenance, learning, and self destruction. The development stage includes contract testing before contract chaining, while the learning sta
|
Web App开发 搜索推荐 安全
【MarTech参考架构】Credera的MarTech参考架构第6部分:AdTech趋势、参与者和衡量
【MarTech参考架构】Credera的MarTech参考架构第6部分:AdTech趋势、参与者和衡量
|
数据采集 前端开发 大数据
创业公司如何做数据分析(一)开篇
本文将按照“WHY->WHAT->HOW”的思考方式来阐述下面三个问题:创业公司为什么需要做数据分析?创业公司做数据分析,需要做哪些事情?如何实现这些数据上的需求?从而基于“数据驱动”来做决策、运营与产品。
9066 0
|
负载均衡 安全 测试技术
洽谈区块链游戏项目系统开发逻辑讲解方案及技术参考原理
洽谈区块链游戏项目系统开发逻辑讲解方案及技术参考原理
301 0
|
SQL 存储 缓存
【视频特辑】数据分析不卡顿,十亿数据0.3秒搞定!看看Quick引擎是如何做到的吧~
报表加载慢、分析卡顿导致思路被打断...常常会给数据分析师造成很大困扰。 不如试试Quick引擎,十亿数据只需0.3秒就可以完成数据分析!
306 0
【视频特辑】数据分析不卡顿,十亿数据0.3秒搞定!看看Quick引擎是如何做到的吧~