Розробка кастомних свічкових графіків для бірж та DeFi

Стандартні біржові віджети не справляються з високим навантаженням і не дають гнучкості в налаштуванні. Ми розробляємо кастомні свічкові графіки, які точно відповідають вашим вимогам до агрегації та відображення даних. Наша команда реалізує проєкт під ключ — від архітектури до впровадження, забезпечуючи стабільну роботу та подальшу підтримку.
Часті запитання

Торгова платформа з мільйоном угод на годину — стандартний TradingView віджет не справляється: агрегація гальмує, кастомізація неможлива. В одному з проєктів для клієнта з 50 000 пар і 2 млн угод на хвилину ми побудували кастомний свічковий графік з нуля. Рішення на TimescaleDB для OHLCV, Go-агрегаторі для real-time та Lightweight Charts для рендерингу обробляє свічку за 3 мс і відображає дані без затримок. Розберемо, як уникнути типових помилок і отримати графік, який не лагає на 100k свічок. Наші рішення дозволяють знизити витрати на інфраструктуру вдвічі за рахунок ефективної агрегації. Зв'яжіться з нами, щоб обговорити вимоги до вашого графіка.

Чому варто обрати кастомний графік?

Готові віджети не дають контролювати логіку агрегації (наприклад, зважені ціни за об'ємом) і не дозволяють додавати індикатори на зразок VWAP з нестандартним періодом. Кастомний графік дає повний контроль над кожним етапом: від збору даних до рендерингу, що критично важливо для пропрієтарних торгових стратегій та швидкої реакції ринку.

Проблеми, які вирішуємо

Основні складнощі при побудові кастомних графіків — latency та кастомізація. Готові віджети не дозволяють міняти логіку агрегації (наприклад, використовувати зважені ціни за об'ємом) або додавати індикатори на зразок VWAP з нестандартним періодом. Друга проблема — продуктивність: при тисячах свічок і кількох індикаторах рендеринг може гальмувати. Ми вирішуємо це комбінацією TimescaleDB на сервері та Lightweight Charts на клієнті.

Як ми вирішуємо проблему latency?

Latency складається з трьох етапів: отримання угоди (trade event), агрегація свічки та відправка на клієнт. Кожен етап має укладатися в мілісекунди. Покроковий процес:

  1. Отримання: WebSocket-шлюз обробляє до 100 000 повідомлень на секунду на один інстанс.
  2. Агрегація: In-memory агрегатор на Go оновлює поточну свічку за <2 мкс, закриті свічки — за 5 мкс.
  3. Доставка: Debounce оновлень до 10 разів на секунду, пакетна відправка — не більше 10 свічок в одному повідомленні.

Continuous aggregate в TimescaleDB автоматично оновлює матеріалізовані представлення. Ми налаштовуємо політику з інтервалом в 1 хвилину для свічок 1m, що дає свіжість даних до 1 хвилини. Для вищих таймфреймів агрегація виконується на льоту з 1m-свічок. У результаті end-to-end затримка від торгів до відображення на графіку не перевищує 200 мс.

Як реалізувати кастомні індикатори?

Індикатори (EMA, VWAP, об'ємний профіль) розраховуються на клієнті або сервері — вибір залежить від частоти перерахунку. Для індикаторів з постійним вікном (наприклад, EMA на 12 періодів) використовуємо серверну агрегацію: додаємо колонки в continuous aggregate. Для інтерактивних (переміщення точок) — клієнтський розрахунок у Web Worker, щоб не блокувати UI.

Приклад серверного індикатора — VWAP з налаштовуваним періодом:

CREATE MATERIALIZED VIEW vwap_1m
WITH (timescaledb.continuous) AS
SELECT
  time_bucket('1 minute', created_at) AS bucket,
  pair_id,
  sum(price * quantity) / sum(quantity) AS vwap
FROM trades
GROUP BY bucket, pair_id;

Як реалізувати кастомний свічковий графік?

Візьмемо типовий кейс: біржа хоче показувати 1-хвилинні свічки з Heikin-Ashi та EMA. Також підтримуємо Renko, kagi та point-and-figure. Серверна частина агрегує trades через TimescaleDB, а фронтенд використовує бібліотеку Lightweight Charts.

Зберігання та агрегація OHLCV

Сирі угоди зберігаються в TimescaleDB. Для швидкої агрегації створюємо continuous aggregate:

CREATE MATERIALIZED VIEW candles_1m
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 minute', created_at) AS bucket,
       pair_id,
       first(price, created_at) AS open,
       max(price) AS high,
       min(price) AS low,
       last(price, created_at) AS close,
       sum(quantity) AS volume,
       count(*) AS trades_count
FROM trades
GROUP BY bucket, pair_id;

SELECT add_continuous_aggregate_policy('candles_1m',
    start_offset => INTERVAL '3 hours',
    end_offset => INTERVAL '1 minute',
    schedule_interval => INTERVAL '1 minute');

З 1-хвилинних свічок вищі таймфрейми збираються на льоту — той же SQL з time_bucket('1 hour', bucket).

Real-time оновлення на Go

type CandleAggregator struct {
    mu sync.RWMutex
    current map[PairTimeframe]*Candle
}

func (ca *CandleAggregator) OnTrade(trade Trade) {
    ca.mu.Lock()
    defer ca.mu.Unlock()
    for _, tf := range TIMEFRAMES {
        key := PairTimeframe{trade.PairID, tf}
        bucket := truncateToTimeframe(trade.Time, tf)
        candle, exists := ca.current[key]
        if !exists || candle.Bucket != bucket {
            if exists {
                ca.publishClosedCandle(candle)
            }
            ca.current[key] = &Candle{
                Bucket: bucket,
                Open: trade.Price,
                High: trade.Price,
                Low: trade.Price,
                Close: trade.Price,
                Volume: trade.Quantity,
            }
        } else {
            if trade.Price > candle.High {
                candle.High = trade.Price
            }
            if trade.Price < candle.Low {
                candle.Low = trade.Price
            }
            candle.Close = trade.Price
            candle.Volume = candle.Volume.Add(trade.Quantity)
        }
        ca.publishLiveCandle(ca.current[key])
    }
}

Фронтенд: TradingView Lightweight Charts

import { createChart, CandlestickSeries } from 'lightweight-charts';

const chart = createChart(container, {
  layout: {
    background: { color: '#0d0d0f' },
    textColor: '#9b9ea8',
  },
  grid: {
    vertLines: { color: '#1e2030' },
    horzLines: { color: '#1e2030' },
  },
  timeScale: {
    timeVisible: true,
    secondsVisible: false,
  },
});

const candleSeries = chart.addSeries(CandlestickSeries, {
  upColor: '#00b15e',
  downColor: '#e84242',
  borderVisible: false,
});

// Load historical + stream via WebSocket
candleSeries.setData(historicalData);
ws.onmessage = (event) => candleSeries.update(JSON.parse(event.data));

Індикатори (EMA, VWAP) додаються як LineSeries поверх. Для Heikin-Ashi конвертуємо дані на клієнті:

function toHeikinAshi(candles: OHLCV[]): OHLCV[] {
  return candles.map((c, i) => {
    const prev = i > 0 ? candles[i-1] : c;
    const haClose = (c.open + c.high + c.low + c.close) / 4;
    const haOpen = i === 0 ? (c.open + c.close)/2 : (prev.open + prev.close)/2;
    return {
      time: c.time,
      open: haOpen,
      high: Math.max(c.high, haOpen, haClose),
      low: Math.min(c.low, haOpen, haClose),
      close: haClose,
    };
  });
}

Порівняння продуктивності: Lightweight Charts vs інші бібліотеки

Параметр Lightweight Charts v4 D3.js Highcharts
Час рендерингу 10k свічок 12 мс 45 мс 30 мс
RAM при 100k свічок 8 MB 25 MB 18 MB
Підтримка Web Worker так так обмежена
Кастомні індикатори TypeScript JavaScript JSON

Lightweight Charts в 3-4 рази швидше D3.js при рендерингу 10 000 свічок і споживає в 3 рази менше пам'яті.

Які дані потрібні для старту?

Для початку достатньо доступу до trade events (сирі угоди) через API або файли. Ми самостійно налаштовуємо агрегацію. Якщо даних нема — допоможемо підключитися до біржових джерел через WebSocket або REST. Мінімальна конфігурація не вимагає специфічних схем — TimescaleDB адаптується під будь-яку структуру.

Етапи роботи

Етап Що робимо
Архітектура Вибір СУБД, схема агрегації, API чати
Сервер TimescaleDB + Go-мікросервіс для real-time
Фронтенд Інтеграція Lightweight Charts, кастомні індикатори, брендинг
WebSocket Push-оновлення з дебаунсом
Документація Опис схем, API, інструкція з розгортання
Навчання Воркшоп для ваших розробників (2 дні)
Підтримка 2 тижні після запуску (баги, доопрацювання)

Що входить у роботу

У результат входить повний пакет: документація (схеми БД, API-специфікація, інструкція з розгортання), доступ до вихідного коду в Git-репозиторії, навчання вашої команди (воркшоп на 2 дні), 2 тижні безкоштовної підтримки після запуску та SLA з відповіддю до 4 годин. Ми забезпечуємо плавний перехід і самостійну експлуатацію.

Стек

Компонент Технологія
Time-series DB TimescaleDB (PostgreSQL extension)
Real-time агрегація Go microservice
WebSocket gorilla/websocket
Frontend TradingView Lightweight Charts v4
Індикатори Custom TypeScript + ta-lib.wasm
State management Zustand

Терміни та вартість

Терміни орієнтовні, розраховуються індивідуально:

  • Базовий графік (live-оновлення, 2–3 індикатори): 4–6 тижнів.
  • Повнофункціональний charting (всі таймфрейми, 10+ індикаторів, малювання, Heikin-Ashi/Renko): 2–3 місяці.
  • Серверна частина (TimescaleDB + агрегатор + WebSocket): 3–5 тижнів паралельно.

Вартість розраховується під ваш обсяг даних і вимоги. Гарантуємо прозорість: попередня оцінка, фіксація бюджету після затвердження ТЗ. Наші клієнти економлять до 40% часу на розробку за рахунок готових компонентів і перевірених рішень.

Наш досвід та гарантії

Ми — команда блокчейн-розробників з 5+ роками досвіду в Web3. Реалізували 30+ проєктів для криптобірж, DeFi-платформ та трейдингових терміналів. Використовуємо перевірені інструменти та надаємо офіційну гарантію на код.

Замовте розробку кастомного свічкового графіка — ми реалізуємо під ключ, від архітектури до деплою. Отримайте консультацію — обговоримо ваш проєкт і запропонуємо оптимальне рішення.

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

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

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142