Розробка системи зберігання tick-даних

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка системи зберігання tick-даних
Середній
~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
    860

Розробка системи зберігання tick-даних

Tick-дані — це кожна окрема угода на біржі: час, ціна, обсяг, сторона (maker/taker). На відміну від OHLCV-свічок, tick-дані дозволяють відновити повну картину активності ринку в будь-який момент. Це вимагає значно більше місця для зберігання та спеціалізованої інфраструктури.

Обсяги даних

Щоб розуміти масштаб завдання: Binance на BTC/USDT генерує приблизно 50,000–200,000 трейдів на день. На всіх парах на всіх біржах — сотні мільйонів записів щодня. Рік даних — десятки мільярдів рядків. Звичайний PostgreSQL не справляється без спеціалізованих рішень.

Технології зберігання

ClickHouse — колоночна СУБД від Yandex, оптимізована для аналітичних запитів на великих обсягах. Стискає часові ряди в 5–20 разів краще за PostgreSQL, виконує агрегації по мільярдам рядків за секунди.

CREATE TABLE trades (
    exchange    LowCardinality(String),
    symbol      LowCardinality(String),
    trade_id    String,
    timestamp   DateTime64(3, 'UTC'),
    price       Decimal(24, 8),
    quantity    Decimal(24, 8),
    side        LowCardinality(String),
    is_maker    Bool
)
ENGINE = MergeTree()
PARTITION BY (exchange, toYYYYMM(timestamp))
ORDER BY (exchange, symbol, timestamp)
SETTINGS index_granularity = 8192;

LowCardinality для рядків з кількома унікальними значеннями (exchange, symbol, side) — автоматичне dictionary encoding забезпечує значну економію місця.

TimescaleDB — якщо вже використовуєте PostgreSQL та обсяги помірні (< 1 млрд рядків). Підтримує hypertables з автоматичним партиціонуванням за часом, compression policies.

Arctic (Python library, на MongoDB) — спеціалізоване рішення для фінансових часових рядів. Підтримує tick-data, OHLCV, довільні DataFrames з версіюванням.

Схема для ClickHouse

Для максимальної продуктивності запису використовуємо буферну таблицю:

-- Буфер: накопичує дані в пам'яті, скидає кожні 10 сек або 1M рядків
CREATE TABLE trades_buffer AS trades
ENGINE = Buffer(currentDatabase(), 'trades', 16, 10, 100, 10000, 1000000, 10000000, 100000000);

-- Записуємо в буфер, читаємо з основної таблиці
INSERT INTO trades_buffer VALUES (...);
SELECT * FROM trades WHERE ...;

Запити на tick-дані

Агрегування tick-даних у OHLCV на льоту:

SELECT
    toStartOfInterval(timestamp, INTERVAL 1 MINUTE) AS candle_time,
    argMin(price, timestamp) AS open,
    max(price) AS high,
    min(price) AS low,
    argMax(price, timestamp) AS close,
    sum(quantity) AS volume,
    count() AS trade_count
FROM trades
WHERE exchange = 'binance'
  AND symbol = 'BTC/USDT'
  AND timestamp BETWEEN '2024-01-01' AND '2024-01-02'
GROUP BY candle_time
ORDER BY candle_time;

На ClickHouse цей запит по 50M рядків виконується за 1–3 секунди.

Pipeline ingestion

import asyncio
from collections import deque

class TickDataIngester:
    BATCH_SIZE = 10000
    FLUSH_INTERVAL = 5.0  # секунди

    def __init__(self, clickhouse_client):
        self.buffer = deque()
        self.client = clickhouse_client

    async def on_trade(self, trade: NormalizedTrade):
        self.buffer.append(trade)
        if len(self.buffer) >= self.BATCH_SIZE:
            await self.flush()

    async def flush(self):
        if not self.buffer:
            return
        batch = [self.buffer.popleft() for _ in range(min(self.BATCH_SIZE, len(self.buffer)))]
        await self.client.insert('trades_buffer', batch)

    async def flush_loop(self):
        while True:
            await asyncio.sleep(self.FLUSH_INTERVAL)
            await self.flush()

Компресія та утримання

ClickHouse стискає дані автоматично. Крім того можна включити cold storage через TTL:

ALTER TABLE trades
MODIFY TTL timestamp + INTERVAL 1 YEAR TO DISK 'cold_storage';

Дані старше року автоматично переносяться на дешевше сховище (S3-сумісне через ClickHouse object storage).

Бэкфилл історичних даних

Для заповнення історичних даних використовуємо публічні API бірж. Binance, наприклад, надає trade history через /api/v3/aggTrades з пагінацією за fromId. Паралельний бэкфилл за часовими діапазонами з rate limiting дозволяє завантажити роки даних за кілька годин.