Docs·Charting Library·Core API

Footprint Chart

Switch the chart type to footprint and render bid×ask volume inline on each candle. Tick aggregation, display modes, and the trade-stream input format.

A footprint chart replaces the candle body with a stack of cells, one per price level, showing the bid-initiated and ask-initiated volume traded at that price during the bar. The engine ships this view as a first-class chart type — flip a switch on the same chart instance and your candles render as footprint cells with POC highlights, imbalance dots, and a volume profile in the same paint pass.

Switch to footprint mode

chart.setChartType(type)

ValueDescription
'candle'Standard OHLCV candlesticks (default).
'footprint'Footprint cells inline on each bar.
JavaScript
chart.setChartType('footprint')

Toggling chart types does not lose data — the same OHLCV stays loaded. The engine just re-renders. Toggle back with setChartType('candle').

Tick size — the price-bucket width

A footprint cell aggregates trades that landed within a tick-size band of price. Smaller tick = more cells = more detail but smaller font; larger tick = denser cells but loses fine-grained imbalance information.

chart.setFootprintTickSize(tick)

ArgumentTypeDescription
ticknumberPrice width of one cell. e.g. 1.0 = each cell groups trades within $1 of each other.

Suggested defaults:

SymbolTick size
BTC perpetual5.0 to 25.0 (depending on volatility)
ETH perpetual0.5 to 2.5
SOL perpetual0.05 to 0.25
Cap-1 altcoins (< $0.10)0.0001 to 0.001

The engine recomputes the footprint each time you change the tick size. Render is one frame.

Feeding trade data

Unlike candles (which compress to OHLCV), footprint needs trade-level data to classify each fill as bid- or ask-initiated.

The engine consumes trades alongside the OHLCV through the same setKlines flow, plus a dedicated trade-append method during real-time:

JavaScript
// On bar close, your backend can aggregate trades to OHLCV plus a
// secondary "footprint slice" — one cell per price level with bid
// vs ask volume already split.

// During real-time, each new trade is added to the current bar's slice.
chart.addFootprintTrade({
  ts: trade.ts,           // Unix seconds
  price: trade.price,
  qty: trade.qty,
  // 'true' when the BUYER is the market maker (resting bid). The
  // aggressor was a SELLER who hit the bid. Follows CEX (Binance,
  // Bybit, OKX) convention.
  isBuyerMaker: trade.isBuyerMaker,
})

The engine bucketises into the configured tick size and updates the current bar's footprint cells in place.

Display modes

The footprint cells can render in three modes:

ModeWhat you see
'bid-ask'Two numbers per row: bid volume on the left, ask volume on the right (split).
'delta'Single number: ask − bid for that row (positive = ask-dominant).
'volume'Single number: total volume at that row, with optional delta tint.
JavaScript
chart.setFootprintMode('bid-ask')  // or 'delta' or 'volume'

Bid×Ask is the most information-dense and is what professional desktop tools default to. Delta is faster to read at a glance. Volume is useful when you want a "thicker candle" rather than full footprint detail.

POC and imbalance highlights

Point of Control (POC)

The price row with the highest volume inside a bar. The engine highlights it automatically when in footprint mode. POC clustering across consecutive bars is one of the most reliable supply/demand signals in order flow trading — see the reading footprint guide for tactical patterns.

Imbalance dots

When the bid volume on a row dwarfs the ask on a diagonally adjacent row (or vice versa), the engine marks the row with a small dot. Stacked imbalances — 3+ consecutive rows all flagged in the same direction — are typically the most actionable signal.

Imbalance configuration

JavaScript
chart.setFootprintImbalanceRatio(3.0)       // bid >= 3 × ask = imbalance
chart.setFootprintImbalanceMinStack(3)      // 3 consecutive rows = "stacked"
chart.setFootprintImbalanceMethod('diagonal')  // 'diagonal' or 'horizontal'
chart.setFootprintImbalanceMaxAge(100)      // bars back to highlight
SettingRangeDescription
Ratio2.5 – 10.0Ratio threshold. Lower = noisier, higher = rarer. Start at 3.0.
Min stack2 – 6Minimum consecutive rows. 3 is the canonical threshold.
Method'diagonal' | 'horizontal'Diagonal (TradingView-style) compares row r's bid to row r+1's ask. Horizontal compares row r's bid to row r's ask.
Max age50 – 500, or 0 for allStop drawing imbalance markers older than N bars. Reduces visual clutter on historical zooms.

A deep dive on stacked imbalance configuration lives in the stacked imbalances guide.

Volume profile on the side

Footprint mode automatically renders a volume profile on the right edge of the chart — a histogram of total volume per price across the visible bars.

MethodEffect
chart.setFootprintShowProfile(true | false)Toggle the side profile.
chart.setFootprintProfileWidth(0.5 – 2.0)Width multiplier.

The profile peak is the visible Visible Range Point of Control (VRPOC) — the high-volume node across the current viewport, not just one bar.

Common pitfalls

Footprint cells are too small to read. Either: too many price levels per bar (lower the tick-size denominator), or the bars are too narrow (zoom in). The engine renders cells at the minimum legible font size before hiding text entirely. If you're zoomed all the way out, cells become solid color blocks — that's by design.

Imbalance dots fire on every bar. Your ratio is too low. Start at 3.0 (300 % imbalance, "300 = TradingView default"). For very liquid pairs (BTC perp), 5.0 is more selective. For thin pairs, stay at 2.5 — a 3× imbalance happens organically when liquidity is thin.

addFootprintTrade is fast but my bar's footprint is wrong. You're missing the isBuyerMaker flag, or it's inverted. Public exchange websocket feeds vary: Binance / OKX / Bybit use is_buyer_maker = true to mean "the buyer was the maker (resting bid), so the aggressor was a seller." Some exchanges flip the convention — verify with one trade you can confirm visually (e.g. a known buy-side market order in the past).

Switching back to candle mode shows ghost footprint. You called setChartType('candle') but the cell-rendering layer was never destroyed. The engine handles this automatically since v0.1 — if you see this, ensure you're on the latest release.

Next