{"id":13630884,"url":"https://github.com/exchange-core/exchange-core","last_synced_at":"2025-05-15T04:04:21.520Z","repository":{"id":37695079,"uuid":"143637640","full_name":"exchange-core/exchange-core","owner":"exchange-core","description":"Ultra-fast matching engine written in Java based on LMAX Disruptor, Eclipse Collections, Real Logic Agrona, OpenHFT, LZ4 Java, and Adaptive Radix Trees.","archived":false,"fork":false,"pushed_at":"2023-10-08T18:06:59.000Z","size":1612,"stargazers_count":2204,"open_issues_count":64,"forks_count":848,"subscribers_count":115,"default_branch":"master","last_synced_at":"2025-04-14T04:59:11.886Z","etag":null,"topics":["bitcoin","cryptocurrency","cryptocurrency-exchanges","exchange","exchange-api","forex-trading","hft","hft-trading","java","lmax-disruptor","lock-free","low-latency","matching-algorithm","matching-engine","order-book","stock-exchange","stock-market","stock-trading","trading-api","trading-platform"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exchange-core.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-08-05T18:25:16.000Z","updated_at":"2025-04-14T03:11:24.000Z","dependencies_parsed_at":"2024-01-14T06:52:58.561Z","dependency_job_id":"b7ee2e52-5c61-481d-959e-222993dad3d1","html_url":"https://github.com/exchange-core/exchange-core","commit_stats":null,"previous_names":["mzheravin/exchange-core"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exchange-core%2Fexchange-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exchange-core%2Fexchange-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exchange-core%2Fexchange-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exchange-core%2Fexchange-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exchange-core","download_url":"https://codeload.github.com/exchange-core/exchange-core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270640,"owners_count":22042858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","cryptocurrency","cryptocurrency-exchanges","exchange","exchange-api","forex-trading","hft","hft-trading","java","lmax-disruptor","lock-free","low-latency","matching-algorithm","matching-engine","order-book","stock-exchange","stock-market","stock-trading","trading-api","trading-platform"],"created_at":"2024-08-01T22:02:02.041Z","updated_at":"2025-05-15T04:04:21.475Z","avatar_url":"https://github.com/exchange-core.png","language":"Java","funding_links":[],"categories":["Java"],"sub_categories":[],"readme":"# exchange-core\n[![Build Status](https://travis-ci.org/mzheravin/exchange-core.svg?branch=master)](https://travis-ci.org/mzheravin/exchange-core)\n[![Javadocs](https://www.javadoc.io/badge/exchange.core2/exchange-core.svg)](https://www.javadoc.io/doc/exchange.core2/exchange-core)\n[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/mzheravin/exchange-core.svg?logo=lgtm\u0026logoWidth=18)](https://lgtm.com/projects/g/mzheravin/exchange-core/context:java)\n[![][license img]][license]\n\nExchange-core is an **open source market exchange core** based on \n[LMAX Disruptor](https://github.com/LMAX-Exchange/disruptor), \n[Eclipse Collections](https://www.eclipse.org/collections/) (ex. Goldman Sachs GS Collections), \n[Real Logic Agrona](https://github.com/real-logic/agrona),\n[OpenHFT Chronicle-Wire](https://github.com/OpenHFT/Chronicle-Wire),\n[LZ4 Java](https://github.com/lz4/lz4-java),\nand [Adaptive Radix Trees](https://db.in.tum.de/~leis/papers/ART.pdf).\n\nExchange-core includes:\n- orders matching engine\n- risk control and accounting module\n- disk journaling and snapshots module\n- trading, admin and reports API\n\nDesigned for high scalability and pauseless 24/7 operation under high-load conditions and providing low-latency responses:\n- 3M users having 10M accounts in total\n- 100K order books (symbols) having 4M pending orders in total\n- less than 1ms worst wire-to-wire target latency for 1M+ operations per second throughput\n- 150ns per matching for large market orders\n\nSingle order book configuration is capable to process 5M operations per second on 10-years old hardware (Intel® Xeon® X5690) with moderate latency degradation:\n\n|rate|50.0%|90.0%|95.0%|99.0%|99.9%|99.99%|worst|\n|----|-----|-----|-----|-----|-----|------|-----|\n|125K|0.6µs|0.9µs|1.0µs|1.4µs|4µs  |24µs  |41µs |\n|250K|0.6µs|0.9µs|1.0µs|1.4µs|9µs  |27µs  |41µs |\n|500K|0.6µs|0.9µs|1.0µs|1.6µs|14µs |29µs  |42µs |\n|  1M|0.5µs|0.9µs|1.2µs|4µs  |22µs |31µs  |45µs |\n|  2M|0.5µs|1.2µs|3.9µs|10µs |30µs |39µs  |60µs |\n|  3M|0.7µs|3.6µs|6.2µs|15µs |36µs |45µs  |60µs |\n|  4M|1.0µs|6.0µs|9µs  |25µs |45µs |55µs  |70µs |\n|  5M|1.5µs|9.5µs|16µs |42µs |150µs|170µs |190µs|\n|  6M|5µs  |30µs |45µs |300µs|500µs|520µs |540µs|\n|  7M|60µs |1.3ms|1.5ms|1.8ms|1.9ms|1.9ms |1.9ms|\n\n![Latencies HDR Histogram](hdr-histogram.png)\n\nBenchmark configuration:\n- Single symbol order book.\n- 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.\n- 1,000 active user accounts.\n- In average ~1,000 limit orders are active, placed in ~750 different price slots.\n- Latency results are only for risk processing and orders matching. Other stuff like network interface latency, IPC, journaling is not included.\n- Test data is not bursty, meaning constant interval between commands (0.2~8µs depending on target throughput).\n- BBO prices are not changing significantly throughout the test. No avalanche orders.\n- No coordinated omission effect for latency benchmark. Any processing delay affects measurements for next following messages.\n- GC is triggered prior/after running every benchmark cycle (3,000,000 messages).\n- RHEL 7.5, network-latency tuned-adm profile, dual X5690 6 cores 3.47GHz, one socket isolated and tickless, spectre/meltdown protection disabled.\n- Java version 8u192, newer Java 8 versions can have a [performance bug](https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8221355)\n\n### Features\n- 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;\n- In-memory working state for accounting data and order books.\n- Event-sourcing - disk journaling and journal replay support, state snapshots (serialization) and restore operations, LZ4 compression.\n- Lock-free and contention-free orders matching and risk control algorithms.\n- No floating-point arithmetic, no loss of significance is possible.\n- Matching engine and risk control operations are atomic and deterministic.\n- 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.\n- Two different risk processing modes (specified per symbol): direct-exchange and margin-trade.\n- Maker/taker fees (defined in quote currency units).\n- Two order books implementations: simple implementation (\"Naive\") and performance implementation (\"Direct\").\n- Order types: Immediate-or-Cancel (IOC), Good-till-Cancel (GTC), Fill-or-Kill Budget (FOK-B)\n- Testing - unit-tests, integration tests, stress tests, integrity/consistency tests.\n- Low GC pressure, objects pooling, single ring-buffer.\n- Threads affinity (requires JNA).\n- User suspend/resume operation (reduces memory consumption).\n- Core reports API (user balances, open interest).\n\n### Installation\n1. Install library into your Maven's local repository by running `mvn install`\n2. Add the following Maven dependency to your project's `pom.xml`:\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003eexchange.core2\u003c/groupId\u003e\n    \u003cartifactId\u003eexchange-core\u003c/artifactId\u003e\n    \u003cversion\u003e0.5.3\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nAlternatively, you can clone this repository and run the [example test](https://github.com/mzheravin/exchange-core/tree/master/src/test/java/exchange/core2/tests/examples/ITCoreExample.java).\n\n### Usage examples\nCreate and start empty exchange core:\n```java\n// simple async events handler\nSimpleEventsProcessor eventsProcessor = new SimpleEventsProcessor(new IEventsHandler() {\n    @Override\n    public void tradeEvent(TradeEvent tradeEvent) {\n        System.out.println(\"Trade event: \" + tradeEvent);\n    }\n\n    @Override\n    public void reduceEvent(ReduceEvent reduceEvent) {\n        System.out.println(\"Reduce event: \" + reduceEvent);\n    }\n\n    @Override\n    public void rejectEvent(RejectEvent rejectEvent) {\n        System.out.println(\"Reject event: \" + rejectEvent);\n    }\n\n    @Override\n    public void commandResult(ApiCommandResult commandResult) {\n        System.out.println(\"Command result: \" + commandResult);\n    }\n\n    @Override\n    public void orderBook(OrderBook orderBook) {\n        System.out.println(\"OrderBook event: \" + orderBook);\n    }\n});\n\n// default exchange configuration\nExchangeConfiguration conf = ExchangeConfiguration.defaultBuilder().build();\n\n// no serialization\nSupplier\u003cISerializationProcessor\u003e serializationProcessorFactory = () -\u003e DummySerializationProcessor.INSTANCE;\n\n// build exchange core\nExchangeCore exchangeCore = ExchangeCore.builder()\n        .resultsConsumer(eventsProcessor)\n        .serializationProcessorFactory(serializationProcessorFactory)\n        .exchangeConfiguration(conf)\n        .build();\n\n// start up disruptor threads\nexchangeCore.startup();\n\n// get exchange API for publishing commands\nExchangeApi api = exchangeCore.getApi();\n```\n\nCreate new symbol:\n```java\n// currency code constants\nfinal int currencyCodeXbt = 11;\nfinal int currencyCodeLtc = 15;\n\n// symbol constants\nfinal int symbolXbtLtc = 241;\n\n// create symbol specification and publish it\nCoreSymbolSpecification symbolSpecXbtLtc = CoreSymbolSpecification.builder()\n        .symbolId(symbolXbtLtc)         // symbol id\n        .type(SymbolType.CURRENCY_EXCHANGE_PAIR)\n        .baseCurrency(currencyCodeXbt)    // base = satoshi (1E-8)\n        .quoteCurrency(currencyCodeLtc)   // quote = litoshi (1E-8)\n        .baseScaleK(1_000_000L) // 1 lot = 1M satoshi (0.01 BTC)\n        .quoteScaleK(10_000L)   // 1 price step = 10K litoshi\n        .takerFee(1900L)        // taker fee 1900 litoshi per 1 lot\n        .makerFee(700L)         // maker fee 700 litoshi per 1 lot\n        .build();\n\nfuture = api.submitBinaryDataAsync(new BatchAddSymbolsCommand(symbolSpecXbtLtc));\n```\n\nCreate new users:\n```java\n// create user uid=301\nfuture = api.submitCommandAsync(ApiAddUser.builder()\n        .uid(301L)\n        .build());\n\n// create user uid=302\nfuture = api.submitCommandAsync(ApiAddUser.builder()\n        .uid(302L)\n        .build());\n```\n\nPerform deposits:\n```java\n// first user deposits 20 LTC\nfuture = api.submitCommandAsync(ApiAdjustUserBalance.builder()\n        .uid(301L)\n        .currency(currencyCodeLtc)\n        .amount(2_000_000_000L)\n        .transactionId(1L)\n        .build());\n\n// second user deposits 0.10 BTC\nfuture = api.submitCommandAsync(ApiAdjustUserBalance.builder()\n        .uid(302L)\n        .currency(currencyCodeXbt)\n        .amount(10_000_000L)\n        .transactionId(2L)\n        .build());\n```\n\nPlace orders:\n```java\n// first user places Good-till-Cancel Bid order\n// he assumes BTCLTC exchange rate 154 LTC for 1 BTC\n// bid price for 1 lot (0.01BTC) is 1.54 LTC =\u003e 1_5400_0000 litoshi =\u003e 10K * 15_400 (in price steps)\nfuture = api.submitCommandAsync(ApiPlaceOrder.builder()\n        .uid(301L)\n        .orderId(5001L)\n        .price(15_400L)\n        .reservePrice(15_600L) // can move bid order up to the 1.56 LTC, without replacing it\n        .size(12L) // order size is 12 lots\n        .action(OrderAction.BID)\n        .orderType(OrderType.GTC) // Good-till-Cancel\n        .symbol(symbolXbtLtc)\n        .build());\n\n// second user places Immediate-or-Cancel Ask (Sell) order\n// he assumes wost rate to sell 152.5 LTC for 1 BTC\nfuture = api.submitCommandAsync(ApiPlaceOrder.builder()\n        .uid(302L)\n        .orderId(5002L)\n        .price(15_250L)\n        .size(10L) // order size is 10 lots\n        .action(OrderAction.ASK)\n        .orderType(OrderType.IOC) // Immediate-or-Cancel\n        .symbol(symbolXbtLtc)\n        .build());\n```\n\nRequest order book:\n```java\nfuture = api.requestOrderBookAsync(symbolXbtLtc, 10);\n```\n\nGtC orders manipulations:\n```java\n// first user moves remaining order to price 1.53 LTC\nfuture = api.submitCommandAsync(ApiMoveOrder.builder()\n        .uid(301L)\n        .orderId(5001L)\n        .newPrice(15_300L)\n        .symbol(symbolXbtLtc)\n        .build());\n        \n// first user cancel remaining order\nfuture = api.submitCommandAsync(ApiCancelOrder.builder()\n        .uid(301L)\n        .orderId(5001L)\n        .symbol(symbolXbtLtc)\n        .build());\n```\n\nCheck user balance and GtC orders:\n```java\nFuture\u003cSingleUserReportResult\u003e report = api.processReport(new SingleUserReportQuery(301), 0);\n```\n\nCheck system balance:\n```java\n// check fees collected\nFuture\u003cTotalCurrencyBalanceReportResult\u003e totalsReport = api.processReport(new TotalCurrencyBalanceReportQuery(), 0);\nSystem.out.println(\"LTC fees collected: \" + totalsReport.get().getFees().get(currencyCodeLtc));\n```\n\n### Testing\n- latency test: mvn -Dtest=PerfLatency#testLatencyMargin test\n- throughput test: mvn -Dtest=PerfThroughput#testThroughputMargin test\n- hiccups test: mvn -Dtest=PerfHiccups#testHiccups test\n- serialization test: mvn -Dtest=PerfPersistence#testPersistenceMargin test\n\n### TODOs\n- market data feeds (full order log, L2 market data, BBO, trades)\n- clearing and settlement\n- reporting\n- clustering\n- FIX and REST API gateways\n- cryptocurrency payment gateway\n- more tests and benchmarks\n- NUMA-aware and CPU layout custom configuration\n\n### Contributing\nExchange-core is an open-source project and contributions are welcome!\n\n### Support\n- [Discussion group in Telegram (t.me/exchangecoretalks)](https://t.me/exchangecoretalks)\n- [News channel in Telegram (t.me/exchangecore)](https://t.me/exchangecore)\n\n[license]:LICENSE.txt\n[license img]:https://img.shields.io/badge/License-Apache%202-blue.svg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexchange-core%2Fexchange-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexchange-core%2Fexchange-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexchange-core%2Fexchange-core/lists"}