Реалізація екрану торговлі (Trading View) в мобільному приложенні біржі
Екран торговлі в біржевому приложенні — один з найтехнічно щільних UI в мобільній розробці. Свічний графік зі сотнями точок даних, стакан котировок з оновленням у реальному часі, форма ордера з мгновенною валідацією, та все це має працювати на 60 fps при WebSocket-потоці з 10 оновленнями в секунду. Саме тут продуктивність прямо впливає на гроші користувача.
Архітектура даних та real-time оновлення
WebSocket та управління потоком даних
Біржові дані приходять по WebSocket — підписка на пари, отримання тиків та оновлень стакана. На iOS — URLSessionWebSocketTask (нативний, з iOS 13) або бібліотека Starscream для гнучкішого управління reconnect-логікою. На Android — OkHttp WebSocket або Ktor WebSocket client.
Критично важлива стратегія throttling вхідних даних. WebSocket може присилати 20–50 оновлень в секунду для активних пар. Обновляти UI на кожне — перегрузка main thread. Правильний підхід: накопичуємо оновлення в ConcurrentQueue на background thread, застосовуємо до UI з частотою 60fps (через CADisplayLink на iOS або Choreographer на Android).
Модель даних стакана
Order book — це sorted structure: bids (покупки) відсортовані по убуванню ціни, asks (продажі) по зростанню. SortedArray або TreeMap (Java) / AVLTree (Swift кастомна реалізація) для O(log n) вставки та видалення при оновленнях. Оновлення стакана — не повна заміна, а patch: новий рівень, змінений volume, видалений рівень (volume = 0).
Для iOS стакана — NSFetchedResultsController-паттерн без CoreData: зберігаємо bids: [(price: Decimal, size: Decimal)] та asks, при зміні — diffing через DeepDiff або Swift's CollectionDifference для мінімальних UITableView updates.
Свічний графік
Кастомна отрисовка через Core Graphics
Стандартний UIKit / View занадто повільний для інтерактивного свічного графіка з 1000+ свічей. Варіанти:
Core Graphics / UIKit Drawing. UIView.draw(_:) з UIGraphicsGetCurrentContext(). Кожна свіча — два прямокутники (тіло та тінь) через context.fill(). Для 500 свічей у draw(_:) — 8–12 мс на iPhone 12, що вписується в 16 мс frame budget. Не рекомендується для 2000+ свічей або анімованих оновлень.
Metal. Для професійних trading-приложень з анімованим scalable графіком — MetalKit. MTLBuffer з vertex data для свічей, vertex shader рисує прямокутники в простору екрану. 10 000 свічей — 1–2 мс render time. TradingView (веб) використовує canvas з WebGL — той же принцип.
Готові бібліотеки. Charts (Daniel Gindi) — популярна iOS/macOS бібліотека, має CandleStickChartView. Не real-time, але для періодичних оновлень підходить. LightweightCharts — офіційна мобільна обертка над TradingView Lightweight Charts (WebView-based). Найшвидший шлях до production-ready графіка з технічними індикаторами.
Жести та навігація по графіку
Pinch для масштабування, pan для переміщення по часовій осі. UIPinchGestureRecognizer + UIPanGestureRecognizer одночасно через gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) -> true.
При масштабуванні — visibleRange міняється, завантажуємо історичні свічі для нового діапазону через REST API. Infinite scroll вліво: при досягненні leftEdge — запит історичних даних, додання на початок без скидання поточної позиції (обновляємо contentOffset на ширину доданих свічей).
Crosshair при long press — UILongPressGestureRecognizer з minimumPressDuration = 0.1. При русі пальця — обновляємо позицію crosshair та OHLCV-тултіп з даними свічі під курсором. Hit-test по X-координаті: candleIndex = Int((touchX - chartOriginX) / (candleWidth + candleSpacing)).
Форма ордера
Валідація та ввід ціни/об'єму
UITextField з inputView — кастомна цифрова клавіатура замість системної. На ній — кнопки 25%, 50%, 75%, 100% від доступного балансу для швидкого вводу. Decimal для зберігання, не Double.
Мгновенна валідація при вводі: мінімальний об'єм, крок ціни (tick size), доступний баланс. Combine publisher(for: \.text) на UITextField з debounce(0.1) та map { Decimal(string: $0) }.
Передварительний розрахунок вартості ордера в реальному часі: total = price * amount з урахуванням комісії. Обновляється при кожній зміні price або amount. NSDecimalNumber.multiplying(by:) для точності.
Buy/Sell переключення
Анімований перехід між buy та sell режимом: фон форми плавно змінює колір (зелений ↔ червоний), текст кнопки, іконки напрямку. На iOS — UIView.animate(withDuration: 0.2) з змінною backgroundColor. Haptic .impact(.medium) при переключенні.
Підтвердження ордера
Bottom sheet з деталями ордера перед відправкою. UISheetPresentationController (iOS 15+) або кастомний. При підтвердженні — кнопка переходить в loading state (UIActivityIndicatorView замість тексту), блокується повторне натиск. Після відповіді API — success animation (зелена галочка з scale animation) або error з конкретним текстом помилки з API.
Продуктивність та оптимізація
UITableView для стакана
Order book — UITableView з бесконечним potential height. UITableView.performBatchUpdates() для анімованого додавання/видалення/оновлення рядків. При 10 оновленнях/сек — batching змін: не викликаємо performBatchUpdates на кожний тик, збираємо за 100 мс та застосовуємо разом.
Ячейка стакана — кастомна UITableViewCell з UILabel-ами для ціни, об'єму та depth bar (візуальна полоса пропорційна об'єму на рівні). Depth bar — UIView з constraint на width, обновляємий через UIView.animate. Не перерисовуємо всю ячейку — тільки міняємо constant constraint.
Профілювання
Xcode Instruments > Time Profiler для пошуку hot spots в циклі оновлень. Core Animation instrument для frame drops. Цільові метрики: <16 мс на обробку WebSocket batch, <5 мс на оновлення UI, 0 dropped frames при скролі стакана.
На Android — Android Profiler в режимі CPU+Memory+Network одночасно. systrace для аналізу довгих frames у Choreographer.
Offline та reconnect
При втраті з'єднання: overlay «Нет подключения» поверх графіка (не заміняємо весь екран), останні відомі дані залишаються видимими. При восстановленні: автоматичний reconnect WebSocket з exponential backoff (1с, 2с, 4с, 8с, max 30с), REST запит актуального snapshot стакана та останніх свічей, seamless resume без скидання позиції графіка.
Термін: 5 днів. За цей час: WebSocket інтеграція з throttling, свічний графік на Core Graphics або LightweightCharts, order book з batch updates, форма ордера з валідацією та підтвердженням. Кастомний Metal-рендеринг графіка з індикаторами та розширена аналітика — дополнительно 5–10 днів.







