交易所撮合引擎 flying-cattle-match-trade

Apache
Java
跨平台
2019-12-25
KINBUG-BP

疫情之下,程序员如何转型?共享数字化转型加速度,就在微软在线技术峰会>>>

match-engine

介绍

match-trade超高效的交易所撮合引擎,采用伦敦外汇交易所LMAX开源的Disruptor框架,用Hazelcast进行分布式内存存取,以及原子性操作。使用数据流的方式进行计算撮合序列,才用价格水平独立撮合逻辑,实现高效大数据撮合。

优势

  • match-engine是以水平价格为独立撮合逻辑,相比于别的订单队列为撮合队列的交易引擎来说,价格区间越小订单数越大时,性能越明显。
  • match-engine每个价格下的订单都是异步完成被撮合。独立价格下订单不影响下一个新发生的撮合。
  • match-engine每个价格撮合都是独立的,与下一个价格没的关系,实现快速吃单。
  • match-engine每个新的订单经历撮合处理器后,后续逻辑采用并行计算,能更快速反馈数据撮合结果。
  • match-engine撤单走独立的逻辑,不用和下单在一个处理序列。

技术选择

  • Disruptor: 号称每秒钟承载600万订单级别的无锁并行计算框架,主要选择原因还是并行计算。
  • Hazelcast: 能很好进行内存处理,有很强原子性保障的操作能力。同时分布式内存实现很简单,能自动内存集群。
  • Kafka: 比较适合大吞吐量的消息,有事务机制,同时能保证消息顺序消费。
  • WebFlux: 它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。

描述

用户输入包括:

  • 创建新的委托单(NewOrder):一个新的委托单可以作为交易撮合引擎的输入,引擎会尝试将其与已有的 委托单进行撮合。
  • 取消已有的委托单(CancelOrder):用户也可以取消一个之前输入的委托单,如果它还没有执行的话,即开口订单。

委托单:

  • 限价委托单
    限价委托单是在当前的加密货币交易环境中最常用的委托类型。这种委托单允许用户指定一个价格,只有当撮合引擎找到同样价格甚至更好价格的对手单时才执行交易。
  • 市价委托单
    市价委托单的撮合会完全忽略价格因素,而致力于有限完成指定数量的成交。市价委托单在交易委托账本中有较高的优先级,在流动性充足的市场中市价单可以保证成交。不充足时,撮合完最后一条撤销。
  • 止损委托单
    止损委托单尽在市场价格到达指定价位时才被激活,因此它的执行方式与市价委托单相反。一旦止损委托单激活,它们可以自动转化为市价委托单或限价委托单。(未实现)

撮合流程

限价撮合: 输入图片说明

市价撮合: 输入图片说明 目前就实现这两种订单撮合

订单簿为撮合簿时代码解析

这个是一个简单流盘口计算demo

//获取匹配的订单薄数据
IMap<Long, Order> outMap = hzInstance.getMap(HzltUtil.getMatchKey(coinTeam, isBuy));
/**
 * -★
 * -使用Java 8 Stream API中的并行流来计算最优
 * -能快速的拿到撮合对象,不用排序取值,降低性能消耗
 */
Order outOrder = outMap.values().parallelStream().min(HzltUtil::compareOrder).get();

//这种方式最难的,就是整理盘口深度数据了

    /**
     * -★
	 * -获取行情深度
	 * 
	 * @param coinTeam 交易队
	 * @param isBuy    是否是买
	 * @return List<Depth>
	 */
	public List<Depth> getMarketDepth(String coinTeam, Boolean isBuy) {
		List<Depth> depths = new ArrayList<Depth>();
		IMap<Long, Order> map = hzInstance.getMap(HzltUtil.getMatchKey(coinTeam, isBuy));
		if (map.size() > 0) {
			/**
			 * -这个流:主要是安价格分组和统计,使用并行流快速归集。
			 */ 
			List<Depth> list = map.entrySet().parallelStream().map(mo -> mo.getValue())
					.collect(Collectors.groupingBy(Order::getPrice)).entrySet().parallelStream()
					.map(ml -> new Depth(ml.getKey().toString(),
							ml.getValue().stream().map(o -> o.getUnFinishNumber()).reduce(BigDecimal.ZERO, BigDecimal::add)
									.toString(),
							"0", 1, coinTeam, isBuy))
					.sorted((d1, d2) -> HzltUtil.compareTo(d1, d2)).collect(Collectors.toList());
			/**
			 * -这个流:主要是盘口的累计计算,因涉及排序选择串行流
			 */
			list.stream().reduce(new Depth("0", "0", "0", 1, coinTeam, isBuy), (one, two) -> {
				one.setTotal((new BigDecimal(one.getTotal()).add(new BigDecimal(two.getNumber()))).toString());
				depths.add(new Depth(two.getPrice(), two.getNumber(), one.getTotal(), two.getPlatform(),
						two.getCoinTeam(), two.getIsBuy()));
				return one;
			});
		} else {
			Depth depth = new Depth("0", "0", "0", 1, coinTeam, isBuy);
			depths.add(depth);
		}
		return depths;
	}

测试结果

在我8cpu,16G内存的开发win10系统上测试结果:

  • Disruptor单生产者初始化10万不能撮合的订单耗时:约700毫秒
  • Disruptor多生产者初始化10万不能撮合的订单耗时:约20秒
  • 实际单吃完1-100价格内随机数量的10万订单耗时:约400毫秒
的码云指数为
超过 的项目
加载中

评论(0)

暂无评论

暂无资讯

暂无问答

SpringBoot 自动代码生成三层

前言 虽然mybatis已经有了代码生成,但是对于SpringBoot 项目来说生成的还是需要改动,而且也没得逻辑层,和控制层。但是这些东西是逃避不了,所以我就针对单表,做了一个代码生成器。 myba...

2018/07/10 10:33
6.8K
1
mysql8+mybatis-plus3.1自动生成带lombok和swagger和增删改查接口

mybatis-dsc-generator 还在为写swagger而烦恼吗?还在为忘记写注释而烦恼吗?还在为写简单的api接口而烦恼吗?mybatis-dsc-generator完美集成lombok,swagger的代码生成工具,让你不再为繁琐...

2019/04/11 11:29
7.1K
1
match VS match_phrase

最近稍微研究了一下ElasticSearch(下文简称ES),所谓可扩展的开源弹性搜索解决方案,跟同事笑称,如果它作为SQL SERVER的话,我的了解还在基本的select语句上,当然学习它也是一个积累知识...

2018/12/26 21:23
12
0
重要提醒 | 手动轮换Rancher Kubernetes集群的证书

在Rancher 2.0和2.1中,Rancher配置集群的自动生成证书的有效期为1年,本文将为您详细介绍如何轮换证书,即使您的证书已经过期也可从文章中获得具体的操作指南。 Kubernetes集群通常使用ssl...

2019/07/01 10:45
186
0
企业支付宝账号开发接口教程--JAVA-UTF-8(实际操作------SpringMVC+JSP)

企业支付宝账号开发教程--JAVA-UTF-8 账号注册就自己去注册吧。API,开发。网站建设。电子账单。支付宝付款。SpringMVC+JSP开发企业支付宝

2014/09/15 17:28
9.1W
36
NEST与JSON语法对照 一 match与multi_match

NEST与JSON语法对照 一 match与multi_match

2016/06/13 12:00
175
0
match_parent和fill_parent

match_parent和fill_parent

2014/03/09 20:54
151
0
match_parent和fill_parent有什么区别? - What is the difference between match_parent and fill_parent?

问题: I'm a little confused about two XML properties: match_parent and fill_parent . 我对两个XML属性有点困惑: match_parent和fill_parent 。 It seems that both are the same. 似乎...

前天 00:55
93
0
String Match

本文主要总结一下《算法导论》一书中基础的字符串匹配的算法思想,希望在处理相关问题的时候可以有所参考。可能书中的讲的东西比较晦涩,我也不太清楚为何晦涩的东西都会被奉为经典,我还是一...

2016/08/20 15:01
14
0
Objective-C选择器 Selector

SEL类型 1 id cattle[3]; 2 SEL say; 3 SEL skin; 其中id cattle[3]定义了一个数组用于存储Cattle或者Bull对象。这一行代码估计大家都很熟悉,笔者就不赘述了。像这样的传统的数组并不能完全...

2011/09/09 15:06
449
0

没有更多内容

加载失败,请刷新页面

返回顶部
顶部