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

Net Advances

Count Participation Without Hiding Data Gaps

Install and import#

bash
npm install fintech-algorithms
ts
import { calculateNetAdvances } from "fintech-algorithms/market-breadth-and-internals/advance-decline-breadth/net-advances";

Signature#

calculateNetAdvances(request)

Advances minus declines for a session. The simplest breadth measure and the input to most of the others — its value is that it counts companies rather than weighting them, so it says what *most* of the market did.

Parameters#

NameTypeNotes
requestBreadthRequestCarries the session identity (session_date, session_id, venue_id, universe_id) plus the rules that decide what counts as an advance: comparison_basis (which price is compared against which), corporate_action_policy, and price_tolerance for unchanged. calculation_as_of bounds which revisions are usable.

Returns#

{ status, direction, metric, session_date, universe_id, … }

The count with a status and the full identity of what was counted — two systems disagreeing on breadth almost always disagree about the universe, not the arithmetic.

Errors#

  • When the comparison basis or corporate-action policy is unrecognised — reported as a status rather than thrown

Complexity: time O(members), space O(1).

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
{
  "session_date": "2026-01-05",
  "session_id": "regular",
  "session_timezone": "UTC",
  "venue_id": "SYNTH-X",
  "universe_id": "SYNTH-3",
  "comparison_basis": "comparable-prior-close",
  "corporate_action_policy": "provider-adjusted",
  "price_tolerance": 0,
  "calculation_as_of": "2026-01-05T22:00:00Z",
  "revisions": [
    {
      "revision_id": "R1",
      "revision_sequence": 1,
      "supersedes_revision_id": null,
      "effective_at": "2026-01-05T21:00:00Z",
      "available_at": "2026-01-05T21:05:00Z",
      "is_final": true,
      "members": [
        {
          "listing_id": "L-A",
          "security_id": "S-A",
          "ticker": "A",
          "state": "eligible",
          "current_price": 11,
          "prior_comparable_price": 10
        },
        {
          "listing_id": "L-D",
          "security_id": "S-D",
          "ticker": "D",
          "state": "eligible",
          "current_price": 9,
          "prior_comparable_price": 10
        },
        {
          "listing_id": "L-U",
          "security_id": "S-U",
          "ticker": "U",
          "state": "eligible",
          "current_price": 10,
          "prior_comparable_price": 10
        }
      ]
    }
  ]
}

Call#

calculateNetAdvances(request)

Returns#

object with 14 fields: status, direction, selected_revision_id, advances, declines, unchanged, excluded, unclassified, …

{
  "status": "ready",
  "direction": "balanced",
  "selected_revision_id": "R1",
  "advances": 1,
  "declines": 1,
  "unchanged": 1,
  "excluded": 0,
  "unclassified": 0,
  "universe_size": 3,
  "mover_count": 2,
  "classified_count": 3,
  "coverage_ratio": 1,
  "net_advances": 0,
  "is_provisional": false
}

Diagrams#

Net Advances — historical opposite breadth
Net Advances — net advances balance

Calculation flow#

Net Advances evidence and calculation flow
flowchart TD
    A["Session, universe, identity, and price policy"] --> B["Select revision effective and available by query time"]
    B --> C{"Unique revision chain and listing IDs?"}
    C -- "No" --> D["ambiguous; net is null"]
    C -- "Yes" --> E["Classify every point-in-time member"]
    E --> F{"Missing or unclassified evidence?"}
    F -- "Yes" --> G["incomplete; net is null"]
    F -- "No" --> H["Reconcile A + D + U + X = N"]
    H --> I{"Universe or movers empty?"}
    I -- "Universe empty" --> J["empty_universe; net 0"]
    I -- "No movers" --> K["no_movers; net 0"]
    I -- "Movers present" --> L["ready; net = A - D"]
Revision lifecycle with two clocks
flowchart LR
    S["Session close effective 21:00"] --> R1["R1 available 21:05"]
    R1 --> Q1["21:30 query selects R1: 5 - 3 = +2"]
    S --> R2["R2 correction available 22:00"]
    R2 --> Q2["22:30 query selects R2: 4 - 4 = 0"]
    R2 -. "Unavailable at 21:30" .-> N["Must not affect or appear in Q1"]

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#

  • R1 - Nasdaq A-D glossary
  • R2 - Nasdaq Daily Market Summary definitions
  • R3 - Nasdaq Daily Market Files and 2026 CSV
  • R4 - Consolidated Tape System output specification
  • R5 - FINRA TRACE End of Day Market Breadth correction
  • R6 - NYSE Daily TAQ catalog and reference data
  • Evidence boundary

The rest of the Advance/Decline Breadth family#