Normalized Advance/Decline Line
Cumulative (A-D)/(A+D) Breadth
Install and import#
npm install fintech-algorithmsimport { calculateNormalizedAdLine } from "fintech-algorithms/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line";Signature#
calculateNormalizedAdLine(records, options)Divides net advances by the number of issues traded before accumulating, which keeps the line comparable across decades as listing counts change.
Parameters#
| Name | Type | Notes |
|---|---|---|
records | BreadthRecord[] | Session records with revision and supersession fields. |
options | { cutoff: string; expectedStartSequence: number; expectedEndSequence: number; initialValue: number; scale: number; minimumCoverage: number } | minimumCoverage refuses to emit a line when too many sessions are missing, rather than producing one with invisible holes. scale sets the units; cutoff applies the point-in-time bound. |
Returns#
{ state, reason_codes, points, ignored_future_revisions, denominator_policy, … }
The normalised line with the denominator policy applied and a count of revisions ignored for arriving after the cutoff.
Errors#
- When coverage falls below minimumCoverage — reported as a state rather than thrown
Complexity: time O(records),
space O(sessions).
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#
[
{
"event_id": "NAD-1",
"revision": 1,
"supersedes_revision": null,
"event_type": "upsert",
"session_sequence": 1,
"session_date": "2026-01-05",
"effective_at": "2026-01-05T21:00:00Z",
"available_at": "2026-01-05T21:05:00Z",
"venue_id": "SYNTH-X",
"universe_id": "SYNTH-100",
"calendar_id": "SYNTH-CAL",
"session": "regular",
"comparison_basis": "comparable-prior-close",
"corporate_action_policy": "provider-adjusted"
},
{
"event_id": "NAD-2",
"revision": 1,
"supersedes_revision": null,
"event_type": "upsert",
"session_sequence": 2,
"session_date": "2026-01-06",
"effective_at": "2026-01-06T21:00:00Z",
"available_at": "2026-01-06T21:05:00Z",
"venue_id": "SYNTH-X",
"universe_id": "SYNTH-100",
"calendar_id": "SYNTH-CAL",
"session": "regular",
"comparison_basis": "comparable-prior-close",
"corporate_action_policy": "provider-adjusted"
}
]{
"cutoff": "2026-01-06T22:00:00Z",
"expectedStartSequence": 1,
"expectedEndSequence": 2,
"initialValue": 0,
"scale": 100,
"minimumCoverage": 0.95
}Call#
calculateNormalizedAdLine(records, options)Returns#
object with 4 fields: state, reason_codes, ignored_future_revisions, points
{
"state": "resolved",
"reason_codes": [],
"ignored_future_revisions": 0,
"points": {
"0": {
"net_advances": 30,
"mover_count": 90,
"scaled_contribution": 33.33333333333333,
"normalized_line": 33.33333333333333
},
"1": {
"net_advances": -20,
"mover_count": 90,
"scaled_contribution": -22.22222222222222,
"normalized_line": 11.111111111111107
}
}
}Diagrams#
Calculation flow#
Causal normalized-line publication flow
flowchart LR
A[Read available time] --> B{Visible at cutoff?}
B -- No --> C[Count ignored future record]
B -- Yes --> D[Validate visible event]
D --> E[Resolve revision heads]
E --> F{Every expected session resolved?}
F -- No --> G[Return state and reasons with no points]
F -- Yes --> H[Verify stable identity seed scale and denominator]
H --> I[Compute ratio as A minus D over A plus D]
I --> J[Add scaled ratio to prior line]
J --> K[Return traceable cumulative points]
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.
References#
- Nasdaq Trader Daily Market Files
- Nasdaq Trader 2026 daily CSV
- Nasdaq Trader field definitions
- McClellan breadth normalization — McClellan Financial Publications
- StockCharts A/D Percent
- Evidence map