Add numerically robust rolling-statistics nodes (variance, stddev, z-score) to the std vocabulary #318

Open
opened 2026-07-23 12:52:54 +02:00 by claude · 0 comments
Collaborator

The std vocabulary has no rolling-statistics nodes: no rolling variance, no rolling standard deviation, no z-score. The pattern is reconstructible from shipped members as E[x²]−E[x]²:

ZScore(x,n) = Div(Sub(x, SMA(x,n)),
                  Sqrt(Sub(SMA(Mul(x,x),n), Mul(SMA(x,n), SMA(x,n)))))

— but exactly this form is the textbook catastrophic-cancellation trap over long series: two large near-equal quantities subtracted per cycle, degrading over millions of ticks.

Field evidence (2026-07-22 external field test, triage in #314): the external agent needed a z-score for a mean-reversion strategy and wrote it as a native node. Its first version recomputed the window per tick — O(N) per cycle, runs stalling after 7 minutes over ~13M ticks — and the O(1) running-sum rewrite that fixed the runtime introduced float drift that the run's own review flagged as decaying into noise over the full series (Welford's algorithm absent). Every downstream author who needs a z-score faces the same fork between a slow correct form and a fast wrong one.

A shipped node makes the numerically robust form (Welford / compensated summation) the default instead of leaving the trap to each author. Cut: RollingVar / RollingStd with a length param (alongside the existing SMA / RollingMax / RollingMin family); whether z-score ships as its own node or as a thin composition over them is part of the cut and open.

Related: #316 (self-description principle — new members carry doc-strings from the start).

The std vocabulary has no rolling-statistics nodes: no rolling variance, no rolling standard deviation, no z-score. The pattern is reconstructible from shipped members as `E[x²]−E[x]²`: ``` ZScore(x,n) = Div(Sub(x, SMA(x,n)), Sqrt(Sub(SMA(Mul(x,x),n), Mul(SMA(x,n), SMA(x,n))))) ``` — but exactly this form is the textbook catastrophic-cancellation trap over long series: two large near-equal quantities subtracted per cycle, degrading over millions of ticks. Field evidence (2026-07-22 external field test, triage in #314): the external agent needed a z-score for a mean-reversion strategy and wrote it as a native node. Its first version recomputed the window per tick — O(N) per cycle, runs stalling after 7 minutes over ~13M ticks — and the O(1) running-sum rewrite that fixed the runtime introduced float drift that the run's own review flagged as decaying into noise over the full series (Welford's algorithm absent). Every downstream author who needs a z-score faces the same fork between a slow correct form and a fast wrong one. A shipped node makes the numerically robust form (Welford / compensated summation) the default instead of leaving the trap to each author. Cut: `RollingVar` / `RollingStd` with a `length` param (alongside the existing `SMA` / `RollingMax` / `RollingMin` family); whether z-score ships as its own node or as a thin composition over them is part of the cut and open. Related: #316 (self-description principle — new members carry doc-strings from the start).
claude added the feature label 2026-07-23 12:52:54 +02:00
claude added this to the Measurement reachable — measure ic end-to-end on robust signals milestone 2026-07-23 13:42:58 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#318