ExponentialSmoothingStat
Exponential smoothing with a damped trend and optional seasonality: Holt's method at period 1, Holt-Winters with a seasonal cycle of period updates otherwise.
Additive recurrence (with a = correction(alpha, weight) and analogous b, g, and k the current seasonal-slot index):
sOld = seasons[k]
prev = level
level = a * (value - sOld) + (1 - a) * (prev + phi * trend)
trend = b * (level - prev) + (1 - b) * phi * trend
seasons[k] = g * (value - level) + (1 - g) * sOld
k = (k + 1) mod periodMultiplicative is the same shape with subtraction replaced by division and addition by multiplication; a zero season falls back to 1.0 and a zero level leaves the season as it was, so neither path divides by zero. At period 1 the single season stays at its identity and the recurrence reduces to Holt's level and trend.
With phi == 1.0 the trend is undamped; with phi < 1.0 it is geometrically damped. At beta == 0 the level is an exponentially weighted mean seeded by the first value; it is not com.eignex.kumulant.stat.decay.EwmaMeanStat, which bias-corrects a zero seed instead, so the two differ from the second update on.
The first update seeds the level, a zero trend, and leaves the seasonal vector at its identity (0 additive, 1 multiplicative); every later update runs the recurrence above. Nothing seeds the seasonal vector separately, so the first cycle carries little seasonal signal.
Merge adopts a remote state while empty and otherwise averages level, trend, and seasonal factors, using the remote seasonal phase. This is an approximate roll-up, not replay of the combined ordered observations.
Use cases: smoothing a noisy series and producing short-horizon forecasts when a local trend, a recurring cycle, or both are expected.
Memory: O(period); three scalar cells plus a season array plus a lock.
Update: O(1); single seasonal slot touched per update.
Concurrency: Order-dependent recurrence, same model as com.eignex.kumulant.stat.decay.EwmaMeanStat. Concurrency.Strict and Concurrency.HighWrite lock the body so each update is atomic but the lock serialises arrival, not order; Concurrency.Relaxed drops the lock and the level/trend/seasonal cells race independently with bounded drift; never throws.
Constructors
ExponentialSmoothingStat
Properties
alpha
alphaWeighting
Per-observation smoothing schedule for the level.
beta
betaWeighting
Per-observation smoothing schedule for the trend. Defaults to the level's alphaWeighting.
concurrency
Thread-safety mode fixed at construction. See Concurrency for the shared contract and the implementation's KDoc for its cell and lock strategy.
gamma
gammaWeighting
Per-observation smoothing schedule for the seasonal vector. Defaults to the level's alphaWeighting.
mode
Seasonal coupling; defaults to SeasonalMode.Additive.
period
phi
Functions
create
Create an independent accumulator at the configured baseline. A null concurrency preserves this accumulator's mode; a non-null value overrides it. Modality subtypes narrow the return type to preserve the input shape.
merge
Fold a compatible snapshot values into this accumulator at timestampNanos. Implementations document whether the combine is exact or approximate and which state the snapshot omits. The source accumulator is unaffected.
Time-dependent statistics, such as windows, place the snapshot at timestampNanos, which must share the clock the caller uses for updates and reads. Time-independent statistics ignore it.
read
Return the current result evaluated at timestampNanos. Time-independent statistics ignore the timestamp. Reading does not add an observation.
Snapshot consistency depends on the implementation's synchronisation. Locks protect coupled state under Concurrency.Strict and Concurrency.HighWrite; independently updated cells and JVM striped adders can still yield a best-effort snapshot. Concurrency.Relaxed permits drift across coupled cells.
reset
Restore the configured baseline, including any prior seed. Preserves the configuration and concurrency.