Skip to content

Order flow

Footprint bars

Bid and ask volume at every price inside the bar, with imbalances marked and a delta strip underneath.

Footprint bars@ortex-charts/financial
Loading footprint bars
Bid and ask volume at every price inside the bar, with imbalances marked and a delta strip underneath.
footprint.ts
import { createFinancialChart, footprintFromTicks, footprintTotals, mergeFootprint } from "@ortex-charts/financial";
import { parseResolution, ticksToBars, type Bar, type Tick } from "@ortex-charts/math";

const RESOLUTION = parseResolution("30");
const TICK = 0.1; // Height of one footprint cell, in price units.

// The public sample feed carries prices only: no sizes and no aggressor
// side. Every print here is therefore given an illustrative size, and
// `footprintFromTicks` splits bid from ask with the tick rule, which is the
// estimate every platform without aggressor flags is built on. A feed that
// reports the aggressor sets `side` on each tick and the split is exact.
const flow = footprintFromTicks(prints, RESOLUTION, TICK, TIME_ZONE);
const bars = ticksToBars(prints, RESOLUTION, TIME_ZONE);

const chart = createFinancialChart(box, {
    theme,
    timeZone: TIME_ZONE,
    resolution: "30",
    // `mergeFootprint` copies each bar's aggressor totals onto the bar, so
    // the delta and CVD indicators read them instead of guessing.
    data: mergeFootprint(bars, flow),
    volume: false,
    seriesOptions: { priceFormat: { type: "price", precision: 2, minMove: 0.01 } },
    timeScale: { barSpacing: 58 },
});

const footprint = chart.setFootprint(flow, { tickSize: TICK, imbalanceRatio: 3, showTotals: true, showPoc: true });

chart.chart.subscribeCrosshairMove((e) => {
    const bar = e.time === null ? undefined : footprint.flowAt(e.time);
    if (!bar) return;
    const t = footprintTotals(bar);
    status(
        `Bid ${t.sell.toLocaleString()}   Ask ${t.buy.toLocaleString()}   Delta ${t.delta >= 0 ? "+" : ""}${t.delta.toLocaleString()}   Point of control ${t.poc.toFixed(2)}`,
    );
});