# D04-F02-A03 — Traditional McClellan Summation Index: Turn the traditional raw-count mcclellan oscillator into an auditable cumulative breadth state

> **Domain:** D04 — Market Breadth and Internals  
> **Family:** D04-F02 — McClellan Family  
> **Status:** Video-ready  
> **Last reviewed:** 2026-07-25

## Executive summary

Traditional McClellan Summation Index transforms ordered daily breadth in three explicit stages:

\[
x_t=A_t-D_t
\]

\[
F_t=0.10x_t+0.90F_{t-1},\qquad
S_t=0.05x_t+0.95S_{t-1}
\]

\[
SI_t=SI_{t-1}+MO_t,\quad SI_{38}=1000
\]

The 10% and 5% trends correspond to conventional EMA labels 19 and 39. This package uses simple-average seeds at observations 19 and 39, emits its first oscillator at observation 39, preserves recursive state without rounding, and resolves source revisions at an explicit causal cutoff.

## Problem and financial relevance

Daily breadth can be noisy and its scale can change. This topic asks whether recent raw Net Advances is running above or below its slower baseline and cumulative index. It measures a defined transformation and state path; it does not prove prediction, market causation, or profitability.

## Learning objectives

The reader can:

- calculate the exact input transformation and explain its units;
- reproduce the 10%/5% dual-EMA warm-up;
- distinguish current input sign from oscillator sign;
- apply the documented cumulative seed when present;
- reject missing, provisional, cancelled, conflicting, or incompatible evidence;
- recompute a corrected suffix without leaking a future revision;
- distinguish this topic from the other five McClellan-family variants.

## Prerequisites

- Net Advances
- Exponential Moving Average
- Traditional McClellan Oscillator
- Ordered time series, revisions, and simple averages

## Scope and variant contract

The package starts the pre-output accumulator at +1000 and then adds every ready oscillator value. This is a reproducible teaching seed, not a claim that a newly started series is calibrated to a publisher's history.

Excluded: alternative EMA lengths, first-value seeding, silent interpolation, vendor-specific thresholds, divergence signals, ratio-adjusted volume unless named, and any performance promise.

| Nearby variant | Different input or state | Why it is not interchangeable |
|---|---|---|
| Traditional issue-count oscillator | Raw A-D | Magnitude changes with the issue population. |
| Ratio-adjusted issue oscillator | 1000(A-D)/(A+D) | Normalization changes units and zero-denominator behavior. |
| Traditional Summation Index | Cumulative raw-count oscillator | Adds a path-dependent state and seed. |
| RASI | Cumulative ratio-adjusted oscillator | Uses normalized input and a zero neutral seed. |
| Volume Oscillator | Up Volume minus Down Volume | Measures allocated share volume, not equal-vote issue counts. |
| Volume Summation Index | Cumulative volume oscillator | Adds volume units, cumulative state, and a zero seed. |

## Input data contract

Each record contains a unique `session_sequence`, `session_date`, `effective_at`, `available_at`, non-negative `revision`, `event_type`, `source_evidence_state`, stable series identity, and the required breadth fields. Revisions after the caller's cutoff are ignored. Retained revisions must start at zero, remain contiguous, and have one unique head.

For issue topics, advances, declines, unchanged, excluded, and unclassified are non-negative integer categories. The complete universe partition must reconcile, and ratio-adjusted topics use only advances plus declines in the denominator.

A validated zero signed input is a real observation; a missing session is not silently replaced with zero.

## Parameters and initialization

| Parameter | Canonical value | Meaning |
|---|---:|---|
| Fast smoothing constant | 0.10 | 10% Trend, conventional EMA-19 |
| Slow smoothing constant | 0.05 | 5% Trend, conventional EMA-39 |
| Fast seed | SMA of observations 1–19 | First fast state |
| Slow seed | SMA of observations 1–39 | First slow state |
| First oscillator | Observation 39 | Both states exist |
| Cumulative starting level | 1000 | State immediately before the first ready oscillator |
| Rounding | Display only | Recursive state remains full precision |

The cumulative state starts immediately before the first ready oscillator at `1000`. At observation 39 it adds that day's oscillator. The starting level translates the full path; it does not change daily increments.

## Output contract

Every resolved record produces `input_value`, `fast_ema`, `slow_ema`, `oscillator`, optional `index_value`, `status`, observation number, and session date. Status is `warming_fast`, `warming_slow`, or `ready`.

The enclosing result is `resolved`, `incomplete`, `ambiguous`, or `unsupported`. Non-resolved results expose no ordinary points, preventing a partial path from looking authoritative.

## Mathematical formulation and intuition

The exponential update is:

\[
EMA_t=EMA_{t-1}+\alpha(z_t-EMA_{t-1})
\]

The fast state closes 10% of its forecast error each observation; the slow state closes 5%. Their difference is positive when recent breadth is above its slower state. Older data never drops out exactly.

Cumulative state adds each ready oscillator, so corrections propagate through both EMA memory and every later accumulated value.

## Algorithm

1. Apply the explicit `available_at <= cutoff` rule.
2. Resolve one contiguous revision head for every session sequence.
3. Reject cancellation, provisional evidence, duplicate revisions, gaps, or series-identity breaks atomically.
4. Transform each resolved record using the topic-specific formula.
5. Seed the fast EMA with observations 1–19 and the slow EMA with observations 1–39.
6. Emit the oscillator from observation 39.
7. Add every ready oscillator to the declared cumulative seed.
8. Preserve unrounded state and provenance.

## Pseudocode

```text
resolve revisions available at cutoff
if evidence is incomplete, ambiguous, cancelled, or incompatible:
    return atomic non-resolved result with no points

transform each accepted record into z
fast = SMA(z[1..19]) at observation 19
slow = SMA(z[1..39]) at observation 39
for every later observation:
    fast = fast + 0.10 * (z - fast)
    slow = slow + 0.05 * (z - slow)
oscillator = fast - slow
index = declared_seed + cumulative_sum(oscillator)
```

## Synthetic worked example

The fixture contains 60 deterministic weekday sessions. The first 39 are balanced, so both EMA seeds and the first oscillator are zero.

| Point | Input | Fast EMA | Slow EMA | Oscillator | Index |
|---|---:|---:|---:|---:|---:|
| First ready, observation 39 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1000.000000 |
| Final, observation 60 | -90.000000 | 10.276097 | 9.410247 | 0.865849 | 1086.309827 |

Exact inputs and expected values are in [the shared fixture](./datasets/shared-fixture.json). The values are synthetic teaching inputs and author-derived calculations, not market observations.

## Choose this variant when

Choose this index when the governed raw issue-count history and its cumulative path are the teaching object.

Accumulation adds path dependence: the same current oscillator can sit at different index levels after different histories. The family decision is therefore not “which line looks better?” It is “which observation unit and which state contract answer the question?”

| Decision | This topic | Choose a sibling when… |
|---|---|---|
| Daily unit | raw issues | the required observation unit differs |
| Output memory | dual EMA plus cumulative state | the task needs only the daily oscillator |
| Source-scale behavior | Changing the teaching seed translates every index level by a constant; it does not change a single daily increment. | a different scale policy is required |
| Invalid evidence | Source evidence is provisional, so no cumulative suffix is allowed. | the source cannot satisfy this contract |

## Nonzero guided-lab path

The implementation fixture remains deliberately simple for exact cross-language checks. The guided lab uses a separate 60-session synthetic teaching path so that the first ready screen is informative rather than empty.

| Observation | Regime | Input | Fast | Slow | Oscillator | Index |
|---:|---|---:|---:|---:|---:|---:|
| 39 | reversal | 80.0000 | 3.6478 | 22.5641 | -18.9163 | 981.0837 |
| 45 | stress and recovery | -80.0000 | 34.5441 | 36.9243 | -2.3802 | 975.8610 |
| 60 | stress and recovery | 20.0000 | 12.4050 | 19.1039 | -6.6989 | 836.5249 |

At observation 45, changing the source scale from 1× to 2× changes the oscillator from -2.3802 to -4.7605. Changing the teaching seed translates every index level by a constant; it does not change a single daily increment.

The records and independently derived checkpoints are stored in [playground-scenarios.json](./datasets/playground-scenarios.json). They are synthetic and are not used as empirical market evidence.

## Implementation and tests

- [Python reference](./implementations/python/)
- [TypeScript reference](./implementations/typescript/)
- [Python tests](./tests/)
- [Fixture methodology](./datasets/README.md)
- [Guided-lab teaching scenarios](./datasets/playground-scenarios.json)
- [Guided-lab teaching scenarios](./datasets/playground-scenarios.json)
- [Guided-lab teaching scenarios](./datasets/playground-scenarios.json)
- [Guided-lab teaching scenarios](./datasets/playground-scenarios.json)
- [Guided-lab teaching scenarios](./datasets/playground-scenarios.json)
- [Guided-lab teaching scenarios](./datasets/playground-scenarios.json)
- [Independent worked arithmetic](./examples/worked-example.json)

Tests cover warm-up, exact fixture parity, scaling, cumulative recurrence, zero or invalid partitions, missing sequences, duplicate revisions, future-revision cutoff behavior, and series identity breaks.

## Source-role boundary

The first-party methodology supports the transform and sequence of operations; the SMA initialization, software statuses, synthetic path, and source-scale lab are package choices. No interpretive threshold from a methodology article is treated as universal evidence.

## Historical-example decision: deferred

A named historical example could improve context, but a reproducible case needs the exact venue universe, final issue or volume allocation, revisions, source timestamp, volume adjustment basis, cumulative calibration history, and redistribution permission. The first-party methodology does not supply all of those fields as one reusable dataset. This package therefore uses a visibly synthetic fixture and does not invent a historical value.

## Edge cases and limitations

- A missing observation is not a zero input.
- SMA and first-value EMA seeds differ early in a series.
- Changing universe or volume methodology requires a series break.
- Cumulative levels depend on the stated starting constant.
- A corrected historical input changes the entire dependent suffix.
- Raw volume and raw issue-count magnitudes are not stable across all eras.
- Ratio adjustment improves issue-count scale comparability but does not make different universes equivalent.
- Formula correctness is not evidence of a profitable signal.

## Visual explanations

- [Calculation flow](./visuals/mermaid/calculation-flow.md)
- [Family transform](./visuals/static/family-transform.svg)
- [Worked state path](./visuals/static/worked-state.svg)
- [Guided playground](./visuals/animated/playground.html)
- [Visual plan](./visuals/VISUAL-PLAN.md)
- [Visual QA record](./visuals/QA.md)

## Related catalog topics

- Net Advances supplies issue-count breadth.
- EMA supplies the recursive smoothing contract.
- Traditional McClellan Oscillator is the family foundation.
- Ratio-Adjusted Summation Index (RASI) is the next handoff.

## References

See [REFERENCES.md](./REFERENCES.md). Sourced formulas, author choices, synthetic inputs, and derived arithmetic are kept separate.
