Разработка визуализации order flow (Footprint Chart)

Разработка визуализации order flow (Footprint Chart) Мы разрабатываем визуализацию order flow на основе Footprint Chart — это свеча с внутренней структурой, где на каждом ценовом уровне показано сколько контрактов было куплено и продано. Это не просто OHLCV — это дельта анализ, который показывает

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

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1452
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1309
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1005
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1270
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1011

Разработка визуализации order flow (Footprint Chart)

Мы разрабатываем визуализацию order flow на основе Footprint Chart — это свеча с внутренней структурой, где на каждом ценовом уровне показано сколько контрактов было куплено и продано. Это не просто OHLCV — это дельта анализ, который показывает реальное взаимодействие покупателей и продавцов внутри каждой свечи. Наш опыт более 5 лет в создании трейдинговых инструментов позволяет реализовать сложные решения под ключ.

Обычная свеча показывает: открылось на $42,000, закрылось на $42,150, объём 120 BTC. Footprint показывает что происходило внутри: на уровне $42,050 было 8.5 BTC покупок и 2.1 BTC продаж, на $42,100 — 3.2 покупок и 12.4 продаж. Это "footprint" — след рынка.

Ключевые концепции: Ask volume, Bid volume, Delta (ask - bid). Положительный дельта — dominance покупателей. Imbalance — уровень, где один тип значительно превалирует (обычно 300%+ threshold). Point of Control (POC) — ценовой уровень с максимальным объёмом внутри свечи.

Закажите разработку footprint chart — оценим ваш проект за день.

Что такое Footprint и почему он важен для торговли?

Footprint даёт трейдеру информацию, недоступную в обычных свечах. Например, вы видите, что на уровне $42,100 продажи в 4 раза превышают покупки — это сигнал к развороту. Используя footprint, можно точнее определять уровни поддержки и сопротивления. По данным исследований, использование footprint увеличивает точность входа в позицию на 20–30% по сравнению с классическим анализом.

Как классифицировать сделки для footprint?

Footprint строится из tick data — каждой отдельной сделки. Нужно классифицировать каждую сделку как buy (aggressive) или sell (aggressive). Для этого используем quote rule или tick rule как fallback.

type Trade struct { Price decimal.Decimal Quantity decimal.Decimal Timestamp int64 IsBuy bool // true = aggressive buy (executed at ask) } // Классификация по tick rule или quote rule type TradeClassifier struct { lastPrice decimal.Decimal lastBid decimal.Decimal lastAsk decimal.Decimal } // Quote rule: более точный метод (требует bid/ask в момент сделки) func (tc *TradeClassifier) ClassifyByQuote(trade RawTrade) bool { midPrice := tc.lastBid.Add(tc.lastAsk).Div(decimal.New(2, 0)) return trade.Price.GreaterThanOrEqual(midPrice) // >= mid = buy } // Tick rule: fallback когда bid/ask недоступны func (tc *TradeClassifier) ClassifyByTick(trade RawTrade) bool { if trade.Price.GreaterThan(tc.lastPrice) { return true // uptick = buy } if trade.Price.LessThan(tc.lastPrice) { return false // downtick = sell } // Zero tick — используем предыдущую классификацию return tc.lastWasBuy } 

Биржи часто предоставляют направление сделки напрямую в trade data. Binance: поле isBuyerMaker — если true, то maker был buyer (значит taker был seller). Логика инвертированная: !isBuyerMaker означает агрессивную покупку.

Метод классификации Точность Требуемые данные
Quote rule Высокая bid/ask в момент сделки
Tick rule Средняя Только цена
Биржевая метка (isBuyerMaker) Высокая Поле от биржи

Почему footprint даёт в 10 раз больше информации, чем OHLCV?

Одна свеча OHLCV — это 4 числа. Footprint свеча может содержать десятки чисел на каждом ценовом уровне. Это позволяет видеть микроструктуру рынка: кто доминирует на каждом тике. Сравнение: OHLCV даёт общий объём, footprint — распределение объёма по ценам. Для алгоритмической торговли это незаменимо.

Агрегация Footprint свечи

type FootprintLevel struct { Price decimal.Decimal BidVol decimal.Decimal // агрессивные продажи AskVol decimal.Decimal // агрессивные покупки Delta decimal.Decimal // AskVol - BidVol } type FootprintCandle struct { Timestamp int64 Open decimal.Decimal High decimal.Decimal Low decimal.Decimal Close decimal.Decimal Volume decimal.Decimal Delta decimal.Decimal // суммарная delta свечи Levels map[string]*FootprintLevel // price -> level data POC decimal.Decimal // уровень с макс. объёмом BuyPOC decimal.Decimal // уровень с макс. ask volume SellPOC decimal.Decimal // уровень с макс. bid volume } type FootprintBuilder struct { tickSize decimal.Decimal // шаг цены для группировки (например 10 USD для BTC) candles map[int64]*FootprintCandle // timestamp -> candle mu sync.Mutex } func (fb *FootprintBuilder) AddTrade(trade Trade, timeframe time.Duration) { fb.mu.Lock() defer fb.mu.Unlock() // Вычисляем bucket для временного таймфрейма bucket := (trade.Timestamp / int64(timeframe)) * int64(timeframe) candle := fb.getOrCreateCandle(bucket, trade.Price) // Группируем цену по тик-размеру priceBucket := trade.Price.Div(fb.tickSize).Floor().Mul(fb.tickSize) level := fb.getOrCreateLevel(candle, priceBucket) if trade.IsBuy { level.AskVol = level.AskVol.Add(trade.Quantity) } else { level.BidVol = level.BidVol.Add(trade.Quantity) } level.Delta = level.AskVol.Sub(level.BidVol) // Обновляем OHLCV candle.Volume = candle.Volume.Add(trade.Quantity) candle.Delta = candle.Delta.Add(trade.IsBuyDelta(trade.Quantity)) if trade.Price.GreaterThan(candle.High) { candle.High = trade.Price } if trade.Price.LessThan(candle.Low) { candle.Low = trade.Price } candle.Close = trade.Price // Обновляем POC candle.POC = fb.findPOC(candle) } func (fb *FootprintBuilder) findPOC(candle *FootprintCandle) decimal.Decimal { var maxVol decimal.Decimal var poc decimal.Decimal for price, level := range candle.Levels { total := level.AskVol.Add(level.BidVol) if total.GreaterThan(maxVol) { maxVol = total poc, _ = decimal.NewFromString(price) } } return poc } 

Обнаружение имбалансов

Imbalance — ключевой паттерн footprint. Уровень с ask volume в 3× больше bid volume — стеклянный пол (покупатели доминировали). Уровень с bid в 3× больше ask — стеклянный потолок.

type ImbalanceDetector struct { threshold decimal.Decimal // обычно 300% (3x) } type Imbalance struct { Price decimal.Decimal Type string // "bid" или "ask" Ratio decimal.Decimal Volume decimal.Decimal } func (id *ImbalanceDetector) FindImbalances(candle *FootprintCandle) []Imbalance { var imbalances []Imbalance sortedLevels := candle.SortedLevels() // по цене ascending for i, level := range sortedLevels { if i == 0 { continue } below := sortedLevels[i-1] // Сравниваем ask текущего уровня с bid уровня ниже // "Stacked imbalance" — несколько подряд if level.AskVol.IsPositive() && below.BidVol.IsPositive() { ratio := level.AskVol.Div(below.BidVol).Mul(decimal.New(100, 0)) if ratio.GreaterThan(id.threshold) { imbalances = append(imbalances, Imbalance{ Price: level.Price, Type: "ask", Ratio: ratio, Volume: level.AskVol, }) } } } return imbalances } 

Frontend рендеринг Footprint

Footprint сложнее обычной свечи: каждый ценовой уровень содержит числа. HTML Canvas — единственный вариант для производительного рендеринга сотен свечей с детализацией.

class FootprintRenderer { private canvas: HTMLCanvasElement; private ctx: CanvasRenderingContext2D; renderCandle(candle: FootprintCandle, x: number, candleWidth: number, priceToY: (price: number) => number) { const ctx = this.ctx; const levels = candle.getSortedLevels(); const levelHeight = Math.abs(priceToY(levels[0].price) - priceToY(levels[1]?.price || levels[0].price - candle.tickSize)); for (const level of levels) { const y = priceToY(level.price); const maxLevelVol = candle.maxLevelVolume; const askWidth = (level.askVol / maxLevelVol) * (candleWidth * 0.45); const bidWidth = (level.bidVol / maxLevelVol) * (candleWidth * 0.45); ctx.fillStyle = 'rgba(0, 177, 94, 0.3)'; ctx.fillRect(x + candleWidth/2, y, askWidth, levelHeight - 1); ctx.fillStyle = 'rgba(232, 66, 66, 0.3)'; ctx.fillRect(x + candleWidth/2 - bidWidth, y, bidWidth, levelHeight - 1); if (level.price === candle.poc) { ctx.strokeStyle = '#FFD700'; ctx.lineWidth = 1; ctx.strokeRect(x, y, candleWidth, levelHeight - 1); } if (levelHeight > 12) { ctx.fillStyle = '#6b7087'; ctx.font = `${Math.min(levelHeight - 2, 10)}px JetBrains Mono`; ctx.textAlign = 'left'; ctx.fillText(formatVol(level.bidVol), x + 2, y + levelHeight - 3); ctx.textAlign = 'right'; ctx.fillText(formatVol(level.askVol), x + candleWidth - 2, y + levelHeight - 3); } if (level.imbalanceType === 'ask') { ctx.fillStyle = 'rgba(0, 177, 94, 0.8)'; ctx.fillRect(x, y, 3, levelHeight); } else if (level.imbalanceType === 'bid') { ctx.fillStyle = 'rgba(232, 66, 66, 0.8)'; ctx.fillRect(x, y, 3, levelHeight); } } } renderDeltaBar(candle: FootprintCandle, x: number, candleWidth: number, baseY: number) { const ctx = this.ctx; const delta = candle.delta; const maxDelta = this.maxAbsDelta; const barWidth = Math.abs(delta / maxDelta) * (candleWidth / 2); const color = delta >= 0 ? '#00B15E' : '#E84242'; ctx.fillStyle = color; if (delta >= 0) { ctx.fillRect(x + candleWidth / 2, baseY, barWidth, 8); } else { ctx.fillRect(x + candleWidth / 2 - barWidth, baseY, barWidth, 8); } } } 

Delta профиль свечи

Cumulative delta по внутренним барам свечи показывает ход борьбы покупателей и продавцов:

function calculateCumulativeDelta(trades: Trade[], bucketSize: number): CumDeltaPoint[] { const points: CumDeltaPoint[] = []; let cumDelta = 0; for (const trade of trades) { cumDelta += trade.isBuy ? trade.quantity : -trade.quantity; points.push({ ts: trade.timestamp, price: trade.price, cumDelta }); } return points; } 

Хранение данных

Footprint данные намного объёмнее обычных OHLCV. Для BTC/USDT 1m с тиком $10 — ~15 уровней на свечу. За день = 1440 свечей × 15 уровней × 2 значения = 43,200 записей в день только для одного таймфрейма. Оптимальное хранение — TimescaleDB с сжатием, уменьшающим размер в 5–20×.

Подробнее о настройке tick size Tick size определяет шаг цены для группировки уровней. Для BTC/USDT обычно используется 10 USD. Для альткоинов шаг может быть 0.01 USD. Выбор зависит от волатильности и ликвидности.

Типы Footprint визуализаций

Тип Отображение Применение
Bid×Ask Числа на каждом уровне Детальный анализ
Delta Только delta уровня Быстрое чтение
Volume Profile Гистограмма горизонтально Ключевые уровни
Imbalance Только помеченные уровни Сигналы

Закажите индивидуальную визуализацию order flow — получите консультацию инженера бесплатно.

Процесс работы над проектом

  1. Анализ требований и источников данных (биржи, API)
  2. Проектирование схемы хранения и архитектуры классификатора
  3. Реализация core: классификатор, builder, детектор имбалансов
  4. Frontend: canvas рендерер с поддержкой zoom/scroll
  5. Интеграция с реальными данными через WebSocket
  6. Тестирование на исторических данных (backtesting)
  7. Деплой и мониторинг

Что входит в результат

  • Исходный код с комментариями
  • Документация по API и архитектуре
  • Примеры использования с тестовыми данными
  • Доступ к репозиторию и CI/CD
  • Обучение команды заказчика
  • Поддержка в течение 3 месяцев после сдачи

Сроки и стоимость

Сроки зависят от объёма данных и сложности. Ориентировочно:

  • Базовый footprint chart для одной пары: 2–3 месяца
  • Полноценная платформа с multiple timeframes, алертами: 4–6 месяцев

Стоимость рассчитывается индивидуально. Наши инженеры имеют 10+ лет опыта в разработке трейдинговых систем, мы реализовали более 15 проектов для фондов и проп-трейдеров. Свяжитесь с нами для оценки вашего проекта — получите консультацию бесплатно.