Files
QuanTAlib/lib/statistics/cma/Cma.md
T

6.1 KiB

CMA: Cumulative Moving Average

The running average that never forgets. Every single tick you've ever fed it? Still in there, affecting the result. It's like the elephant of technical indicators.

Property Value
Category Statistic
Inputs Source (close)
Parameters source
Outputs Single series (CMA)
Output range Varies (see docs)
Warmup 1 bars
PineScript cma.pine
  • The Cumulative Moving Average (CMA) calculates the arithmetic mean of ALL data points seen so far, not just a fixed window.
  • Similar: SMA, EMA | Trading note: Cumulative Moving Average; running mean of all data points. Anchored VWAP without volume weighting.
  • Validated against TA-Lib, Skender, and Tulip reference implementations where available.

The Cumulative Moving Average (CMA) calculates the arithmetic mean of ALL data points seen so far, not just a fixed window. Unlike SMA or EMA which use a sliding window, CMA treats every historical value with equal weight. As the sample size grows, each new value has diminishing impact on the average.

Historical Context

The concept of a running mean is fundamental to statistics and was formalized by B. P. Welford in 1962 for numerically stable computation. Donald Knuth popularized it in The Art of Computer Programming. While not a traditional trading indicator, CMA is essential for scenarios requiring the true average of all observed data: calculating session VWAP from scratch, averaging tick counts, or computing lifetime average fill prices.

Architecture & Physics

The naive approach (sum all values, divide by count) works for small datasets but fails at scale. After millions of ticks, the running sum can overflow or lose precision.

Welford's Algorithm with FMA

QuanTAlib uses Welford's numerically stable update, enhanced with Fused Multiply-Add (FMA) for maximum precision:

M_n = M_{n-1} + \alpha \cdot (x_n - M_{n-1}) \quad \text{where } \alpha = \frac{1}{n}

Implemented as:

double alpha = 1.0 / n;
double delta = x - mean;
mean = Math.FusedMultiplyAdd(alpha, delta, mean);

This formulation:

  1. Keeps intermediate values near the scale of the actual mean (no overflow)
  2. Requires only O(1) memory (just count and mean)
  3. Achieves O(1) time complexity per update
  4. Uses FMA for single-rounding precision (avoids rounding alpha * delta before adding to mean)
  5. Is mathematically equivalent to M_n = \frac{(n-1) \cdot M_{n-1} + x_n}{n}

Why Not Just Sum?

Consider averaging 10 million tick prices around 50,000 (a futures contract). The naive sum exceeds 5 \times 10^{11}, approaching the precision limits of double. Welford's algorithm keeps the working value around 50,000 throughout, maintaining full precision.

The Diminishing Return Problem

As n grows large, each new value contributes only \frac{1}{n} to the mean. After 1 million samples, a new tick moves the average by roughly 0.0001% of the difference from the current mean. This is mathematically correct but may not be what traders want for responsiveness (use EMA or SMA for that).

Mathematical Foundation

1. Incremental Update (Welford)

M_n = M_{n-1} + \frac{x_n - M_{n-1}}{n}

Where:

  • M_n = cumulative mean after n values
  • M_{n-1} = previous cumulative mean
  • x_n = new value
  • n = total count of values

2. Algebraic Equivalence

M_n = \frac{1}{n} \sum_{i=1}^{n} x_i = \frac{(n-1) \cdot M_{n-1} + x_n}{n}

Performance Profile

Operation Count (Streaming Mode)

Cumulative Mean Arithmetic uses a simple running sum divided by count — no window, no buffer.

Operation Count Cost (cycles) Subtotal
Add value to running sum 1 1 cy ~1 cy
Increment count 1 1 cy ~1 cy
Divide sum by count 1 4 cy ~4 cy
NaN guard + state update 1 2 cy ~2 cy
Total O(1) ~8 cy

Cheapest mean variant — no buffer, no window management. Throughput limited by division latency (~4 cy on modern x86).

Metric Score Notes
Throughput ~5 ns/bar Single division per update.
Allocations 0 Zero-allocation in hot paths.
Complexity O(1) Constant time regardless of history length.
Accuracy 10 Welford's algorithm ensures numerical stability.
Timeliness 1 Maximum lag; every historical value affects output.
Overshoot 0 Never overshoots the input data range.
Smoothness 10 Extremely smooth as n grows (almost constant).

Validation

Library Status Notes
TA-Lib N/A No CMA function.
Skender N/A No CMA function.
Tulip N/A No CMA function.
Mathematical Validated against known formulas.

CMA is a fundamental statistical operation rather than a standard TA library indicator. QuanTAlib validates against mathematical proofs: arithmetic progressions, geometric series, and direct sum/count calculations.

Use Cases

  1. Session VWAP: Calculate volume-weighted average price from session start
  2. Lifetime Averages: Average fill price across all trades
  3. Quality Metrics: Average latency, slippage, or fill rate over time
  4. Baseline Comparison: Compare current price to "all-time average"

Common Pitfalls

  1. Responsiveness: CMA becomes nearly unresponsive after many values. For a reactive average, use SMA or EMA instead.
  2. Memory of Bad Data: A single extreme outlier early in the stream permanently affects the average. Consider filtering before feeding CMA.
  3. No Period Parameter: Unlike SMA/EMA, CMA has no period. It always includes all data. This is by design.
  4. Session Resets: If you need per-session averages, call Reset() at session boundaries.