Розробка торговельного двигуна (matching engine)

Уявіть: ваша криптобіржа втрачає мілісекунди на кожному ордері, хайп-трейдери йдуть до конкурентів з latency у 10 мкс. Matching engine — це серце біржі, і його продуктивність безпосередньо конвертується у виручку. Помилка в логіці matching може коштувати мільйони, а кожна мікросекунда затримки знижу

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1003

Уявіть: ваша криптобіржа втрачає мілісекунди на кожному ордері, хайп-трейдери йдуть до конкурентів з latency у 10 мкс. Matching engine — це серце біржі, і його продуктивність безпосередньо конвертується у виручку. Помилка в логіці matching може коштувати мільйони, а кожна мікросекунда затримки знижує конкурентоспроможність. Ми розробляємо кастомні matching engine для бірж, що працюють на Ethereum, Solana та інших L1/L2. Розберемо, як ми будуємо системи, що витримують 10 000+ ордерів на секунду з latency менше 10 мікросекунд. Наш досвід — 10+ років у high-load системах, 50+ проектів у фінансовому секторі. Зв'яжіться з нами — оцінимо ваш проект безкоштовно.

Чому варто використовувати integer ціни?

Floating point arithmetic неприпустима в фінансових розрахунках — 0.1 + 0.2 != 0.3 в IEEE 754. Натомість використовуємо integer з фіксованою точністю (10^8). Це виключає помилки округлення та прискорює порівняння.

const PRICE_PRECISION: i64 = 100_000_000; let price: i64 = 4_375_050_000_000; // 43750.50000000 fn float_to_price(f: f64) -> Price { (f * PRICE_PRECISION as f64).round() as Price } 

Як працює price-time priority?

Стандартний алгоритм: Price priority — ордер з кращою ціною виконується першим. При рівній ціні — Time priority (FIFO). Для покупок краща ціна — вища (готовий платити більше), для продажів — нижча.

Структура Order Book

Використовуємо BTreeMap для цінових рівнів (O(log n)) та HashMap для швидкого доступу за ID ордера. Це дає баланс між швидкістю вставки та пошуку. У високонавантажених системах альтернативи — SkipList (Java ConcurrentSkipListMap) або array-based структури з біннінгом цін.

pub struct OrderBook { pub bids: BTreeMap<Reverse<Price>, PriceLevel>, pub asks: BTreeMap<Price, PriceLevel>, pub orders: HashMap<OrderId, Order>, } 

Алгоритм matching: від limit до stop orders

Limit order matching працює так: taker шукає кращий протилежний ордер, виконує за ціною maker-а, частково або повністю. Market order не має price limit — виконується до кінця книги, залишок скасовується. Stop orders активуються при досягненні тригерної ціни. Fill-or-Kill (FOK) вимагає повного виконання, інакше скасування. Iceberg orders маскують реальний обсяг. Реалізація всіх типів з event sourcing гарантує консистентність.

// Спрощений matching loop while taker.remaining() > 0 { let best_ask = self.asks.keys().next()?; if taker.price < best_ask { break; } // execute against level } 

Як LMAX Disruptor підвищує продуктивність?

LMAX Disruptor — lock-free ring buffer для inter-thread комунікації. Він використовує CAS-операції замість м'ютексів, забезпечуючи latency 1-2 ns проти ~100 ns у mutex. Ми застосовуємо його в Java-рішеннях, в Rust — аналоги (crossbeam channel). У тестах Rust з crossbeam показує P99 нижче 100 µs навіть під навантаженням 20 000 ордерів на секунду.

Типові bottlenecks та їх вирішення

  1. Memory allocation — object pool/arena allocator
  2. Serialization — FlatBuffers/Cap'n Proto замість JSON
  3. Locking — single-threaded per-symbol + lock-free queues
  4. Cache misses — SoA замість AoS

Порівняння мов за latency:

Реалізація P50 P99 P99.9
Python (asyncio) 2ms 15ms 100ms
Go 200µs 2ms 10ms
Java (Disruptor) 50µs 500µs 2ms
Rust (custom) 10µs 100µs 500µs
C++ (HFT grade) 1-5µs 20µs 100µs

P99.9 особливо важливий — туди потрапляють скарги трейдерів на "гальма". Rust у 20 разів швидше Python для matching engine, що безпосередньо впливає на прибуток біржі.

Порівняння структур даних для Order Book

Структура Вставка Пошук кращого Підходить для
BTreeMap O(log n) O(log n) Універсальний
SkipList O(log n) O(log n) Багатопотокове середовище
Array + bucket O(1) O(1) Фіксовані тіки
HashMap + price levels O(1) O(1) Високочастотний трейдинг

Які тести гарантують коректність?

Використовуємо event sourcing: всі події пишуться в Kafka, downstream консьюмери асинхронно оновлюють базу. При рестарті стан відновлюється з snapshot + replay.

class MatchingEngineRecovery: def restore_order_book(self, symbol): snapshot = self.load_snapshot(symbol) book = OrderBook.from_snapshot(snapshot) for event in self.kafka.get_events_after(symbol, snapshot.sequence): book.apply_event(event) return book 

Тестуємо тисячами unit-тестів, property-based fuzzing, порівнянням з reference implementation. Це гарантує коректність навіть в екзотичних сценаріях. Згідно з дослідженнями IEEE, property-based тестування виявляє на 60% більше помилок у фінансових системах.

Що входить в розробку matching engine?

  • Документація з API та архітектури
  • Доступ до репозиторію з CI/CD
  • Навчання вашої команди (2 дні)
  • Підтримка 3 місяці після запуску
  • Інтеграція з вашою системою через Kafka та REST/WebSocket
  • Навантажувальне тестування з емуляцією ринкових даних

Процес та строки

Аналітика → проектування (архітектура, вибір мови) → реалізація (core, тести) → інтеграція з вашою системою → навантажувальне тестування → деплой. Строки: від 2 до 6 місяців залежно від складності. Вартість розраховується індивідуально. Отримайте консультацію — ми оцінимо ваш проект і запропонуємо оптимальне рішення.