撮合引擎开发:完结篇

简介: 笔记

本小节是该系列文章的最后一篇了,将讲解剩下的一些东西,包括交易委托账本中订单队列的实现逻辑、更多订单类型的实现逻辑。另外,不少朋友在问,完结后所有代码是否会开源放上 Github?我只能说,长期大概率会开源,但短期内还没打算开源。


订单队列


交易委托账本其实就是由两个订单队列组成的,一个买单队列,一个卖单队列。任何对交易委托账本的查询和操作,实际上都是查询和操作这两个队列。订单队列的设计也直接影响了撮合的性能,前面文章讲数据结构设计时也有简单聊了订单队列的设计,我们主要是用二维链接结合 Map 来保存所有订单的,依赖的是 container/list 包。

订单队列的结构体如下:

type orderQueue struct {
  sortBy     enum.SortDirection
  parentList *list.List
  elementMap map[string]*list.Element
}

sortBy 指定价格排序的方向,买单队列是降序的,而卖单队列则是升序的。parentList 保存整个二维链表的所有订单,第一维以价格排序,第二维以时间排序。elementMap 则是 Key 为价格、Value 为第二维订单链表的键值对。

初始化函数就比较简单了,对几个字段赋值而已,代码如下:

func (q *orderQueue) init(sortBy enum.SortDirection) {
  q.sortBy = sortBy
  q.parentList = list.New()
  q.elementMap = make(map[string]*list.Element)
}

除了初始化函数,还提供了另外五个函数:

  • addOrder(order):添加订单
  • getHeadOrder():读取头部订单
  • popHeadOrder():读取并删除头部订单
  • removeOrder(order):移除订单
  • getDepthPrice(depth):读取深度价格

以上五个函数就只有第一个函数会比较复杂,为了让处理流程更容易理解,我就不贴代码了,画一个完整的流程图给大家看看:

这个流程确实有一点复杂,可以多看几遍好好消化,最好自己动手将其转为代码实现。

其他几个函数就简单了,关于最后一个函数需要补充说明一下。读取深度价格是为了方便处理 market-opponent、market-top5、market-top10 等类型的订单时判断上限价格。请看该函数的代码以理解该函数的逻辑和用法:

func (q *orderQueue) getDepthPrice(depth int) (string, int) {
  if q.parentList.Len() == 0 {
    return "", 0
  }
  p := q.parentList.Front()
  i := 1
  for ; i < depth; i++ {
    t := p.Next()
    if t != nil {
      p = t
    } else {
      break;
    }
  }
  o := p.Value.(*list.List).Front().Value.(*Order)
  return o.Price.String(), i
}

多种订单类型


我们引擎总共支持了六种订单类型,之前的文章有简单介绍过,但没有深入讲解这几种不同类型的具体业务逻辑应该是怎样的,因此,在此将这部分内容补充上。

1. limit

普通限价是最简单的,前文也已经展示过代码实现,为了加深理解,我再给大家画一张图:

处理逻辑就是:

  1. 判断新订单是买单还是卖单。
  2. 如果是买单,那从 OrderBook 中读取出头部卖单,即卖单队列中的头部订单;如果是卖单,那从 OrderBook 中读取出头部买单,即买单队列中的头部订单。
  3. 新订单为买单时,如果头部订单为空,或者新订单小于头部订单,即无法成交,那就把新订单添加到买单队列中,处理结束;新订单为卖单时,如果头部订单为空,或者新订单大于头部订单,即无法成交,那就把新订单添加到卖单队列中,处理结束。
  4. 否则,符合匹配条件,新订单和头部订单进行撮合成交。
  5. 撮合完成后,如果新订单剩余数量为零则结束,如果还大于零,则回到第2步继续取下一个头部订单,如此循环。

2. limit-ioc

IOC 限价与普通限价不同的地方只有一个,如果新订单和头部订单不匹配时,普通限价单会被添加到订单队列中,而 IOC 限价则是作撤单处理,请看下图:

3. market

默认市价单的逻辑也比较简单,它不需要判断价格,只要头部订单不为空,就直接和头部订单匹配成交,其处理逻辑如下图:

4. market-top5/market-top10

最优五档/十档市价单与默认市价单的逻辑也是类似的,不同点在于:默认市价的成交价格没有上限或下限,但最优五档/十档市价则存在价格上限或下限,超过上下限的委托单不会成交。画图太累,还是直接贴代码吧,以下是处理买单的:

func dealBuyMarketTop(order *Order, book *orderBook, lastTradePrice *decimal.Decimal, depth int) {
  priceStr, _ := book.getSellDepthPrice(depth)
  if priceStr == "" {
    cancelOrder(order)
    return
  }
  limitPrice, _ := decimal.NewFromString(priceStr)
LOOP:
  headOrder := book.getHeadSellOrder()
  if headOrder != nil && limitPrice.GreaterThanOrEqual(headOrder.Price) {
    matchTrade(headOrder, order, book, lastTradePrice)
    if order.Amount.IsPositive() {
      goto LOOP
    }
  } else {
    cancelOrder(order)
  }
}

5. market-opponent

最后一种类型,对手方最优价,该类型只与对手方一档的价位成交,但与最优五档/十档还有一点不一样:最优五档/十档未成交的部分是作撤单处理的,而对手方最优价最后未成交的部分则是转为限价单。请看代码:

func dealBuyMarketOpponent(order *Order, book *orderBook, lastTradePrice *decimal.Decimal) {
  priceStr, _ := book.getSellDepthPrice(1)
  if priceStr == "" {
    cancelOrder(order)
    return
  }
  limitPrice, _ := decimal.NewFromString(priceStr)
LOOP:
  headOrder := book.getHeadSellOrder()
  if headOrder != nil && limitPrice.GreaterThanOrEqual(headOrder.Price) {
    matchTrade(headOrder, order, book, lastTradePrice)
    if order.Amount.IsPositive() {
      goto LOOP
    }
  } else {
    order.Price = limitPrice
    order.Type = enum.TypeLimit
    book.addBuyOrder(order)
    cache.UpdateOrder(order.ToMap())
    log.Info("engine %s, a order has added to the orderbook: %s", order.Symbol, order.ToJson())
  }
}

完结


至此,整个系列就此完结。不过,我的撮合程序依然会继续迭代升级,另外,也将开始开发其他组件,将会和当前这个撮合引擎结合来用。欢迎关注后续动态。


相关文章
|
6月前
|
存储 安全 区块链
DAPP持币生息系统开发|模式案例|开发指南
智能合约是一种计算机协议,在协议制定和部署后,不需要外加人为干预,即可实现自我执行和自我验证
|
6月前
|
新零售 小程序 搜索推荐
认养模式小程序系统开发|成熟技术|项目案例
随着新零售的发展,我们设想更多创新的商业模式和营销方式。
|
6月前
|
自然语言处理 安全
线下陪玩游戏系统开发多语言/海外版/成熟技术/方案项目/源码功能
Continuing to develop an offline companion game system may involve the following aspects:
|
存储 安全 算法
Jogger跑鞋NFT铸造合成分红系统开发成熟技术方案及详细/源码功能
  区块链技术是利用块链式数据结构来验证与存储数据、利用分布式节点共识算法来生成和更新数据、利用密码学的方式保证数据传输和访问的安全、利用由自动化脚本代码组成的智能合约来编程和操作数据的一种全新的分布式基础架构与计算方式。
|
存储 区块链
Jogger慢跑者/stepn跑鞋链游模式系统开发详细功能/案例项目/源码程序
区块链的核心技术之一就是公开且透明的交易信息。一般情况下,在区块链内产生、流转和存储的信息是对所有节点用户开放的,其高度的透明化也使得区块内的所有人都能够查看数据的所有相关信息同时使用其应用。因此,区块链技术在信息共享与数据交换领域具有一定的优势。
|
JavaScript 前端开发 区块链
NFT链游stepn跑鞋质押模式系统开发(技术原理)|案例搭建
智能合约是在区块链上运行并在web3生态系统中启用去中心化应用程序
|
6月前
|
存储 安全 区块链
Matic马蹄链Meforce佛萨奇3.0系统开发设计及方案
信大家对智能合约的优点和缺点是什么,以及为什么智能合约很重要,有了一定的了解
|
存储 区块链 数据安全/隐私保护
Stepn跑鞋/Jogger慢跑者NFT链游铸造合成项目系统开发(正式版)/案例说明/方案介绍/逻辑项目/源码平台
链游是指基于区块链技术的游戏,也被称为区块链游戏或加密游戏。在传统游戏中,游戏数据通常由中心化的服务器控制和存储,而在链游中,游戏数据被存储在区块链网络中,所有的玩家都可以访问和验证这些数据。
|
人工智能 数据挖掘 物联网
NFT/Stepn/Jogger跑鞋链游铸造合成项目系统开发成熟稳定版/开发案例/规则玩法/源码平台
  NFT跑鞋链游项目则是将区块链技术应用到跑鞋领域中去的一个创新项目。通过NFT跑鞋链游项目,跑者可以将自己的跑鞋进行数字资产化,并在游戏中进行买卖和交换。这种数字资产化的跑鞋不仅可以让跑者更好地了解自己的跑鞋价值,还可以为跑者带来更多的社交和娱乐价值。
|
存储 人工智能 算法
MATIC马蹄链佛萨奇2.0系统源码搭建|现成案例|成熟技术
function _setImplementation(address newImplementation)internal{