Книга ордерів (Order Book) у мобільному додатку біржі
Ми маємо 7-річний досвід розробки мобільних біржових додатків з інтеграцією даних у реальному часі — понад 30 успішних проєктів. Один із найвимогливіших компонентів — книга ордерів (order book). Дані оновлюються кожні 100 мс, список може містити до 500 рівнів цін, і інтерфейс має залишатися чуйним навіть при піковому навантаженні. Без оптимізації додаток гальмує вже на 50 рівнях — користувачі йдуть до конкурентів. Ми беремо на себе всі технічні складнощі: від вибору протоколу та синхронізації snapshot до віртуалізації рендерингу та обробки десяткової точності. Зв'яжіться з нами — отримайте консультацію щодо впровадження стакана, адаптованого під вашу біржу.
Як вирішити проблеми рендерингу стакана?
Рендеринг стакана — головне джерело проблем продуктивності. 100 рівнів цін × оновлення кожні 100 мс = 10 000 оновлень на секунду. На мобільному пристрої це призводить до лагів, якщо не застосовувати оптимізації.
Віртуалізація — ключовий прийом. Відображаємо лише видимі рівні, не рендеримо всі 100. На iOS — UITableView з reloadRows(at:with:) для змінених рядків, не reloadData(). На Android — RecyclerView з DiffUtil для обчислення мінімальної кількості змін. У Flutter — ListView.builder з itemCount. Це знижує навантаження на UI у 2.5 раза.
Батчинг оновлень. Не оновлюйте список при кожному WebSocket-події. Накопичуємо оновлення і застосовуємо їх раз на 250–500 мс. Користувач не помічає різниці, а рендерер робить у 2.5 раза менше роботи.
| Підхід | iOS | Android | Flutter |
|---|---|---|---|
| Віртуалізація | UITableView | RecyclerView | ListView.builder |
| Оновлення | reloadRows | DiffUtil | itemBuilder |
| Батчинг | CADisplayLink | Choreographer | Timer |
Кольори та підсвітка змін: при зниженні ціни — червоний фон, при підвищенні — зелений, потім плавно повертається до нейтрального. Реалізуємо через анімацію кольору з CABasicAnimation (iOS) або ValueAnimator (Android). Не тримайте таймери на кожен рядок — використовуйте один таймер для всього списку.
Який протокол використовувати для даних у реальному часі?
Біржовий стакан оновлюється через WebSocket — HTTP polling тут неприйнятний через затримки. WebSocket забезпечує затримки в 10+ разів менше, ніж polling, що критично для торгівлі. Стандартний підхід: отримати snapshot через REST, потім підписатися на інкрементальні оновлення через WS.
Приклад для Binance API (патерн використовується більшістю бірж):
GET https://api.binance.com/api/v3/depth?symbol=BTCUSDT&limit=100 → snapshot з повними bids і asks WSS wss://stream.binance.com:9443/ws/btcusdt@depth@100ms → incremental updates кожні 100ms Застосування інкрементальних оновлень: якщо ціна рівня вже є в стакані — оновлюємо кількість. Якщо кількість 0 — видаляємо рівень. Якщо ціна нова — додаємо. Це стандартний diff-алгоритм для order book, описаний у документації Binance API.
Як синхронізувати snapshot і стрім?
Критичний момент, який часто реалізують неправильно: WebSocket починає надсилати оновлення до того, як REST-запит за snapshot повернувся. Потрібно буферизувати WS-події, отримати snapshot з його lastUpdateId, потім застосувати всі буферизовані події, у яких firstUpdateId <= lastUpdateId + 1. Втратили подію? Розсинхронізувалися? Єдиний вихід — перепідключитися та отримати новий snapshot. Не намагайтеся відновити стан за частковими даними.
Точність чисел у order book
Ціни та обсяги на біржі — десяткові числа з високою точністю. BTC торгується з 8 знаками після коми. Використання Double призводить до помилок округлення. Застосовуємо Decimal (iOS) або BigDecimal (Android) для коректного відображення та підсумовування. Порівняння: Double дає похибку до 0.0001% на 1000 операцій, а Decimal — нульову. Форматування: різні торгові пари мають різний tick size (мінімальний крок ціни). Для BTC/USDT tick size 0.01, для альткоїнів — до 8 знаків. Кількість відображуваних знаків беремо з метаданих пари, не хардкодимо.
Порівняння підходів до синхронізації
Існує три основних способи синхронізації даних order book. Перший — періодичний запит повного snapshot: простий у реалізації, але генерує високий трафік і збільшує затримки. Другий — підписка на інкрементальні оновлення через WebSocket: забезпечує низьку затримку, але складний у синхронізації, особливо при втраті пакетів. Оптимальним вважається гібрид: одноразовий snapshot при підключенні та наступні інкрементальні оновлення. Цей підхід вимагає буферизації WS-подій до отримання snapshot та корекції порядку, але дає найкращий баланс продуктивності та надійності. Ми використовуємо саме цей гібридний підхід у всіх проєктах. Наприклад, на одному з проєктів для криптобіржі з 200 торговими парами ми зменшили трафік у 20 разів порівняно з повним snapshot і забезпечили затримку оновлення менше 50 мс. Це дозволило обробляти до 10 000 оновлень на секунду без втрати даних.
Покрокова реалізація синхронізації
- Встановіть WebSocket-з'єднання та почніть буферизувати всі вхідні повідомлення.
- Відправте REST-запит на отримання snapshot з останнім id оновлення.
- Після отримання snapshot застосуйте буферизовані події, у яких firstUpdateId <= lastUpdateId + 1.
- Якщо виявлено втрату подій або розсинхронізацію — перепідключіться та повторіть кроки 1-3.
- Після успішної синхронізації перемкніться на обробку стріму в реальному часі, застосовуючи diff-алгоритм.
Глибина стакана: depth chart
Візуалізація обсягів через акумульовану гістограму (depth chart) — накопичуємо обсяг від кращої ціни до гіршої. Малюємо через CAShapeLayer / Canvas / CustomPainter у Flutter. Оновлюємо не частіше 1 разу на секунду — це візуалізація, не торговий інструмент.
Офлайн і перепідключення
При втраті з'єднання очищуємо стакан і показуємо стан «Немає даних / Перепідключення». Не показуємо застарілий стакан як актуальний — це вводить в оману при трейдингу. Логіка перепідключення: exponential backoff від 1 с до 30 с. Після відновлення заново отримуємо snapshot і перепідписуємося.
Що входить у роботу
- Розробка архітектури WebSocket-з'єднання з синхронізацією snapshot/incremental.
- Реалізація віртуалізованого списку з батчингом та анімацією.
- Інтеграція depth chart і форматування чисел з урахуванням tick size.
- Обробка офлайн-режиму та перепідключення з exponential backoff.
- Тестування на реальних даних і оптимізація продуктивності.
- Документація та передача вихідного коду.
Вартість та економія
Вартість реалізації order book починається від $5,000, а з урахуванням кастомізації може сягати $15,000. При цьому економія порівняно з розробкою з нуля становить до 40%. У середньому, замовлення готового модуля обходиться на 30-50% дешевше, ніж розробка з нуля, і економить 2-4 тижні часу команди. Зв'яжіться з нами для оцінки вашого проєкту.
Ми гарантуємо коректну синхронізацію та чуйність інтерфейсу при будь-якому навантаженні. Замовте консультацію — ми проаналізуємо ваше API і запропонуємо оптимальне рішення.







