Indicator

Fathom Imbalances

Where the footprint shows every number, Imbalances keeps only the signal: when one side overwhelms the other on several levels in a row, the closed candle leaves a zone on the chart.

On each closed bar, finds runs of consecutive imbalanced levels (diagonal, horizontal, or by delta percentage) and turns them into zones extended for extendedBars bars. A crossed zone can spawn a retest zone. Each zone is republished on every change and becomes final when it ends. The computation restarts every week.

Identifier
imbalances
Objects received
zone
Calculation
Since the start of the week
Historical cost
1 unit per trade

Subscribe

The same params work in real time, on historical data and in exports. Any you leave out take their default value.

Subscribe message
{
  "t": "subscribe",
  "sub": "imbalances",
  "instrument": "NQ.front",
  "indicator": "imbalances",
  "params": {
    "consecutive": 3,
    "extendedBars": 10,
    "extraTicks": 0,
    "groupTicks": 1,
    "includeZero": false,
    "minimumPercent": 300,
    "minimumVolume": 0,
    "mode": "diagonal",
    "resetSession": false,
    "timeframe": 300,
    "triggerOnlyTouch": false,
    "triggeredZones": true
  },
  "mode": "live",
  "from": "live"
}

Parameters

As soon as a parameter differs from its default, the subscription counts as a custom configuration. A new value may require preparing a new calculation (status warming).

ParameterTypeDefaultAllowed valuesUnitDescription
consecutiveinteger31 to 20—Minimum number of consecutive imbalanced levels to form a zone.
extendedBarsinteger101 to 500barsZone lifetime, in bars.
extraTicksinteger00 to 100ticksPadding added to zones, in ticks.
groupTicksinteger11 to 100ticksNumber of ticks grouped into each level.
includeZerobooleanfalsetrue · false—Count an empty side as an imbalance.
minimumPercentinteger3001 to 10,000%Minimum ratio between the two sides, in percent.
minimumVolumeinteger00 to 1,000,000contractsMinimum volume difference between the two sides.
modechoicediagonaldiagonal · horizontal · delta-percentage—How volumes are compared: diagonal, horizontal, or by delta percentage.
resetSessionbooleanfalsetrue · false—End zones at the open of each session.
timeframeinteger30015 · 60 · 300—Bar duration in seconds: 15, 60 or 300.
triggerOnlyTouchbooleanfalsetrue · false—Trigger on touch instead of on close.
triggeredZonesbooleantruetrue · false—Create a retest zone once a zone is triggered.

Objects received

Each object keeps the same id from one update to the next. Its data is in the data field. Prices are in ticks: multiply them by the instrument’s tick size (GET /v1/instruments) to get points.

zone updated continuously

Zone; provisional while it is active.

Format of the id: <weekStart>:<ordinal>. While it changes, the object is sent with final: false, and each new version fully replaces the previous one. Its last version carries final: true.

FieldTypeUnitPresentDescription
activeboolean—alwaysThe zone is still being extended.
barstringtimestamp (ns)alwaysStart of the bar that created the zone.
endnumberbarssometimesEnd, in bars from bar; present once the zone has ended.
highintegerticksalwaysTop of the zone.
lowintegerticksalwaysBottom of the zone (equal to the top for a line).
sidestring · buy | sell—alwaysBuy or sell imbalance.
startnumberbarsalwaysStart, in bars from bar.
triggeredboolean—alwaysRetest zone, created after a zone was triggered.

Calculation warm-up

The calculation starts over at the beginning of every week (Saturday 00:00 UTC). During the weekend close it keeps the state of the past week; objects still open are finalized on the first trade of the new week. If nobody is using your parameters yet, the server first recomputes the week since its start (status warming), then goes live (status live).

Historical data follows the same rules: a query over a past period returns exactly what the real-time stream published.

Example messages

Messages received with the subscription parameters above. Over WebSocket, each message also carries sub and cursor.

Final version
{
  "t": "upsert",
  "id": "2026-09-19:526",
  "final": true,
  "ts": "1790208000058746563",
  "data": {
    "side": "sell",
    "high": 123052,
    "low": 123050,
    "triggered": true,
    "active": false,
    "bar": "1790207400000000000",
    "start": -0.5,
    "end": 2
  }
}
In-progress version
{
  "t": "upsert",
  "id": "2026-09-19:527",
  "final": false,
  "ts": "1790208000058746563",
  "data": {
    "side": "sell",
    "high": 123040,
    "low": 123038,
    "triggered": false,
    "active": true,
    "bar": "1790207700000000000",
    "start": 0.5
  }
}

JSON schemas

To validate or type your data: the JSON schemas of the parameters and of data, also available from GET /v1/indicators. The SDK can generate types from them.

Parameters schema
JSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://fathomcharts.com/schemas/imbalances/params.json",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "consecutive": {
      "type": "integer",
      "default": 3,
      "minimum": 1,
      "maximum": 20,
      "description": "Minimum number of consecutive imbalanced levels to form a zone."
    },
    "extendedBars": {
      "type": "integer",
      "default": 10,
      "minimum": 1,
      "maximum": 500,
      "description": "Zone lifetime, in bars."
    },
    "extraTicks": {
      "type": "integer",
      "default": 0,
      "minimum": 0,
      "maximum": 100,
      "description": "Padding added to zones, in ticks."
    },
    "groupTicks": {
      "type": "integer",
      "default": 1,
      "minimum": 1,
      "maximum": 100,
      "description": "Number of ticks grouped into each level."
    },
    "includeZero": {
      "type": "boolean",
      "default": false,
      "description": "Count an empty side as an imbalance."
    },
    "minimumPercent": {
      "type": "integer",
      "default": 300,
      "minimum": 1,
      "maximum": 10000,
      "description": "Minimum ratio between the two sides, in percent."
    },
    "minimumVolume": {
      "type": "integer",
      "default": 0,
      "minimum": 0,
      "maximum": 1000000,
      "description": "Minimum volume difference between the two sides."
    },
    "mode": {
      "type": "string",
      "default": "diagonal",
      "enum": [
        "diagonal",
        "horizontal",
        "delta-percentage"
      ],
      "description": "How volumes are compared: diagonal, horizontal, or by delta percentage."
    },
    "resetSession": {
      "type": "boolean",
      "default": false,
      "description": "End zones at the open of each session."
    },
    "timeframe": {
      "type": "integer",
      "default": 300,
      "enum": [
        15,
        60,
        300
      ],
      "description": "Bar duration in seconds: 15, 60 or 300."
    },
    "triggerOnlyTouch": {
      "type": "boolean",
      "default": false,
      "description": "Trigger on touch instead of on close."
    },
    "triggeredZones": {
      "type": "boolean",
      "default": true,
      "description": "Create a retest zone once a zone is triggered."
    }
  }
}
Schema of the data field
JSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://fathomcharts.com/schemas/imbalances/data.json",
  "title": "zone",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "side",
    "high",
    "low",
    "triggered",
    "active",
    "bar",
    "start"
  ],
  "properties": {
    "active": {
      "type": "boolean",
      "description": "The zone is still being extended."
    },
    "bar": {
      "type": "string",
      "pattern": "^[0-9]+$",
      "description": "Start of the bar that created the zone."
    },
    "end": {
      "type": "number",
      "description": "End, in bars from `bar`; present once the zone has ended."
    },
    "high": {
      "type": "integer",
      "description": "Top of the zone."
    },
    "low": {
      "type": "integer",
      "description": "Bottom of the zone (equal to the top for a line)."
    },
    "side": {
      "type": "string",
      "enum": [
        "buy",
        "sell"
      ],
      "description": "Buy or sell imbalance."
    },
    "start": {
      "type": "number",
      "description": "Start, in bars from `bar`."
    },
    "triggered": {
      "type": "boolean",
      "description": "Retest zone, created after a zone was triggered."
    }
  }
}