Order flow
Volume profile and market profile
Visible-range, fixed-range and per-session profiles with point of control and value area, plus a TPO letter profile.
Volume profile and market profile
@ortex-charts/financialLoading volume profile and market profile…
Visible-range, fixed-range and per-session profiles with point of control and value area, plus a TPO letter profile.
volume-profile.ts
import { createFinancialChart, footprintFromTicks, type ProfileKind, type ProfileMode } from "@ortex-charts/financial";
import { parseResolution, ticksToBars, type Bar, type Tick } from "@ortex-charts/math";
const RESOLUTION = parseResolution("15");
const TICK = 0.05;
const bars = ticksToBars(prints, RESOLUTION, TIME_ZONE);
// The aggressor split is derived for this demonstration; a feed that reports
// it makes both the profile and its buy/sell halves exact.
const flow = footprintFromTicks(prints, RESOLUTION, TICK, TIME_ZONE);
const chart = createFinancialChart(box, {
theme,
timeZone: TIME_ZONE,
resolution: "15",
data: bars,
volume: false,
seriesOptions: { priceFormat: { type: "price", precision: 2, minMove: 0.01 } },
});
const profile = chart.addVolumeProfile({
mode: "visible",
tickSize: TICK,
splitDelta: true,
showPoc: true,
showValueArea: true,
valueArea: 0.7,
width: 0.32,
});
// Attaching the order flow is what turns an estimated profile into an exact
// one: every trade lands in the row that holds its price, and the buy and
// sell halves of each row are counted rather than inferred from the close.
profile.setFlow(flow);
/** Profiles are computed while drawing, so read them after the frame has painted. */
function report(): void {
const first = profile.profiles()[0];
if (!first || first.poc < 0) return status("No bars in range.");
const poc = first.rows[first.poc];
const va = `${first.rows[first.vaLow].lo.toFixed(2)} to ${first.rows[first.vaHigh].hi.toFixed(2)}`;
const count = profile.profiles().length;
status(
`${count} profile${count === 1 ? "" : "s"}, ${first.rows.length} rows Point of control ${poc.lo.toFixed(2)} Value area ${va} ${first.exact ? "exact" : "estimated"}`,
);
}