When developing a digital asset exchange, choosing the right open-source framework is critical for achieving high performance, scalability, and reliability. The exchange-core framework stands out as a powerful solution, designed to meet the demanding requirements of modern trading platforms.
This article explores the key open-source components and architectural principles behind building a robust exchange core, providing insights for developers and technical architects.
What Is the Exchange-Core Framework?
Exchange-core is an open-source market exchange core built on several high-performance Java libraries. It is engineered for high scalability under heavy load, offering low-latency responses and uninterrupted 24/7 operation.
Key components of the framework include:
- An order matching engine
- Risk control and accounting modules
- Disk journaling and snapshot modules
- Trading, management, and reporting APIs
Its design prioritizes atomic and deterministic operations for both matching engines and risk controls, ensuring consistency and reliability.
Core Technologies and Dependencies
The exchange-core framework leverages several advanced open-source libraries:
- LMAX Disruptor: Facilitates high-throughput, low-latency inter-thread communication.
- Eclipse Collections: Delivers high-performance and memory-efficient data structures.
- Real Logic Agrona: Provides building blocks for concurrent and networked applications.
- OpenHFT Chronicle-Wire: Offers efficient data serialization and memory-mapped file support.
- LZ4 Java: Enables fast compression for journaling and snapshots.
- Adaptive Radix Trees: Allows for efficient indexing and data retrieval.
Performance Capabilities and Benchmarks
The exchange-core is designed for exceptional performance, capable of handling massive scale with minimal latency.
In benchmark tests, a single order book configuration processed 5 million operations per second on decade-old hardware (Intel® Xeon® X5690) with only moderate latency increases. The worst-case tail latency for over 1 million operations per second remained under 1 microsecond, while large market orders were matched in just 150 nanoseconds.
Latency distribution across various throughput levels demonstrates consistent performance:
| Rate (ops/sec) | 50.0% | 90.0% | 99.0% | 99.9% | Worst |
|---|---|---|---|---|---|
| 125K | 0.6µs | 0.9µs | 1.4µs | 4µs | 41µs |
| 500K | 0.6µs | 0.9µs | 1.6µs | 14µs | 42µs |
| 1M | 0.5µs | 0.9µs | 4µs | 22µs | 45µs |
| 3M | 0.7µs | 3.6µs | 15µs | 36µs | 60µs |
| 5M | 1.5µs | 9.5µs | 42µs | 150µs | 190µs |
These benchmarks were conducted using a single symbol order book with 3,000,000 inbound messages, 1,000 active user accounts, and approximately 1,000 active limit orders across 750 different price slots.
Key Features of Exchange-Core
The framework offers several distinctive features tailored for exchange development:
High-Frequency Trading Optimization
The system prioritizes average latency for limit order move operations (approximately 0.5µs), with cancel operations taking about 0.7µs and new order placement around 1.0µs.
In-Memory Operations
Both accounting data and order book working states are maintained in memory for maximum performance.
Event Sourcing Architecture
Supports disk journaling with log replay, state snapshots (serialization), recovery operations, and LZ4 compression.
Lock-Free Algorithms
Order matching and risk control algorithms are implemented without locks or contention points.
Precision Computing
Uses no floating-point operations, eliminating concerns about precision loss in financial calculations.
Multi-Core Processing
Utilizes pipelined processing based on LMAX Disruptor, where each CPU core handles specific processing stages, user account shards, or symbol order book fragments.
Getting Started with Exchange-Core
To begin using exchange-core in your project, first install the library to your local Maven repository by running:
mvn installThen add the following Maven dependency to your project's pom.xml file:
<dependency>
<groupId>exchange.core2</groupId>
<artifactId>exchange-core</artifactId>
<version>0.5.3</version>
</dependency>Alternatively, you can clone the repository and run the sample tests to explore functionality.
Basic Implementation Example
The following code demonstrates how to create and start an empty exchange core:
// Create simple async events handler
SimpleEventsProcessor eventsProcessor = new SimpleEventsProcessor(new IEventsHandler() {
@Override
public void tradeEvent(TradeEvent tradeEvent) {
System.out.println("Trade event: " + tradeEvent);
}
// Additional event handlers...
});
// Use default exchange configuration
ExchangeConfiguration conf = ExchangeConfiguration.defaultBuilder().build();
// Build exchange core
ExchangeCore exchangeCore = ExchangeCore.builder()
.resultsConsumer(eventsProcessor)
.serializationProcessorFactory(() -> DummySerializationProcessor.INSTANCE)
.exchangeConfiguration(conf)
.build();
// Start disruptor threads
exchangeCore.startup();
// Get exchange API for publishing commands
ExchangeApi api = exchangeCore.getApi();Creating Symbols and Users
Define currency codes and symbols for your exchange:
final int currencyCodeXbt = 11;
final int currencyCodeLtc = 15;
final int symbolXbtLtc = 241;
// Create symbol specification
CoreSymbolSpecification symbolSpecXbtLtc = CoreSymbolSpecification.builder()
.symbolId(symbolXbtLtc)
.type(SymbolType.CURRENCY_EXCHANGE_PAIR)
.baseCurrency(currencyCodeXbt)
.quoteCurrency(currencyCodeLtc)
.baseScaleK(1_000_000L)
.quoteScaleK(10_000L)
.takerFee(1900L)
.makerFee(700L)
.build();
// Submit symbol to exchange
future = api.submitBinaryDataAsync(new BatchAddSymbolsCommand(symbolSpecXbtLtc));Create user accounts with unique identifiers:
// Create user with uid=301
future = api.submitCommandAsync(ApiAddUser.builder()
.uid(301L)
.build());
// Create user with uid=302
future = api.submitCommandAsync(ApiAddUser.builder()
.uid(302L)
.build());Processing Deposits and Orders
Handle user deposits and order placement:
// First user deposits 20 LTC
future = api.submitCommandAsync(ApiAdjustUserBalance.builder()
.uid(301L)
.currency(currencyCodeLtc)
.amount(2_000_000_000L)
.transactionId(1L)
.build());
// Place Good-till-Cancel Bid order
future = api.submitCommandAsync(ApiPlaceOrder.builder()
.uid(301L)
.orderId(5001L)
.price(15_400L)
.reservePrice(15_600L)
.size(12L)
.action(OrderAction.BID)
.orderType(OrderType.GTC)
.symbol(symbolXbtLtc)
.build());Testing and Performance Validation
The framework includes comprehensive testing utilities:
- Latency testing:
mvn -Dtest=PerfLatency#testLatencyMargin test - Throughput testing:
mvn -Dtest=PerfThroughput#testThroughputMargin test - Hiccup testing:
mvn -Dtest=PerfHiccups#testHiccups test - Serialization testing:
mvn -Dtest=PerfPersistence#testPersistenceMargin test
These tests help validate performance characteristics under various load conditions.
👉 Explore advanced exchange development tools
Frequently Asked Questions
What makes exchange-core suitable for high-frequency trading?
Exchange-core is optimized for low latency, with limit order move operations averaging 0.5µs. Its lock-free algorithms, in-memory data storage, and pipelined multi-core processing make it ideal for high-frequency trading environments.
How does exchange-core ensure data persistence and recovery?
The framework uses an event sourcing architecture with disk journaling and LZ4 compression. It supports log replay, state snapshots, and recovery operations, ensuring data integrity even in unexpected shutdown scenarios.
Can exchange-core handle multiple currency pairs simultaneously?
Yes, the framework supports multiple order books (symbols) concurrently. Benchmark tests have demonstrated handling of 10,000 order books with 4 million pending orders across 1 million user accounts.
What risk control features does exchange-core provide?
The framework includes built-in risk control and accounting modules with two different risk processing modes per symbol: direct trading and margin trading. It also supports configurable maker/taker fee structures.
How does exchange-core achieve its high performance?
Performance is achieved through multiple strategies: object pooling, single ring buffers, thread affinity (with JNA), memory-only working state, and avoiding floating-point operations to prevent precision loss.
What order types does exchange-core support?
The framework supports Immediate-or-Cancel (IOC), Good-till-Cancel (GTC), and Fill-or-Kill Budget (FOK-B) order types, covering most trading needs for digital asset exchanges.
Future Development Roadmap
The exchange-core project continues to evolve with several planned enhancements:
- Market data feeds (complete order log, level 2 market data, BBO, trades)
- Clearing and settlement functionality
- Enhanced reporting capabilities
- Cluster support for distributed deployment
- FIX and REST API gateways
- Cryptocurrency payment gateway integration
- Additional testing and benchmarking tools
- NUMA-aware and custom CPU layout configurations
This ongoing development ensures that exchange-core remains at the forefront of exchange technology, providing developers with a robust foundation for building next-generation trading platforms.
Whether you're developing a centralized exchange, decentralized trading protocol, or hybrid solution, understanding and leveraging these open-source frameworks can significantly accelerate your development process while ensuring high performance and reliability.