Exchange brokerage transactions [1]

Keywords: Programming Database Redis MongoDB Java

Preface

Recently, I have been researching the stock (currency) exchange matching engine. From a concept of matching that is not clear enough, I am gradually exploring some of my own understanding and concepts.So I'm going to write a matching engine, and I want to get the people together to make a good engine.

Matching rules

This is mainly to achieve, limit price and market price transactions;

Matching rules:
(1) If the purchase price is greater than or equal to the selling price, the transaction may be concluded. The transaction price is defined as the price customizer by hanging the bill first;
(2) The same price, which is traded earlier than the time limit.
(3) The market price is the first to be traded, with the opponent price as the transaction price.

Parking Architecture and Technical Qualitative

Architectural and technical qualitative factors:
1. The nature of matching is a single linear process, which cannot be concurrent.(If you have one, please ask God to point out...
2. Use a single order as the matching logic (finish a single order and take the next one from the order book), the rating is too high and takes a long time.
3. Database matching, not considered, only memory matching.
4. When matching up: just come up with the best, no sorting required.
5. Match results: You don't need to care who you deal with.Combining the second point makes each price level logically independent.Decrease frequency.

Framework and technology options:
Thread Framework Selection: "LMAX Open Source Disruptor Framework for the London Exchange", performance is explained in more detail.
Memory Framework Selection: Start with redis and decide to use Hazelcast The main reason is simple, fast and easy to cluster.
Database selection: Because the project is basically data flow development, consider mongodb based on industry friendly aspects of data flow support
Get the best match in parallel stream computing when you order.
Complete the k-line data disc depth data generation with Flink or the Rule Engine after the matching.(still under consideration)

Implementation of Some Technologies

Because some of my friends used to make thin orders, I also made this happen. Here are some important details of the code:

//Get matching order book data
IMap<Long, Order> outMap = hzInstance.getMap(HzltUtil.getMatchKey(coinTeam, isBuy));
/**
 * -★
 * -Computing optimum using parallel streams in the Java 8 Stream API
 * -Quickly get matched objects without sorting values, reducing performance consumption
 */
Order outOrder = outMap.values().parallelStream().min(HzltUtil::compareOrder).get();

//The hardest way to do this is to sort out the disk depth data.

    /**
     * -★
	 * -Get Market Depth
	 * 
	 * @param coinTeam Trading Team
	 * @param isBuy    Is it purchased
	 * @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) {
			/**
			 * -This flow: mainly price grouping and statistics, using parallel flow for fast aggregation.
			 */ 
			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());
			/**
			 * -This stream: mainly the cumulative calculation of the disk port, because it involves sorting to select the serial stream
			 */
			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;
	}

This method has a lot of records, changes to orders are frequent, there is a lot of pressure on the database, and the magnitude of the calculation is also huge, so discard...

Unsolved Issues

Question 1: When the market price empties the opponent's plate, will it be billed at the last transaction price or canceled directly?If it is a bill of lading, will it become a limited price bill?

Question 2: After the market price is purchased, the money left can not be purchased even the smallest unit. What should I do?Undo it directly?Is there a revocation record?

Question 3: I have seen some friends divide the trading price into two matching queues, so to buy and sell the market price at the same time, is it two or more last trading prices or do they eat each other?


                        

Posted by Texan on Fri, 29 Nov 2019 00:09:30 -0800