Реалізація історії торгів у мобільному приложенні біржі
Історія торгів на біржі — це не просто список ордерів. Це таблиця з високим темпом оновлення в реальному часі, фільтрацією за торговими парами та типами ордерів, пагінацією на тисячах записів, коректним відображенням статусів та розрахунком P&L за кожною угодою.
Типи записів та структура даних
Біржева історія включає кілька сутностей, які важливо розділяти на UI:
- Ордери (Orders) — те, що виставив користувач: лімітний, ринковий, стоп. Статус: open, filled, partially_filled, cancelled
- Угоди (Trades/Fills) — фактичні виконання ордерів. Один ордер може мати кілька fills
- P&L — розрахунок прибутку за закритими позиціями
class TradeRecord {
final String tradeId;
final String orderId;
final String symbol; // "BTC/USDT"
final TradeSide side; // buy / sell
final double price; // ціна виконання
final double quantity;
final double fee;
final String feeAsset; // "USDT" або "BNB" (якщо fee discount)
final DateTime executedAt;
final OrderType orderType; // market, limit, stop_limit
}
P&L для spot торговлі: (sell_price - avg_buy_price) * quantity - fees. Для бирж, які не надають P&L через API — обчислюємо локально, зіставляючи buy та sell угоди за FIFO.
Завантаження даних: REST + WebSocket
Історичні дані — через REST API біржі. Більшість бирж (Binance, OKX, Bybit) мають /api/v3/myTrades або аналог з cursor-based пагінацією за fromId або startTime:
Future<List<TradeRecord>> fetchTradeHistory({
required String symbol,
int? fromId,
DateTime? startTime,
int limit = 50,
}) async {
final response = await dio.get('/api/v3/myTrades', queryParameters: {
'symbol': symbol.replaceAll('/', ''),
if (fromId != null) 'fromId': fromId,
if (startTime != null) 'startTime': startTime.millisecondsSinceEpoch,
'limit': limit,
'timestamp': DateTime.now().millisecondsSinceEpoch,
'signature': _sign(queryString), // HMAC-SHA256
});
return (response.data as List).map(TradeRecord.fromJson).toList();
}
Real-time оновлення — WebSocket executionReport (Binance) або orders channel. При отриманні події про виконання ордера — додаємо угоду на початок списку та оновлюємо статус ордера.
UI: віртуалізований список
Історія торгів може містити тисячи записів. ListView.builder з пагінацією — єдиний правильний підхід. Звичайний ListView з children із 5000 віджетів викликає jank при прокруці та OOM на слабких пристроях.
NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollEndNotification &&
notification.metrics.pixels >= notification.metrics.maxScrollExtent - 200) {
_loadNextPage(); // lazy load при приближенні до кінця списку
}
return false;
},
child: ListView.builder(
itemCount: _trades.length + (_hasMore ? 1 : 0),
itemBuilder: (context, index) {
if (index == _trades.length) {
return const Center(child: CircularProgressIndicator());
}
return TradeRow(trade: _trades[index]);
},
),
)
Фільтрація
Фільтри за торговою парою, стороною (buy/sell), типом ордера, датою. Критично важливо: фільтрація за датою через DateTimeRange picker з пресетами «сьогодні / 7 днів / 30 днів».
Фільтри застосовуємо на сервері при завантаженні (параметри запиту), не на клієнті — інакше при великій історії доведеться скачати все та фільтрувати локально.
Кольорова індикація та читаємість
Стандарт для біржевих приложень: buy — зелений, sell — червоний. Статуси: filled — основний колір, cancelled — сірий, partially_filled — оранжевий. Ціна виконання — чуть крупніше інших полів.
Для відображення P&L: зелений з + для прибутку, червоний з - для збитку. Ноль — нейтральний колір.
Експорт
Кнопка експорту в CSV — стандартна вимога для біржевих історій (податкова звітність). Формуємо CSV з полями: Date, Pair, Side, Price, Quantity, Fee, Fee Asset, Total. BOM для коректного відкриття в Excel.
Що входить у роботу
- REST API інтеграція з підтримкою пагінації та підпису запитів (HMAC-SHA256)
- WebSocket для real-time оновлень нових угод
- Віртуалізований список з ленивим завантаженням
- Фільтри за парою, стороною, датою
- Відображення P&L (якщо API надає або розрахунок за FIFO)
- Експорт у CSV
Строки
Базова історія з пагінацією та фільтрами: 3–5 днів. З real-time, розрахунком P&L та експортом: 1–2 тижні. Вартість розраховується індивідуально.







