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

Absolute Breadth Index

Install and import#

bash
npm install fintech-algorithms
ts
import { evaluateAbsoluteBreadthIndex } from "fintech-algorithms/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index";

Signature#

evaluateAbsoluteBreadthIndex(request)

The absolute difference between advances and declines, in issues — direction discarded on purpose. It reports how far apart the two counts were, so an up session and a down session of the same size share a value. Nothing here reads it as conviction, activity, volatility, or a signal: the package returns the signed spread and the original counts alongside it, and interpretation is left to separate research.

Parameters#

NameTypeNotes
request{ decision_time: string; metric_variant: string; records: Record[] }metric_variant must be the string raw_issue_count; it is the only supported form. A normalized, smoothed, or cumulative variant is not calculated — the request comes back with evaluation state unsupported. decision_time bounds which revisions are usable: a record counts only when both its effective_at and its available_at are at or before it.

Returns#

{ metric, evaluation_state, publishable, reason_codes, decision_time, records_causally_available, future_records_ignored, record_id, revision, is_provisional, net_advances, absolute_breadth_index, mover_count, classified_count, coverage_ratio, breadth_state, plus the snapshot identity and count fields when resolved }

evaluation_state is resolved, incomplete, ambiguous, or unsupported; every derived number is null unless it is resolved. A resolved result adds the snapshot identity — session, venue, universe id and revision, session and calendar ids, comparison basis, corporate-action policy, listing-identifier scheme — and the full count partition, so the index always travels with the universe it was computed over. breadth_state separates the three distinct ways a zero can arise: active_balance, no_movers, and empty_universe.

Errors#

  • When metric_variant is anything other than raw_issue_count — reported as evaluation state unsupported rather than thrown
  • When an input cannot be interpreted safely: a timestamp that is missing, malformed or without a UTC offset, a non-string identity field, a negative or unsafe count, a non-boolean is_final, or a kind other than observation or cancellation — throws ABIValidationError

Complexity: time O(r log r) for r revision records: validation and causal filtering are linear, and the visible revisions are sorted before the lineage head is taken, space O(r).

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#

request
{
  "decision_time": "2026-01-05T22:00:00Z",
  "metric_variant": "raw_issue_count",
  "records": [
    {
      "record_id": "ABI-R1",
      "revision": 1,
      "supersedes_record_id": null,
      "kind": "observation",
      "effective_at": "2026-01-05T21:00:00Z",
      "available_at": "2026-01-05T21:05:00Z",
      "is_final": true,
      "session_date": "2026-01-05",
      "venue_id": "SYNTH-X",
      "universe_id": "SYNTH-100",
      "universe_revision": "U1",
      "session_id": "regular",
      "calendar_id": "SYNTH-CAL",
      "comparison_basis": "comparable-prior-close"
    }
  ]
}

Call#

evaluateAbsoluteBreadthIndex(request)

Returns#

object with 12 fields: evaluation_state, publishable, reason_codes, record_id, revision, is_provisional, net_advances, absolute_breadth_index, …

{
  "evaluation_state": "resolved",
  "publishable": true,
  "reason_codes": [],
  "record_id": "ABI-R1",
  "revision": 1,
  "is_provisional": false,
  "net_advances": 30,
  "absolute_breadth_index": 30,
  "mover_count": 90,
  "classified_count": 98,
  "coverage_ratio": 0.98,
  "breadth_state": "advances_imbalanced"
}

Diagrams#

Absolute Breadth Index — direction fold
Absolute Breadth Index — session magnitudes

Calculation flow#

Absolute Breadth Index evidence and calculation flow
flowchart LR
    A["Raw issue-count request"] --> B{"Supported variant?"}
    B -- "No" --> U["Unsupported; ABI null"]
    B -- "Yes" --> C["Keep records effective and available by decision time"]
    C --> D{"Any causal record?"}
    D -- "No" --> I["Incomplete; ABI null"]
    D -- "Yes" --> E{"One identity and contiguous lineage?"}
    E -- "No" --> M["Ambiguous; ABI null"]
    E -- "Yes" --> F{"Current record complete and not cancelled?"}
    F -- "No" --> I
    F -- "Yes" --> G["Net Advances = A - D"]
    G --> H["Raw ABI = absolute value of Net Advances"]
    H --> R["Resolved; retain counts, sign, clocks, revision, finality"]

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#

  • Schwab thinkorswim AdvanceDecline study
  • TC2000 T2101 help
  • Nasdaq Trader Daily Market Files
  • Nasdaq Daily Market Summary definitions
  • Nasdaq Trader 2026 annual CSV
  • Evidence reconciliation

The rest of the Advance/Decline Breadth family#