Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Ultra-fast matching engine written in Java based on LMAX Disruptor, Eclipse Collections, Real Logic Agrona, OpenHFT, LZ4 Java, and Adaptive Radix Trees.

License

NotificationsYou must be signed in to change notification settings

exchange-core/exchange-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build StatusJavadocsLanguage grade: Java

Exchange-core is anopen source market exchange core based onLMAX Disruptor,Eclipse Collections (ex. Goldman Sachs GS Collections),Real Logic Agrona,OpenHFT Chronicle-Wire,LZ4 Java,andAdaptive Radix Trees.

Exchange-core includes:

  • orders matching engine
  • risk control and accounting module
  • disk journaling and snapshots module
  • trading, admin and reports API

Designed for high scalability and pauseless 24/7 operation under high-load conditions and providing low-latency responses:

  • 3M users having 10M accounts in total
  • 100K order books (symbols) having 4M pending orders in total
  • less than 1ms worst wire-to-wire target latency for 1M+ operations per second throughput
  • 150ns per matching for large market orders

Single order book configuration is capable to process 5M operations per second on 10-years old hardware (Intel® Xeon® X5690) with moderate latency degradation:

rate50.0%90.0%95.0%99.0%99.9%99.99%worst
125K0.6µs0.9µs1.0µs1.4µs4µs24µs41µs
250K0.6µs0.9µs1.0µs1.4µs9µs27µs41µs
500K0.6µs0.9µs1.0µs1.6µs14µs29µs42µs
1M0.5µs0.9µs1.2µs4µs22µs31µs45µs
2M0.5µs1.2µs3.9µs10µs30µs39µs60µs
3M0.7µs3.6µs6.2µs15µs36µs45µs60µs
4M1.0µs6.0µs9µs25µs45µs55µs70µs
5M1.5µs9.5µs16µs42µs150µs170µs190µs
6M5µs30µs45µs300µs500µs520µs540µs
7M60µs1.3ms1.5ms1.8ms1.9ms1.9ms1.9ms

Latencies HDR Histogram

Benchmark configuration:

  • Single symbol order book.
  • 3,000,000 inbound messages are distributed as follows: 9% GTC orders, 3% IOC orders, 6% cancel commands, 82% move commands. About 6% of all messages are triggering one or more trades.
  • 1,000 active user accounts.
  • In average ~1,000 limit orders are active, placed in ~750 different price slots.
  • Latency results are only for risk processing and orders matching. Other stuff like network interface latency, IPC, journaling is not included.
  • Test data is not bursty, meaning constant interval between commands (0.2~8µs depending on target throughput).
  • BBO prices are not changing significantly throughout the test. No avalanche orders.
  • No coordinated omission effect for latency benchmark. Any processing delay affects measurements for next following messages.
  • GC is triggered prior/after running every benchmark cycle (3,000,000 messages).
  • RHEL 7.5, network-latency tuned-adm profile, dual X5690 6 cores 3.47GHz, one socket isolated and tickless, spectre/meltdown protection disabled.
  • Java version 8u192, newer Java 8 versions can have aperformance bug

Features

  • HFT optimized. Priority is a limit-order-move operation mean latency (currently ~0.5µs). Cancel operation takes ~0.7µs, placing new order ~1.0µs;
  • In-memory working state for accounting data and order books.
  • Event-sourcing - disk journaling and journal replay support, state snapshots (serialization) and restore operations, LZ4 compression.
  • Lock-free and contention-free orders matching and risk control algorithms.
  • No floating-point arithmetic, no loss of significance is possible.
  • Matching engine and risk control operations are atomic and deterministic.
  • Pipelined multi-core processing (based on LMAX Disruptor): each CPU core is responsible for certain processing stage, user accounts shard, or symbol order books shard.
  • Two different risk processing modes (specified per symbol): direct-exchange and margin-trade.
  • Maker/taker fees (defined in quote currency units).
  • Two order books implementations: simple implementation ("Naive") and performance implementation ("Direct").
  • Order types: Immediate-or-Cancel (IOC), Good-till-Cancel (GTC), Fill-or-Kill Budget (FOK-B)
  • Testing - unit-tests, integration tests, stress tests, integrity/consistency tests.
  • Low GC pressure, objects pooling, single ring-buffer.
  • Threads affinity (requires JNA).
  • User suspend/resume operation (reduces memory consumption).
  • Core reports API (user balances, open interest).

Installation

  1. Install library into your Maven's local repository by runningmvn install
  2. Add the following Maven dependency to your project'spom.xml:
<dependency>    <groupId>exchange.core2</groupId>    <artifactId>exchange-core</artifactId>    <version>0.5.3</version></dependency>

Alternatively, you can clone this repository and run theexample test.

Usage examples

Create and start empty exchange core:

// simple async events handlerSimpleEventsProcessoreventsProcessor =newSimpleEventsProcessor(newIEventsHandler() {@OverridepublicvoidtradeEvent(TradeEventtradeEvent) {System.out.println("Trade event: " +tradeEvent);    }@OverridepublicvoidreduceEvent(ReduceEventreduceEvent) {System.out.println("Reduce event: " +reduceEvent);    }@OverridepublicvoidrejectEvent(RejectEventrejectEvent) {System.out.println("Reject event: " +rejectEvent);    }@OverridepublicvoidcommandResult(ApiCommandResultcommandResult) {System.out.println("Command result: " +commandResult);    }@OverridepublicvoidorderBook(OrderBookorderBook) {System.out.println("OrderBook event: " +orderBook);    }});// default exchange configurationExchangeConfigurationconf =ExchangeConfiguration.defaultBuilder().build();// no serializationSupplier<ISerializationProcessor>serializationProcessorFactory = () ->DummySerializationProcessor.INSTANCE;// build exchange coreExchangeCoreexchangeCore =ExchangeCore.builder()        .resultsConsumer(eventsProcessor)        .serializationProcessorFactory(serializationProcessorFactory)        .exchangeConfiguration(conf)        .build();// start up disruptor threadsexchangeCore.startup();// get exchange API for publishing commandsExchangeApiapi =exchangeCore.getApi();

Create new symbol:

// currency code constantsfinalintcurrencyCodeXbt =11;finalintcurrencyCodeLtc =15;// symbol constantsfinalintsymbolXbtLtc =241;// create symbol specification and publish itCoreSymbolSpecificationsymbolSpecXbtLtc =CoreSymbolSpecification.builder()        .symbolId(symbolXbtLtc)// symbol id        .type(SymbolType.CURRENCY_EXCHANGE_PAIR)        .baseCurrency(currencyCodeXbt)// base = satoshi (1E-8)        .quoteCurrency(currencyCodeLtc)// quote = litoshi (1E-8)        .baseScaleK(1_000_000L)// 1 lot = 1M satoshi (0.01 BTC)        .quoteScaleK(10_000L)// 1 price step = 10K litoshi        .takerFee(1900L)// taker fee 1900 litoshi per 1 lot        .makerFee(700L)// maker fee 700 litoshi per 1 lot        .build();future =api.submitBinaryDataAsync(newBatchAddSymbolsCommand(symbolSpecXbtLtc));

Create new users:

// create user uid=301future =api.submitCommandAsync(ApiAddUser.builder()        .uid(301L)        .build());// create user uid=302future =api.submitCommandAsync(ApiAddUser.builder()        .uid(302L)        .build());

Perform deposits:

// first user deposits 20 LTCfuture =api.submitCommandAsync(ApiAdjustUserBalance.builder()        .uid(301L)        .currency(currencyCodeLtc)        .amount(2_000_000_000L)        .transactionId(1L)        .build());// second user deposits 0.10 BTCfuture =api.submitCommandAsync(ApiAdjustUserBalance.builder()        .uid(302L)        .currency(currencyCodeXbt)        .amount(10_000_000L)        .transactionId(2L)        .build());

Place orders:

// first user places Good-till-Cancel Bid order// he assumes BTCLTC exchange rate 154 LTC for 1 BTC// bid price for 1 lot (0.01BTC) is 1.54 LTC => 1_5400_0000 litoshi => 10K * 15_400 (in price steps)future =api.submitCommandAsync(ApiPlaceOrder.builder()        .uid(301L)        .orderId(5001L)        .price(15_400L)        .reservePrice(15_600L)// can move bid order up to the 1.56 LTC, without replacing it        .size(12L)// order size is 12 lots        .action(OrderAction.BID)        .orderType(OrderType.GTC)// Good-till-Cancel        .symbol(symbolXbtLtc)        .build());// second user places Immediate-or-Cancel Ask (Sell) order// he assumes wost rate to sell 152.5 LTC for 1 BTCfuture =api.submitCommandAsync(ApiPlaceOrder.builder()        .uid(302L)        .orderId(5002L)        .price(15_250L)        .size(10L)// order size is 10 lots        .action(OrderAction.ASK)        .orderType(OrderType.IOC)// Immediate-or-Cancel        .symbol(symbolXbtLtc)        .build());

Request order book:

future =api.requestOrderBookAsync(symbolXbtLtc,10);

GtC orders manipulations:

// first user moves remaining order to price 1.53 LTCfuture =api.submitCommandAsync(ApiMoveOrder.builder()        .uid(301L)        .orderId(5001L)        .newPrice(15_300L)        .symbol(symbolXbtLtc)        .build());// first user cancel remaining orderfuture =api.submitCommandAsync(ApiCancelOrder.builder()        .uid(301L)        .orderId(5001L)        .symbol(symbolXbtLtc)        .build());

Check user balance and GtC orders:

Future<SingleUserReportResult>report =api.processReport(newSingleUserReportQuery(301),0);

Check system balance:

// check fees collectedFuture<TotalCurrencyBalanceReportResult>totalsReport =api.processReport(newTotalCurrencyBalanceReportQuery(),0);System.out.println("LTC fees collected: " +totalsReport.get().getFees().get(currencyCodeLtc));

Testing

  • latency test: mvn -Dtest=PerfLatency#testLatencyMargin test
  • throughput test: mvn -Dtest=PerfThroughput#testThroughputMargin test
  • hiccups test: mvn -Dtest=PerfHiccups#testHiccups test
  • serialization test: mvn -Dtest=PerfPersistence#testPersistenceMargin test

TODOs

  • market data feeds (full order log, L2 market data, BBO, trades)
  • clearing and settlement
  • reporting
  • clustering
  • FIX and REST API gateways
  • cryptocurrency payment gateway
  • more tests and benchmarks
  • NUMA-aware and CPU layout custom configuration

Contributing

Exchange-core is an open-source project and contributions are welcome!

Support

Packages

No packages published

Contributors10


[8]ページ先頭

©2009-2025 Movatter.jp