# Absolute Breadth Index: Keep Magnitude Without Inventing Certainty

The canonical raw Absolute Breadth Index (ABI) is one session's unsigned advance/decline spread:

\[
ABI_t = |A_t-D_t|
\]

Here, \(A_t\) and \(D_t\) are integer counts of advancing and declining issues under one declared point-in-time universe and comparison policy. The output unit is **issues**. Raw ABI is neither cumulative nor normalized. It removes direction, so every result retains the original counts and signed Net Advances beside the magnitude.

## Learning contract

After this topic, a reader can:

- calculate raw ABI and explain exactly what absolute value destroys;
- distinguish raw ABI from Net Advances, the A/D ratio, normalized variants, smoothing, price volatility, and volume;
- separate active balance, no movers, and an empty universe even though all can produce zero;
- gate publication on a complete, causal, reconciled revision;
- label bounded historical evidence without upgrading provider observations into stronger claims.

Prerequisite: **Net Advances**, the signed value \(A-D\).

## Scope and nearby measures

| Measure | Definition | Unit | Keeps direction? | Canonical here? |
|---|---|---|---|---|
| Net Advances | \(A-D\) | issues | Yes | Retained diagnostic |
| Raw ABI | \(|A-D|\) | issues | No | Yes |
| A/D ratio | \(A/D\), with a declared zero policy | ratio | Usually | No |
| Mover-normalized ABI | \(|A-D|/(A+D)\) | ratio | No | No |
| Smoothed ABI | Declared smoother over ABI | depends on input | No | No |
| Cumulative A/D line | Running sum of signed breadth | index level | Yes | No |

The canonical function rejects a request for a normalized or smoothed variant as `unsupported`. That boundary prevents a percentage or moving average from being mislabeled as a raw issue count.

Raw ABI is not price-return variance, realized or implied volatility, volume, turnover, dollar volume, or an investable signal. Formula correctness supplies no evidence of prediction or profitability.

## Data contract

The calculation consumes a request with a `decision_time`, `metric_variant: raw_issue_count`, and one revision lineage. Every observation revision declares:

| Field group | Required meaning |
|---|---|
| Stable snapshot identity | `session_date`, `venue_id`, `universe_id`, `universe_revision`, `session_id`, `calendar_id` |
| Classification policy | `comparison_basis`, `corporate_action_policy`, `listing_identifier_scheme` |
| Two clocks | `effective_at` says when the record applies; `available_at` says when it became knowable |
| Lineage | unique `record_id`, positive contiguous `revision`, and `supersedes_record_id` |
| Status | `kind` is `observation` or `cancellation`; `is_final` distinguishes provisional from final evidence |
| Counts | advances, declines, unchanged, excluded, missing, unclassified, and universe size |

All counts are non-negative safe integers. The full partition is:

\[
A+D+U+X+M+Q=N
\]

where \(U\) is unchanged, \(X\) is excluded by a known policy, \(M\) is missing, \(Q\) is unclassified, and \(N\) is the point-in-time universe size. Missing and unclassified are not synonyms for unchanged or excluded. A snapshot can publish raw ABI only when \(M=Q=0\) and the partition reconciles.

The upstream policy must resolve listings, delistings, symbol changes, new issues without a comparable prior close, halts, suspensions, stale prices, and corporate actions using stable listing identifiers. A current symbol or current roster is not a substitute for historical identity.

## Causal revision selection

At decision time \(T\), a record is eligible only when:

\[
effective\_at \le T \quad\text{and}\quad available\_at \le T
\]

Future corrections are counted in `future_records_ignored` but cannot affect the selected result. Eligible revisions must form one unique contiguous chain beginning at revision 1. Duplicate revision numbers, a broken `supersedes_record_id`, a lineage gap, or conflicting snapshot identity makes the result `ambiguous`. A cancellation at the lineage head makes it `incomplete` until replacement evidence exists.

## Evaluation states

| State | Meaning | ABI publishable? |
|---|---|---|
| `resolved` | One causal lineage head, full partition, no missing or unclassified issues | Yes, with provisional/final label |
| `incomplete` | No causal record, partition gap, missing/unclassified issues, or current cancellation | No; ABI and Net Advances are null |
| `ambiguous` | Conflicting identity or non-unique/broken lineage | No; ABI and Net Advances are null |
| `unsupported` | Request is not the raw issue-count ABI | No |

Malformed types, negative counts, unsafe integers, or timestamps without offsets raise an input validation error rather than fabricating an evaluation.

## Mathematics and information loss

First retain the signed spread:

\[
NA_t=A_t-D_t
\]

Then fold it onto the non-negative axis:

\[
ABI_t=|NA_t|
\]

With mover count \(R_t=A_t+D_t\):

\[
0\le ABI_t\le R_t\le N_t
\]

Swapping advances and declines flips the signed spread but preserves ABI:

\[
|A-D|=|D-A|
\]

ABI alone cannot reconstruct direction or the original counts. Production output therefore retains `advances`, `declines`, and `net_advances`.

## Three resolved zero states

| Condition | `breadth_state` | Raw ABI | Interpretation |
|---|---|---:|---|
| \(A=D>0\) | `active_balance` | 0 | Movers exist and cancel exactly |
| \(A=D=0, N>0\) | `no_movers` | 0 | Declared population exists but no issue moved |
| \(N=0\) | `empty_universe` | 0 | No population exists |

These states share arithmetic but not meaning. They must never be collapsed into a generic “flat market” label.

## Synthetic resolved example

The package's complete synthetic mirror uses the same 100-issue universe and policy:

| Scenario | A | D | U | X | M | Q | Net | Raw ABI | State |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---|
| Advances dominate | 60 | 30 | 8 | 2 | 0 | 0 | +30 | 30 | advances imbalanced |
| Declines dominate | 30 | 60 | 8 | 2 | 0 | 0 | -30 | 30 | declines imbalanced |

The pair is deliberately synthetic and contract-complete. It proves symmetry, not a market event.

## Bounded Nasdaq observation: same ABI, opposite direction

Nasdaq Trader's official Daily Market Files page describes a downloadable annual file of daily Nasdaq statistics. Its field definitions list the Nasdaq Composite, Advances, Declines, and Unchanged, and say that “Number of Issues” is based on issues active for the date. The official 2026 CSV contained these rows when retrieved at `2026-07-22T22:01:20Z`:

| Date | Composite | Advances | Declines | Unchanged | Author-derived Net | Author-derived raw ABI |
|---|---:|---:|---:|---:|---:|---:|
| 2026-03-25 | 21,929.83 | 3,254 | 1,611 | 224 | +1,643 | 1,643 |
| 2026-05-19 | 25,870.71 | 1,636 | 3,279 | 243 | -1,643 | 1,643 |

The counts and Composite levels are **Nasdaq provider observations**. Net and ABI are **author-derived arithmetic**:

\[
3{,}254-1{,}611=+1{,}643
\]

\[
1{,}636-3{,}279=-1{,}643
\]

\[
|+1{,}643|=|-1{,}643|=1{,}643
\]

This is a strong historical illustration of direction loss, but it is not a `resolved` production result under this package's stricter contract. The free file does not expose a stable row-level roster; exclusions, missing, and unclassified partitions; row publication timestamps; corporate-action/comparison policy; or revision lineage. The two dates are not claimed to have equal universes. The Composite levels are context only: no causal, predictive, or profitability relationship is inferred.

See the [bounded evidence note](./examples/nasdaq-2026-bounded-observation.json), [Nasdaq Daily Market Files](https://www.nasdaqtrader.com/Trader.aspx?id=DailyMarketFiles), and [Nasdaq field definitions](https://www.nasdaqtrader.com/Trader.aspx?id=DailyMarketSummaryDefs).

## Algorithm

```text
validate request and timestamps
if requested metric is not raw issue-count ABI: return unsupported

keep records with effective_at <= decision_time and available_at <= decision_time
if none: return incomplete

require one stable snapshot identity
require unique IDs and a contiguous, unbranched revision lineage
if conflicts exist: return ambiguous

take the causal lineage head
if it is a cancellation: return incomplete
require A + D + U + X + M + Q = N
require M = 0 and Q = 0
if evidence is incomplete: return incomplete with null arithmetic

net = A - D
abi = absolute_value(net)
classify advances, declines, active balance, no movers, or empty universe
return resolved result with counts, signed spread, ABI, clocks, revision, and finality
```

The arithmetic is \(O(1)\) once a lineage head is selected. Sorting \(r\) visible revisions is \(O(r\log r)\) in the reference implementation.

## Implementation and tests

- [Python implementation](./implementations/python/absolute_breadth_index.py)
- [TypeScript implementation](./implementations/typescript/absoluteBreadthIndex.ts)
- [Shared fixture](./datasets/abi-fixtures.json)
- [Python tests](./tests/test_absolute_breadth_index.py)
- [TypeScript tests](./tests/absoluteBreadthIndex.test.ts)

The shared fixture covers direction mirrors, all three zero states, missing and unclassified issues, a broken partition, future evidence, an applied correction, revision and identity conflicts, a lineage gap, cancellation, provisional data, unsupported normalization, and no records.

## Failure modes and limits

- A large raw ABI may reflect a larger universe; compare raw counts only under a stable scope.
- Excluded issues reduce `coverage_ratio` even when the known partition reconciles.
- Provisional resolved outputs may change; they must be labeled provisional.
- A correction changes that session and any separately defined downstream smoother.
- Taking absolute value before smoothing is not equivalent to smoothing signed breadth first.
- Historical association, threshold selection, and trading value require separate point-in-time research with bias controls and out-of-sample validation.

## Visual explanations

- [Evidence and calculation flow](./visuals/mermaid/calculation-flow.md)
- [Historical direction fold](./visuals/static/direction-fold.svg)
- [Resolved zero states](./visuals/static/session-magnitudes.svg)
- [Guided ABI lab](./visuals/animated/abi-playground.html)
- [Visual plan](./visuals/VISUAL-PLAN.md)

## Related topics

- **Net Advances** retains direction.
- **Advance/Decline Ratio** changes the transform and introduces zero-denominator policy.
- **Cumulative Advance/Decline Line** accumulates signed breadth.
- **Normalized Advance/Decline Line** uses a declared signed denominator before accumulation.

## References

See [REFERENCES.md](./REFERENCES.md). Formula definitions, historical observations, package policy choices, and limitations are kept separate throughout.
