Розробка системи нормалізації даних з бірж

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка системи нормалізації даних з бірж
Середній
~3-5 днів
Часті запитання

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

Етапи блокчейн-розробки

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

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

Розробка системи нормалізації даних з бірж

Кожна крипто-біржа — окремий всесвіт з власними угодами про найменування, форматами чисел, одиницями часу та семантикою полів. BTC/USDT на Binance називається BTCUSDT, на Kraken — XBT/USDT, на Bitfinex — tBTCUST. Нормалізація — це шар, який приховує цю несумісність за єдиним інтерфейсом.

Що потрібно нормалізувати

Символи та пари. Кожна біржа має власні угоди. Нормалізований формат — BASE/QUOTE у верхньому регістрі: BTC/USDT, ETH/BTC. Біржові символи зберігаються в маппінгу з можливістю зворотного перетворення.

Timestamps. Binance повертає мілісекунди, деякі біржи — секунди, OKX — наносекунди. Нормалізований формат — мілісекунди UTC, що зберігаються як int64.

Числа. REST API часто повертає числа як рядки ("43250.50"), деякі біржи втрачають trailing zeros. Нормалізований формат — Decimal з явною точністю, залежно від інструменту.

Сторони ордера. BUY/SELL, buy/sell, b/s, 1/-1 — все це зустрічається. Нормалізований формат — enum BUY | SELL.

Статуси ордерів. У кожної біржі власні статуси. Нормалізований маппінг:

Біржа Raw Normalized
Binance NEW, PARTIALLY_FILLED, FILLED, CANCELED OPEN, PARTIAL, FILLED, CANCELLED
Bybit Created, New, PartiallyFilled, Filled OPEN, OPEN, PARTIAL, FILLED
OKX live, partially_filled, filled, canceled OPEN, PARTIAL, FILLED, CANCELLED

Архітектура нормалізатора

Нормалізатор реалізується як набір адаптерів специфічних для бірж з загальним інтерфейсом:

from abc import ABC, abstractmethod
from decimal import Decimal

class ExchangeNormalizer(ABC):
    @abstractmethod
    def normalize_symbol(self, raw_symbol: str) -> str:
        """Перетворює біржевий символ у нормалізований формат BASE/QUOTE"""

    @abstractmethod
    def normalize_ticker(self, raw_data: dict) -> NormalizedTicker:
        """Нормалізує ticker дані"""

    @abstractmethod
    def normalize_order(self, raw_data: dict) -> NormalizedOrder:
        """Нормалізує дані ордера"""


class BinanceNormalizer(ExchangeNormalizer):
    SYMBOL_MAP = {
        "BTCUSDT": "BTC/USDT",
        "ETHUSDT": "ETH/USDT",
        # ... з API /api/v3/exchangeInfo
    }

    def normalize_ticker(self, raw: dict) -> NormalizedTicker:
        return NormalizedTicker(
            exchange="binance",
            symbol=self.normalize_symbol(raw["s"]),
            timestamp=int(raw["T"]),
            price=Decimal(raw["c"]),
            volume_24h=Decimal(raw["v"]),
        )

Динамічне завантаження маппінгу символів

Жорсткий маппінг символів у коді — погана ідея: біржи додають нові пари щодня. Правильний підхід — завантажити маппінг з Exchange Info API при запуску та періодично оновлювати:

async def load_symbol_map(self):
    exchange_info = await self.rest_client.get("/api/v3/exchangeInfo")
    self.symbol_map = {
        s["symbol"]: f"{s['baseAsset']}/{s['quoteAsset']}"
        for s in exchange_info["symbols"]
        if s["status"] == "TRADING"
    }
    # Інвертований маппінг для зворотного перетворення
    self.reverse_map = {v: k for k, v in self.symbol_map.items()}

Валідація нормалізованих даних

Після нормалізації важливо валідувати результат. Негативні ціни, нульові обсяги, timestamp у майбутньому — все це ознаки проблем з джерелом даних:

def validate_ticker(ticker: NormalizedTicker) -> list[str]:
    errors = []
    if ticker.price <= 0:
        errors.append(f"Invalid price: {ticker.price}")
    if ticker.timestamp > now_ms() + 5000:
        errors.append(f"Future timestamp: {ticker.timestamp}")
    if ticker.bid and ticker.ask and ticker.bid >= ticker.ask:
        errors.append(f"Crossed book: bid={ticker.bid} ask={ticker.ask}")
    return errors

Невалідні дані логуються та відкидаються, не потрапляючи в downstream-системи.

Тестування нормалізатора

Unit-тести з реальними прикладами raw-даних від кожної біржі — обов'язкові. Біржи іноді змінюють формат API без попередження. Набір фіксованих fixtures з очікуваними нормалізованими результатами дозволяє швидко виявити регресію:

def test_binance_normalizer():
    raw = {"s": "BTCUSDT", "c": "43250.50", "v": "28450.12", "T": 1704067200000}
    result = BinanceNormalizer().normalize_ticker(raw)
    assert result.symbol == "BTC/USDT"
    assert result.price == Decimal("43250.50")
    assert result.exchange == "binance"

Крім того — integration тести з live API біржей у sandbox-режимі, запускаються щодня в CI для раннього виявлення змін у API.