fintech-algorithms
Using a coding agent? Give it the skill: npx skills add IslamBaraka90/Fintech-Algorithms-Library What it does →

Volume-Imbalance Bars

Install and import#

bash
npm install fintech-algorithms
ts
import { constructBars } from "fintech-algorithms/market-data-engineering/bar-construction/volume-imbalance-bars";

Signature#

constructBars(trades, config)

The imbalance rule applied to signed *volume* rather than signed tick count, so one large order weighs more than many small ones pointing the same way.

Parameters#

NameTypeNotes
tradesTrade[]The raw tape in chronological order. Each trade carries tradeId, timestamp, session, symbol, price, volume and currency.
config{ initialTickSign: number; initialExpectedTicks: number; initialExpectedSignedVolume: number; alphaTicks: number; alphaSignedVolume: number; thresholdFloorShares: number; thresholdScale: number; closePartial?: boolean }As for tick-imbalance bars, but the tracked quantity is signed volume. thresholdFloorShares is the floor in shares, and thresholdScale multiplies the expectation to form the trigger.

Returns#

Bar[] · length fewer

One bar per signed-volume imbalance event.

Errors#

  • When any alpha falls outside 0…1, or a seed expectation is not positive — throws

Complexity: time O(n), space O(bars).

Worked example#

verified This is the worked example published in the article, replayed by the test suite on every run. The output cannot drift.

Input#

trades
[
  {
    "tradeId": "W01",
    "timestamp": "2026-01-05T14:30:00.000Z",
    "session": "2026-01-05",
    "symbol": "SYNTH",
    "price": 100,
    "volume": 60,
    "currency": "USD"
  },
  {
    "tradeId": "W02",
    "timestamp": "2026-01-05T14:30:00.000Z",
    "session": "2026-01-05",
    "symbol": "SYNTH",
    "price": 100,
    "volume": 40,
    "currency": "USD"
  },
  {
    "tradeId": "W03",
    "timestamp": "2026-01-05T14:30:01.000Z",
    "session": "2026-01-05",
    "symbol": "SYNTH",
    "price": 99.99,
    "volume": 70,
    "currency": "USD"
  }
]

Showing 3 of 8 elements.

config
{
  "closePartial": true,
  "initialTickSign": 1,
  "initialExpectedTicks": 4,
  "initialExpectedSignedVolume": 50,
  "alphaTicks": 0.25,
  "alphaSignedVolume": 0.25,
  "thresholdFloorShares": 120,
  "thresholdScale": 1
}

Call#

constructBars(trades, config)

Returns#

array of 2 objects

[
  {
    "barIndex": 0,
    "session": "2026-01-05",
    "startTime": "2026-01-05T14:30:00.000Z",
    "endTime": "2026-01-05T14:30:04.000Z",
    "open": 100,
    "high": 100,
    "low": 99.97,
    "close": 99.97,
    "volume": 405,
    "dollarValue": 40493.65,
    "tickCount": 6,
    "firstTradeId": "W01",
    "lastTradeId": "W06",
    "closeReason": "threshold"
  },
  {
    "barIndex": 1,
    "session": "2026-01-05",
    "startTime": "2026-01-05T14:30:05.000Z",
    "endTime": "2026-01-05T14:30:06.000Z",
    "open": 99.98,
    "high": 99.99,
    "low": 99.98,
    "close": 99.99,
    "volume": 135,
    "dollarValue": 13497.85,
    "tickCount": 2,
    "firstTradeId": "W07",
    "lastTradeId": "W08",
    "closeReason": "threshold"
  }
]

Diagrams#

Volume-Imbalance Bars — article hero
Volume-Imbalance Bars — boundary and state
Volume-Imbalance Bars — construction anatomy

Calculation flow#

Causal volume-imbalance construction flow
flowchart TD
    A["Receive corrected, eligible, ordered trade"] --> B{"New session?"}
    B -->|Yes| C["Apply partial-tail policy"]
    C --> D["Reset sign and expectation seeds"]
    B -->|No| E["Keep frozen threshold"]
    D --> F["Infer tick sign and add signed shares"]
    E --> F
    F --> G{"Absolute signed shares >= frozen threshold?"}
    G -->|No| A
    G -->|Yes| H["Emit complete bar, lineage, and overshoot"]
    H --> I["Update expected ticks and signed shares per trade"]
    I --> J["Reset accumulation and freeze next threshold"]
    J --> A

How it works#

This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.

Read the article →

References#

The rest of the Bar Construction family#