FerroWave · reference

Regime primitives

Reference for the change-point and scale-energy estimators downstream regime-detection consumers build on.

ferro-wave exposes a small set of regime-detection primitives that operate on the output of an MRA. Downstream signal crates compose these into full regime classifiers — but the primitives themselves live here so every consumer agrees on the math.

Scale-energy ratio

For an MRA with details {dj}j=1J\{d_j\}_{j=1}^{J}, the scale-energy ratio at level jj is

rj=dj2k=1Jdk2r_j = \frac{\|d_j\|^2}{\sum_{k=1}^{J} \|d_k\|^2}

A rising rjr_j for small jj indicates the signal's variance is migrating to higher-frequency bands — a common signature of a vol-expansion regime.

let ratios = mra.scale_energy_ratios();

Wavelet variance

The unbiased estimator of the variance contributed by scale 2j2^j over a window of length NjN_j surviving boundary correction:

ν^j2=1Njndj[n]2\hat{\nu}^2_j = \frac{1}{N_j} \sum_{n} d_j[n]^2
let wv = mra.wavelet_variance();

This is the building block for the scale-by-scale variance plots regime-research produces.

Change-point statistic

A cumulative-sum (CUSUM) statistic on the detail energies, normalized to [0,1][0, 1]:

Sj[t]=1Zjntdj[n]2tNS_j[t] = \frac{1}{Z_j} \sum_{n \le t} d_j[n]^2 - \frac{t}{N}

A change in regime at scale 2j2^j shows up as a deflection in Sj[t]S_j[t]. The statistic itself is the primitive — thresholding and classification are left to the consumer.

let cusum = mra.detail_cusum(level);

Determinism guarantees

All three estimators are pure functions of the input MRA and the chosen wavelet. They allocate exactly one output Vec (sized at call time) and otherwise touch no global state, no PRNG, and no floating-point summation order that depends on system layout. The same inputs produce bit-identical outputs across runs and across architectures with IEEE-754 compliant f64 arithmetic.

This is what lets a backtest's regime signal match production's byte-for-byte — the property the rest of the stack is built around.