lightweight-orderflow-charts
v0.2.0
Published
Reusable order-flow charts and studies for lightweight-charts and React.
Maintainers
Readme
Reusable order-flow charts, studies, and React bindings for applications built on
TradingView lightweight-charts.
This package is designed for host apps that already own chart creation, market-data ingestion, and layout orchestration, but need a clean, broker-neutral rendering layer for footprint charts, profiles, VWAP, and aligned order-flow subcharts.
See it in action: Open the main demo | Get started

Resources
| Demo | Playground | Theming | Docs | Storybook | Demo data |
Highlights
- Footprint and volume-footprint custom series built on the same renderer pipeline
- Visible-range and session volume profile primitives with configurable left/right alignment
- Footprint-level point-of-control highlighting plus inline imbalance and stacked-imbalance styling
- Metric badges that can be stacked above or below each footprint bar with custom formatters and per-bar styling
- Theme-level metric style palettes so imbalance text, candle-side metrics, and summary badges can share consistent positive/negative styling
- Scale-driven shading for footprint cells and delta-summary tables
- Metric-driven candle heatmap helper for diverging probability or score overlays on standard candles
- Delta-summary subchart with selectable row keys and configurable row color scales
- Volume Delta Pivot data builder for zero-anchored delta candles
- Public style presets and public theme presets so consumers can start from working baselines
- Backend-neutral contracts plus normalization and patch helpers for feed adapters
Package Entry Points
- Core API:
lightweight-orderflow-charts - React API:
lightweight-orderflow-charts/react
Installation
npm install lightweight-orderflow-charts lightweight-charts react react-domTradingView lightweight-charts is required.
react and react-dom are optional peers for the React bindings.
Review docs/ATTRIBUTION.md before shipping a user-facing application.
TradingView lightweight-charts requires
TradingView attribution for deployed charts.
Development
npm ci
npm run check
npm run demo:buildCommon local commands:
npm run demoStarts the demo application fromdemo/npm run demo:connect-bridgeStarts the local connector bridge used by the repo-sideConnectdemo pagenpm run connector:ibkr:capture -- --helpRuns the resumable IBKR historical capture CLI that writes aggregated minute data into the local vendor cachenpm run connector:polygon:capture -- --helpRuns the Polygon.io / Massive REST capture CLI for minute aggregates using an environment-provided API keynpm run formatApplies the shared Prettier formatting rulesnpm run format:checkVerifies formatting without writing changesnpm run ciRuns the full repository verification flow used by CInpm run docsStarts the public docs landing app fromdocs-site/npm run storybookStarts the package-focused Storybook for interactive component and surface documentationnpm run build-storybookBuilds the package-focused Storybook static outputnpm run site:buildBuilds the GitHub Pages layout undersite/latest/{docs,storybook,demo,data}npm run package:dry-runShows the exact npm tarball contents without publishingnpm run release:checkRuns the release verification bundle, including npm package dry-run output
See CONTRIBUTING.md for the short contributor workflow.
Documentation Map
docs/GETTING_STARTED.mdStep-by-step path to the first rendered footprint chartdocs/API_REFERENCE.mdAuto-generated public export index for the core and React entry pointsdocs/EXTENSION_GUIDE.mdCompose the public API into a reusable host-side extension helperdocs/index.mdPublishable docs entry point for GitHub Pages or a static docs generatordocs/DATA_REQUIREMENTS.mdWhat each chart or study needs from the host data pipelinedocs/CANDLE_HEATMAP.mdPublic candle-heatmap helper for score-driven candlestick coloringdocs/TICK_DATA.mdAggregated minute storage, local vendor cache layout, and replay guidancedocs/MINTICK.mdPrice clustering, bucketing semantics, and publicmintickhelpersdocs/FORMATTING.mdPrice, compact value, and metric-style palette controls for footprint textdocs/AUTO_FIT.mdPrice-scale auto-fit helper for TradingView lightweight-charts-styleAuto (fits data to screen)behaviordocs/FEATURE_INVENTORY.mdConcise label-and-description inventory of the public charting features and presetsdocs/THEORY.mdRendering guidance distilled from recurring order-flow research articles and expert practicedocs/ARCHITECTURE.mdSource-tree responsibilities, extension points, and contributor guidancedocs/CHART_STATE.mdReusable viewport snapshot and restore helpers for URL sync or other persistence layersdocs/ATTRIBUTION.mdTradingView attribution and notice guidance inherited from TradingView lightweight-chartsdocs/RELEASING.mdGitHub Pages, npm provenance, semver tagging, and first-publish guidancedocs/CONNECTORS.mdRepo-side bridge, vendor adapters, and cache-first connector notes
Core Data Contract
The package works with normalized order-flow bars rather than raw broker payloads:
type OrderFlowBar = {
time: Time;
open: number;
high: number;
low: number;
close: number;
sessionId?: string;
totalVolume?: number;
delta?: number;
bidVolume?: number;
askVolume?: number;
tradeCount?: number;
vwap?: number;
pocPrice?: number;
pocVolume?: number;
deltaMin?: number;
deltaMax?: number;
levels: Array<{
price: number;
bidVolume: number;
askVolume: number;
totalVolume?: number;
delta?: number;
}>;
};The key idea is that the host application owns feed-specific translation and hands the library a clean, stable contract.
Useful helpers when your upstream feed is not already normalized:
normalizeOrderFlowBatch()normalizeOrderFlowPatch()applyOrderFlowPatch()aggregateOrderFlowBarsByInterval()aggregateMarketBarsByInterval()buildAggregatedMarketBarsFromOrderFlowBars()buildCandleHeatmapSeriesData()buildOrderFlowBarsFromTicks()createOrderFlowTickStreamController()resolveSessions()
The preferred canonical demo layout is now 1m-based:
bars-1m.jsonCandle summaries with required OHLCV plus optionalvwap,tradeCount,bidVolume,askVolume,delta,deltaMin,deltaMax,pocPrice, andpocVolumeorderflow-1m.jsonFootprint-capableOrderFlowBar[]with per-price bid/ask participation
The demo derives higher intervals such as 5m from those 1m files instead of storing separate
canonical interval files. Local vendor capture now writes into connectors/vendors/<vendor>/data/
as a cache-first source, while checked-in demo fixtures stay under data/market/.
Not every vendor cache is footprint-capable. IBKR can produce orderflow-1m.json when historical
ticks are requested, while Polygon.io / Massive REST on the current Basic plan only provides
bars-1m.json plus a manifest with orderFlowAvailable: false.
Choose The Right Study
| Study | Best Input | Notes | | -------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | | Candle Heatmap | OHLC bars plus one metric per bar | Best when the host already has a normalized score such as probability, percentile, or model confidence | | Footprint | Price-level bid/ask volume per bar | Primary view for ladder-level order-flow analysis | | Volume Footprint | Price-level total volume per bar | Useful when total participation matters more than aggressor side | | Visible / Session Volume Profile | Price-level volume across a scope | Built from normalized bars and aggregated by price | | VWAP | Tick-level or price-at-volume data | Can fall back to bar aggregates, but execution-quality VWAP should come from higher-resolution data | | Delta Summary | Same bars used by the footprint | Keeps delta context aligned to the chart time axis | | Volume Delta Pivot | Chart bars plus lower-timeframe bars | Best results come from lower-timeframe bars that already carry delta, with OHLC-volume fallback only when needed |
See docs/DATA_REQUIREMENTS.md for the full integration guidance.
Public Presets
Two preset layers are published:
ORDER_FLOW_STYLE_PRESETSStudy-level defaults for footprint, volume-footprint, profiles, and delta summaryORDER_FLOW_THEME_PRESETS10 theme packs with 5 dark and 5 light variants, each combining chart-surface colors with study styling overrides
The published presets now include:
ORDER_FLOW_STYLE_PRESETS.orderFlowReferenceA letter-delimited order-flow ladder baseline with thin candle strips, delta-colored row fills, diagonal-dominance text emphasis, and edge-only POC outlinesORDER_FLOW_THEME_PRESETS.smoothLightThe light order-flow surface used by the demo default, with red/green row shading and blue diagonal-dominance text
Candle Heatmap Example
import { buildCandleHeatmapSeriesData } from 'lightweight-orderflow-charts';
const candleData = buildCandleHeatmapSeriesData({
bars,
options: {
range: {
min: 0,
minShadeThreshold: 0.1,
threshold: 0.5,
maxShadeThreshold: 0.9,
max: 1,
},
downColor: '#f23645',
upColor: '#089981',
wickDownColor: '#c9cdd4',
wickUpColor: '#c9cdd4',
borderDownColor: '#f23645',
borderUpColor: '#089981',
shadeWicks: false,
noOfShades: 10,
shader: 'alpha',
},
backgroundColor: '#020617',
getValue: (bar) => Number(bar.metadata?.probabilityScore ?? null),
});This helper preserves candle geometry while replacing simple up/down candle colors with a
metric-driven diverging scale. See docs/CANDLE_HEATMAP.md for the full contract.
Use style presets when you want a strong starting point for a specific study configuration. Use theme presets when you want to re-skin an existing chart composition without changing the study layout itself.
import { ORDER_FLOW_STYLE_PRESETS, ORDER_FLOW_THEME_PRESETS } from 'lightweight-orderflow-charts';
const shaded = ORDER_FLOW_STYLE_PRESETS.shadedReference;
const midnight = ORDER_FLOW_THEME_PRESETS.midnightTerminal;Price Grid Integrity And Mintick
If the host application provides sparse or aggregated ladder levels, set ladder.priceStep to the
instrument tick size so row geometry remains deterministic while zooming:
const options = {
ladder: {
priceStep: 0.01,
},
};This is especially important when:
- ladder levels were synthesized from OHLCV bars
- the upstream feed omits zero-volume prices
- the host wants every rendered row to respect a constant tick grid
When the host wants a different visual ladder, use the public mintick helpers and keep
priceStep aligned to the same value:
import {
clusterOhlcBarsByMintick,
clusterOrderFlowBarsByMintick,
} from 'lightweight-orderflow-charts';
const mintick = 0.05;
const clusteredOrderFlowBars = clusterOrderFlowBarsByMintick(
orderFlowBars,
mintick,
instrument.tickSize,
);
const clusteredChartBars = clusterOhlcBarsByMintick(chartBars, mintick, instrument.tickSize);Larger mintick values cluster multiple source levels into broader buckets. Smaller positive values
such as 0.005 preserve the source levels and let the renderer show zero-volume intermediate rows.
See docs/MINTICK.md for the full bucketing rules and integration guidance.
Footprint Text Formatting
Footprint text formatting is split into two surfaces so a host can keep prices precise while abbreviating large ladder quantities:
const footprintOptions = {
style: {
priceDecimalDigits: 2,
priceRounding: 'ceil',
valueIntegerDigits: 2,
valueDecimalDigits: 1,
valueRounding: 'ceil',
valueUnitVisible: true,
},
};priceDecimalDigitsandpriceRoundingUsed for price-oriented values such asopen,high,low, andclosevalueIntegerDigits,valueDecimalDigits,valueRounding, andvalueUnitVisibleUsed for compact ladder values such as12.3k
For order-flow ladder presentation, the same public option surface also exposes:
ladder.bidAskFillModeladder.separatorMode,ladder.separatorLabel, andladder.separatorGapladder.highlightImbalanceTextladder.imbalanceRatiopointOfControl.visible,pointOfControl.borderColor, andpointOfControl.borderWidthstyle.separatorColorandstyle.separatorFontstyle.positiveImbalanceTextColor,style.positiveImbalanceTextFont,style.negativeImbalanceTextColor, andstyle.negativeImbalanceTextFont
These controls let a consumer reproduce layouts such as a letter-delimited bid x ask ladder,
delta-driven row shading, a separator gutter that inherits the row background, and positive/negative
imbalance text emphasis derived from the same diagonal comparison used by the footprint metrics.
See docs/FORMATTING.md for the full formatting surface.
Chart View State
The package exposes viewport snapshot helpers for persistence:
import { captureChartViewState, restoreChartViewState } from 'lightweight-orderflow-charts';
const snapshot = captureChartViewState(chart);
restoreChartViewState(chart, snapshot);The returned snapshot is JSON-safe, so a consuming application can store it in a URL, local storage, or another persistence layer without the library directly owning those policies.
For hosts that want TradingView-style vertical autoscaling after restore or a data swap, the package also exposes an auto-fit helper:
import { setPriceScaleAutoFit } from 'lightweight-orderflow-charts';
setPriceScaleAutoFit(chart, true, {
paneIndex: 0,
topInsetRatio: 0.05,
bottomInsetRatio: 0.05,
});The helper turns on the chart library's built-in price autoscaling with explicit top and bottom insets, so the visible data stays fitted while the user pans until they switch back to manual scaling.
Vanilla Quick Start
import { ColorType, createChart } from 'lightweight-charts';
import {
ORDER_FLOW_STYLE_PRESETS,
ORDER_FLOW_THEME_PRESETS,
createDeltaSummarySeries,
createFootprintSeries,
createVolumeProfilePrimitive,
} from 'lightweight-orderflow-charts';
const chart = createChart(container, {
layout: {
background: {
color: ORDER_FLOW_THEME_PRESETS.chartDarkPro.surface.backgroundColor,
type: ColorType.Solid,
},
textColor: ORDER_FLOW_THEME_PRESETS.chartDarkPro.surface.textColor,
attributionLogo: true,
},
});
const footprint = chart.addCustomSeries(
createFootprintSeries({
...ORDER_FLOW_STYLE_PRESETS.shadedReference.footprint,
...ORDER_FLOW_THEME_PRESETS.chartDarkPro.footprint,
}),
undefined,
0,
);
footprint.setData(orderFlowBars);
footprint.attachPrimitive(
createVolumeProfilePrimitive({
bars: orderFlowBars,
options: {
...ORDER_FLOW_STYLE_PRESETS.shadedReference.volumeProfile,
...ORDER_FLOW_THEME_PRESETS.chartDarkPro.volumeProfile,
},
}),
);
const deltaSummary = chart.addCustomSeries(
createDeltaSummarySeries({
...ORDER_FLOW_STYLE_PRESETS.shadedReference.deltaSummary,
...ORDER_FLOW_THEME_PRESETS.chartDarkPro.deltaSummary,
}),
undefined,
1,
);
deltaSummary.setData(orderFlowBars);React Quick Start
import {
ChartProvider,
DeltaSummarySeries,
FootprintSeries,
VolumeProfile,
} from 'lightweight-orderflow-charts/react';
import {
ORDER_FLOW_THEME_PRESETS,
ORDER_FLOW_STYLE_PRESETS,
type OrderFlowBar,
type TimeValue,
} from 'lightweight-orderflow-charts';
function OrderFlowPane({ bars, chart }: { bars: OrderFlowBar[]; chart: IChartApi | null }) {
return (
<ChartProvider chart={chart}>
<FootprintSeries
chart={chart}
data={bars}
paneIndex={0}
options={{
...ORDER_FLOW_STYLE_PRESETS.shadedReference.footprint,
...ORDER_FLOW_THEME_PRESETS.depthHeat.footprint,
}}
/>
<VolumeProfile
data={bars}
options={{
...ORDER_FLOW_STYLE_PRESETS.shadedReference.volumeProfile,
...ORDER_FLOW_THEME_PRESETS.depthHeat.volumeProfile,
}}
/>
<DeltaSummarySeries
chart={chart}
data={bars}
paneIndex={1}
options={{
...ORDER_FLOW_STYLE_PRESETS.shadedReference.deltaSummary,
...ORDER_FLOW_THEME_PRESETS.depthHeat.deltaSummary,
}}
/>
</ChartProvider>
);
}Demo
The repo contains four demo entry points:
- Explore at
#/explorePreset-driven exploration surface with URL-synced controls forPreset,Theme,Date,Symbol,Interval,Mintick, and optional synthetic streaming - Playground at
#/playgroundAdvanced fixture lab for trying lower-level renderer combinations, heatmap tuning, and layout toggles - Theming at
#/themingFixed Order Flow Delta plus profile composition for editing chart-surface, candle, footprint, volume-profile, and delta-summary theme tokens against live data - Connect at
#/connectLocal-development-only direct vendor flow with cache-first loading, streaming progress, and connector status
Explore is built around conceptual presets such as:
Order Flow DeltaDelta-First ReadAbsorptionStacked ImbalancesVolume Profile ShapeSession MapVolume FootprintVolume Delta Pivot
The theme selector applies one of the published ORDER_FLOW_THEME_PRESETS, so the same concept can
be re-skinned without changing the underlying study composition.
The published GitHub Pages demo exposes Explore, Playground, and Theming. It intentionally omits
the Connect route because that flow depends on the local bridge process and vendor credentials.
Source Layout
src/modelsPublic contracts, option types, defaults, and merge helperssrc/presetsPublished style packs and theme packssrc/adaptersNormalization and patch/session helperssrc/calculationsFootprint, profile, VWAP, and volume-delta derivationssrc/renderers/footprint-seriesFootprint and volume-footprint custom-series implementationsrc/renderers/primitivesVolume profile, session profile, annotation, and VWAP primitivessrc/renderers/delta-summary-seriesTable-style custom-series implementationsrc/reactThin lifecycle wrappers around the core renderersdemo/src/contentExplore presets and educational mappingsdemo/src/fixturesPlayground and test-oriented fixture dataconnectors/Repo-side, non-dist connector bridge, vendor adapters, and persistence helpers used by theConnectdemo surfacedata/marketSource-managed market fixtures used by the demo and verification flows, not by the published dist
Repo-Side Connectors
The connectors/ tree is intentionally a repo-side integration layer rather than part of the
published npm surface.
- The browser demo never talks to vendor sockets directly.
- The
Connectpage uses a local HTTP plus SSE bridge started withnpm run demo:connect-bridge. - Vendor adapters such as IBKR live under
connectors/vendors/. - The bridge writes to
data/marketby default, butCONNECTOR_MARKET_DATA_ROOTcan point it at an alternate location for safe experimentation.
See docs/CONNECTORS.md for the connector protocol, bridge workflow, and
extension guidance.
Extension Guide
See docs/EXTENSION_GUIDE.md for a runnable host-side extension
example and a matching CodeSandbox starter.
When adding a new study or enhancing an existing one:
- Add or refine public option types in
src/models/options.ts - Add the calculation or aggregation logic under
src/calculations - Thread the new behavior into the renderer or primitive layer
- Publish a reusable preset under
src/presets - Expose the API from
src/index.tsandsrc/react.tswhen needed - Add a focused test under
tests/unitortests/integration - Add an Explore preset only when it meaningfully teaches the feature
Full Verification
npm run typecheck
npm run test
npm run build
npm run docs:build
npm run build-storybook
npm run demo
npm run demo:connect-bridge
npm run demo:build
npm run site:buildNotes
- The demo data in examples or the served fixture data is locally crafted for visualization and validation. It is not a live feed and may not represent complete market conditions.
