撮合引擎开发:对接黑箱

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 笔记

黑箱引擎


我们的撮合引擎作为一个相对通用的组件,其实就是一个黑箱,如果想将它应用到各种不同的交易系统,只要有标准的输入和输出,对接是很容易的。

写作此文时的撮合引擎为 1.3 版本,我将其编译构建成可在 Linux amd64 环境运行的可执行文件,并与依赖的配置文件一起压缩成一个压缩包 matching.zip。这就成为一个黑箱引擎了。

不过,该黑箱引擎除了对运行系统有要求,还对 Redis 有要求。由于使用了 Redis 的新版 MQ 功能,即 stream 数据结构,要求 Redis 至少是 5.0 版本。

其实,我也可以编译构建成其他系统环境的可执行文件,如 Windows 或 Mac 系统。但作为一款商业软件以及对性能的一些要求,运行在 Linux 环境更合适。

后面,我们就来看看,如果要将这个黑箱引擎应用到自己的交易系统中,如何对接?


安装部署


安装部署的系统环境需是 Linux amd64 的,另外,如果要让撮合性能更快,建议 Redis 与撮合引擎可以使用同一服务器,这可以减少不同服务器之前的传输耗时。

按照以下步骤操作就可以将撮合引擎安装部署到运行环境了:

1.matching.zip 压缩包上传到运行环境;2.在运行环境解压 matching.zip 压缩包,解压后有一个可执行文件和一个文件夹:

matching:这是撮合引擎程序的可执行文件conf:存放配置文件的目录,里面就一个配置文件 config.yaml

修改配置文件为自己想要的配置值:

server:
  port: :9466  //撮合引擎程序启动监听的端口
log:                 //输出日志配置
  fileDir: logs      //输出日志存放的目录
  fileName: matching //日志文件名,会按日期分割
  prefix:            //日志消息前缀
  level: debug       //日志级别,由低到高为:debug、info、warn、error
redis:
  addr: 127.0.0.1:6379  //Redis地址

1.如果使用默认配置,请确认运行环境本地已安装并启动了Redis并运行在6379端口;2.如果不用默认配置,依然需要确认Redis能正确连接;3.运行以下命令,后台启动撮合引擎程序:


./matching &

1.运行以下命令,检查程序是否启动成功:


ps aux|grep matching

1.程序启动成功后,会在配置的日志目录生成日志文件,默认为与 matching 可执行文件同目录下的 logs/matching.log;2.至此,撮合引擎程序安装部署成功。


对接输入


接入撮合引擎只需要对接三个 HTTP 接口,接口统一采用 POST 方法,参数统一用 json 格式,传 body。

1. 开启撮合

开启指定交易标的(交易对)的撮合功能。

HTTP请求

POST  /openMatching

请求参数

symbol:字符串类型,必传字段,交易标的(交易对)的标识,如 BTC_USDTprice:数字类型,非必传字段,默认为 0,开盘价

请求示例

POST  /openMatching
Body:
{
  "symbol": "BTC_USDT",
  "price": 8219.85
}

响应数据


{"code":0,"msg":"OK"}

2. 关闭撮合

关闭指定交易标的(交易对)的撮合功能。

HTTP请求

POST  /closeMatching

请求参数

symbol:字符串类型,必传字段,交易标的(交易对)的标识,如 BTC_USDT

请求示例

  • 响应数据
POST  /closeMatching
Body:
{
  "symbol": "BTC_USDT"
}

响应数据

{"code":0,"msg":"OK"}


3. 处理订单

接收下单和撤单请求。

HTTP请求

POST  /handleOrder

请求参数

symbol:字符串类型,必传字段,交易标的(交易对)的标识,如 BTC_USDTaction:字符串类型,必传字段,订单动作,下单=create,撤单=cancelorderId:字符串类型,必传字段,订单IDside:字符串类型,必传字段,买卖方向,买入=buy,卖出=selltype:字符串类型,必传字段,订单类型,包括:limit、limit-ioc、market、market-top5、market-top10、market-opponent,说明见下文amount:数字类型,非必传字段,默认为 0,订单交易量,下单时必传,撤单时可不传price:数字类型,非必传字段,默认为 0,委托价格,订单类型为市价时可不传

订单类型说明:

limit:普通限价limit-ioc:IOC限价-即时成交剩余撤销market:默认市价-即时成交剩余撤销market-top5:市价-最优五档即时成交剩余撤销market-top10:市价-最优十档即时成交剩余撤销market-opponent:市价-对手方最优价

请求示例

  • 响应数据
POST  /handleOrder
Body:
{
  "symbol": "BTC_USDT",
  "action": "create",
  "orderId": "a0001",
  "side": "buy",
  "type": "limit",
  "amount": 0.012,
  "price": 8230.74
}


响应数据

{"code":0,"msg":"OK"}


对接输出


撮合引擎有两种输出:撤单结果成交记录。统一用 MQ 的方式进行输入,MQ 是保存为 Redis 5.0 版本之后引入的新数据结构 Stream 类型。每个消息队列其实就是一条 stream,关于 stream 的具体用法我就不展开了,大伙自行去网上搜索学习即可。

1. 撤单结果

每个不同的 symbol 设置一个 stream,其 key 的格式为:matching:cancelresults:{symbol},value 包含两个字段:

orderId:订单号ok:1=成功;0=失败

2. 成交记录

每个不同的 symbol 也设置一个 MQ,key 的格式为:matching:trades:{symbol},value 包含的字段如下:

makerId:maker订单IDtakerId:taker订单IDtakerSide:taker买卖方向amount:成交数量price:成交价格timestamp:成交时间

下游服务就可以通过订阅监听这两种输出,之后做后续的处理,比如 K 线行情服务订阅监听成交记录来生成 K 线数据。等撮合引擎完成之后,我下一个要开发的组件就是 K 线行情服务。


项目结构


最后,先给大伙看看我们这个黑箱内部的整个 Go 项目的文件目录结构:

├── conf                     # 配置文件存放目录,在1.1版本时增加
│   ├── config.yaml          # 配置文件,在1.1版本时增加
├── engine                   # 引擎包
│   ├── init.go              # 初始化
│   ├── order.go             # 委托单
│   ├── order_book.go        # 交易委托账本
│   ├── order_queue.go       # 订单队列
│   ├── run.go               # 具体交易对的撮合引擎启动入口
│   └── trade.go             # 成交记录
├── enum                     # 枚举类型的包
│   ├── order_action.go      # 订单行为,create为下单,cancel为撤单
│   ├── order_side.go        # 买卖方向,buy为买入,sell为卖出
│   ├── order_type.go        # 订单类型,MVP版本(1.0版本)只支持limit,1.3版本共支持7种类型 
│   └── sort_direction.go    # 排序方向,asc为升序,desc为降序
├── errcode                  #
│   ├── code.go              # 定义了各种不同的错误码
│   └── errcode.go           # 错误码的数据结构,包括code和msg两个字段
├── handler                  #
│   ├── close_matching.go    # 接收关闭撮合的请求
│   ├── handle_order.go      # 接收处理订单的请求
│   └── open_matching.go     # 接收开启撮合的请求
├── log                      # 日志包,在1.2版本增加
│   ├── log.go               # 日志输出,在1.2版本增加
├── main.go                  # Go程序唯一入口
├── middleware               # 中间件的包
│   ├── cache                # 缓存包
│   │   └── cache.go         # 缓存操作
│   ├── mq                   # 消息队列包
│   │   └── mq.go            # MQ操作
│   └── redis.go             # 主要做Redis初始化操作
└── process                  #
    ├── close_engine.go      # 关闭引擎
    ├── dispatch.go          # 分发订单
    ├── init.go              # 初始化
    └── new_engine.go        # 启动新引擎

包括 main 包,整个项目总共划分为了 10 个包和 1 个配置文件目录:

conf:存放配置文件的目录。main:main 包只有一个 main.go 文件,定义了程序入口函数。enum:枚举包实现了几个枚举类型的数据结构,包括订单行为、买卖方向、订单类型和排序方向。errcode:存放错误码的包,errcode.go 定义了错误码的数据结构,有 code 和 msg 两个属性;code.go 则定义了一些错误码对象。handler:接收 HTTP 请求的函数都放在这个包里,目前也就只有三个 handler 函数。process:启动、关闭引擎和分发订单的处理过程都在这个包里,包里还维护着不同交易对的订单通道,用来分发不同交易对的订单。engine:引擎包,包含了委托单、交易委托账本、订单队列、成交记录这几个核心的数据结构,以及用于处理交易对撮合的入口函数。middleware:存放中间件的包,目前只用到了 Redis 一个中间件。cache:缓存包,只有一个 cache.go 文件,缓存操作都在这个文件里定义。mq:消息队列包,也只有一个 mq.go 文件,消息的发送就定义在这里。log:日志包,实现了日志消息按日期分割并输出到文件。


小结


本节我们了解到撮合引擎作为一个通用组件,有标准的输入和输出,而且这输入和输出都非常简单。也开始给大家展示了黑箱内部的文件目录结构,开始探究黑箱的内部逻辑,后续章节将陆续揭露这些内部实现逻辑。

本节预留的思考题:揣测下为什么我要将下单和撤单定义到同一个接口?而不是分开两个接口?分两个接口和用一个接口各有何优劣?

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6天前
|
新零售
智慧农场认养模式系统开发|成熟方案|逻辑分析
新零售概念的提出也有三年时间了,不管是一级市场的创业者还是二级市场的公司
|
3月前
|
数据采集 监控 安全
量化交易源码开发丨量化交易系统开发成熟技术/教程方案/策略指南
定你的量化交易系统的需求和目标,包括交易策略、数据来源、风险管理等。
|
10月前
|
缓存 NoSQL Java
|
10月前
|
存储 安全 算法
Jogger跑鞋NFT铸造合成分红系统开发成熟技术方案及详细/源码功能
  区块链技术是利用块链式数据结构来验证与存储数据、利用分布式节点共识算法来生成和更新数据、利用密码学的方式保证数据传输和访问的安全、利用由自动化脚本代码组成的智能合约来编程和操作数据的一种全新的分布式基础架构与计算方式。
|
10月前
|
TensorFlow API 区块链
合约跟单开发案例丨合约跟单对接API火币/币安/OK交易所系统开发逻辑方案/成熟技术/项目案例/源码平台
dapp定制开发技术主要包括以太坊智能合约定制开发,包括智能合约语言Solidity开发,以太坊智能合约框架Truffle开发,Web3.js开发,以太坊区块链浏览器Mist开发等。这些技术可以帮助开发者快速构建出功能强大、可靠性高的dapp。
|
8月前
|
安全 区块链 UED
DAPP持币生息系统开发方案指南(成熟技术)
Web3.0不仅在技术层面上带来了变革,还对人们的生活产生了深远的影响
|
9月前
|
区块链
DAPP互助公排模型系统DAPP开发技术方案
// 参与互助公排 function participate() public { if (participants[msg.sender] == true) { revert(); }
|
9月前
|
存储 NoSQL 区块链
量化现货合约跟单交易软件系统开发(成熟技术)源码部署
我们需要一个全新的概念来定义业已带来的区块链时代,我们需要一个全新的名词来诠释业已到来的区块链时代
|
10月前
|
算法 机器人 API
量化交易机器人丨现货量化合约跟单系统开发(对接API火币/币安/OK/其他交易所)案例项目/方案设计/源码部署
量化的关键在于策略家预先建立的策略信号。比如有人用macd金叉作为进场信号,其实就是简单的量化;macd处理了一些基本的K线数据,然后画出来,就是量化,After processing the data with the golden cross structure on the chart,you choose to enter the market,which is quantitative trading.量化交易不是高频交易,每个指标其实都是一种量化,每个量化交易者都在创造一个新的指标;通过你理解的算法组合数据,用电脑计算,形成自己的交易系统,这就是真正的量化交易。
|
11月前
|
算法
量化交易现货合约跟单对冲系统开发详细案例/方案设计/功能说明/源码部署
  算法交易的主要类型有:(1)被动型算法交易,也称结构型算法交易。该交易算法除利用历史数据估计交易模型的关键参数外,不会根据市场的状况主动选择交易时机和交易的数量,而是按照一个既定的交易方针进行交易。该策略的的核心是减少滑价(目标价与实际成交均价的差)。被动型算法交易最成熟,使用也最为广泛,如在国际市场上使用最多的成交加权平均价格(VWAP)、时间加权平均价格(TWAP)等都属于被动型算法交易。