Skip to content

Volume Profile — the distribution of what you can see ​

The volume of the visible x range as horizontal bars per price bucket — pan or zoom and the distribution rebuilds on the spot (the TradingView Visible Range lineage). Only the thickest bucket (the POC) has a different color. It's a decoration rather than a series, so it's one addDecoration line, and every bar is a drawShape rect, so it can be asserted headless.

Source ​

apps/examples/src/cases/volume-profile.ts — the real thing, type-checked in CI.

ts
import { PlotBuilder, browserDeps } from "@finchart/dom";
import type { OHLC } from "@finchart/core";
import { candleSeries, priceFormat, timeTicks } from "@finchart/core";
import { volumeProfile } from "@finchart/indicators";
import { fixtureCandles } from "./fixture";
import { chartHost } from "./stage";

export const title = "Volume Profile — the distribution of what you can see";
export const description =
  "The volume of the visible x range as horizontal bars per price bucket — pan or zoom and the distribution rebuilds on the spot (the TradingView Visible Range lineage). " +
  "Only the thickest bucket (the POC) has a different color. It's a decoration rather than a series, so it's one addDecoration line, and every bar is a drawShape rect, so it can be asserted headless.";

export function mount(container: HTMLElement): () => void {
  const host = chartHost(container, 480);
  const plot = PlotBuilder.create<OHLC>(browserDeps({ autoSize: true }))
    .setSize(container.clientWidth || 900, 480)
    .setAxis({
      x: { ticks: timeTicks({ timeZone: "UTC", locale: "en-US" }) },
      y: { position: "right", format: priceFormat({ compact: true, locale: "en-US" }) },
    })
    .build(host);

  const data = fixtureCandles();
  const price = plot.mainPane.addSeries({
    series: candleSeries(),
    data,
    name: "Price",
  });

  const remove = plot.mainPane.addDecoration(
    volumeProfile({ source: price }),
  );

  return Object.assign(
    () => {
      remove();
      plot.destroy();
      host.remove();
    },
    { requestRender: () => plot.requestRender() },
  );
}