kumulant

stat.forecast

Predictive recurrences with multi-cell state. Their results expose forecast(steps) projections, distinguishing them from the decay family's running-moment shape.

Picking a forecaster

StatOutput shapeReach for it when
HoltStatLevel + trend + damped forecastThe stream has a slow-moving trend on top of noise and you want a short-horizon forecast.
SeasonalSmoothingStatLevel + trend + seasonal factor vector (length period)The stream has a repeating cycle (daily, weekly, anything periodic) on top of level and trend. The classical Holt-Winters method, additive or multiplicative.
RecursiveVarianceStatGARCH-style volatility tracker sigma² = omega + alpha * value² + beta * sigma²Volatility tracking where a long-run baseline matters; compared with EwmaVarianceStat it adds omega and decouples the shock and persistence coefficients.

Holt's method

HoltStat tracks two coupled cells:

  • level: the smoothed running level, updated as level = alpha * value + (1 - alpha) * (priorLevel + priorTrend).

  • trend: the smoothed level-to-level change, updated as trend = beta * (level - priorLevel) + (1 - beta) * priorTrend.

The result exposes forecast(steps) which projects the level forward by a damped trend: forecast(h) = level + (1 - phi^h) / (1 - phi) * trend. The damping factor phi in (0, 1] geometrically discounts the trend's contribution to long-horizon forecasts; phi = 1.0 recovers the classical undamped Holt. Pick phi close to 1 for streams with sustained trends, lower (~0.8) for streams where the trend tends to revert.

Seasonal smoothing (Holt-Winters)

SeasonalSmoothingStat adds a seasonal[period] vector to Holt's shape. Each update applies one of two compositions:

  • Additive: level + seasonal[t mod period] (use when the seasonal amplitude is independent of level).

  • Multiplicative: level * seasonal[t mod period] (use when the seasonal amplitude scales with level; typical for ratios, sales, anything where seasonal effects multiply rather than add).

The result exposes the same forecast(steps) projection, now factoring in the appropriate seasonal slot for each step.

Recursive variance (GARCH-1,1)

RecursiveVarianceStat applies the standard GARCH(1,1) recurrence: sigma² = omega + alpha * value² + beta * sigma². Three coefficients:

  • omega: long-run baseline variance.

  • alpha: sensitivity to the latest shock (squared value).

  • beta: persistence of the prior variance.

alpha + beta < 1 is the standard stationarity condition; the long-run variance is omega / (1 - alpha - beta). Pick this over EwmaVarianceStat when the long-run floor matters or you want to decouple shock and persistence.

Merge

All three forecasters merge only approximately. The smoothing recurrences are order-dependent with no exact parallel combine, so the merge averages the coupled cells: level and trend for HoltStat, plus the seasonal factor vector for SeasonalSmoothingStat and the running variance for RecursiveVarianceStat. Treat merge as a roll-up convenience; for the truest forecast, feed one stat the ordered stream.

Concurrency

All three stats keep multi-cell coupled state (level + trend; level + trend + seasonal vector; variance + omega/alpha/beta parameters) and need consistent reads. Locked under com.eignex.kumulant.core.Concurrency.Strict / com.eignex.kumulant.core.Concurrency.HighWrite. Under com.eignex.kumulant.core.Concurrency.Relaxed the cells race; results may drift briefly under contention but never throw.

Types

Link copied to clipboard
@Serializable
@SerialName(value = "HoltResult")
data class HoltResult(val level: Double, val trend: Double, val phi: Double) : Result

Snapshot from a HoltStat: the current level and trend plus the damping factor.

Link copied to clipboard
class HoltStat(val alphaWeighting: DecayWeighting.Alpha, val betaWeighting: DecayWeighting.Alpha = alphaWeighting, val phi: Double = 1.0, val concurrency: Concurrency = Concurrency.None) : SeriesStat<HoltResult>

Double exponential smoothing (Holt's method) with optional damping.

Link copied to clipboard
@Serializable
@SerialName(value = "RecursiveVarianceResult")
data class RecursiveVarianceResult(val variance: Double, val omega: Double, val alpha: Double, val beta: Double) : Result

Snapshot from a RecursiveVarianceStat: the current variance and the recurrence coefficients.

Link copied to clipboard
class RecursiveVarianceStat(val omega: Double, val alpha: Double, val beta: Double, val concurrency: Concurrency = Concurrency.None) : SeriesStat<RecursiveVarianceResult>

Generic recursive variance: sigma^2_t = omega + alpha * value_t^2 + beta * sigma^2_{t-1}.

Link copied to clipboard
@Serializable
enum SeasonalMode : Enum<SeasonalMode>

Additive vs multiplicative seasonal coupling.

Link copied to clipboard
@Serializable
@SerialName(value = "SeasonalSmoothingResult")
data class SeasonalSmoothingResult(val level: Double, val trend: Double, val seasons: List<Double>, val currentSlot: Int, val phi: Double, val mode: SeasonalMode) : Result

Snapshot from a SeasonalSmoothingStat: level, trend, seasonal factors, and forecast machinery.

Link copied to clipboard
class SeasonalSmoothingStat(val alphaWeighting: DecayWeighting.Alpha, val betaWeighting: DecayWeighting.Alpha, val gammaWeighting: DecayWeighting.Alpha, val period: Int, val mode: SeasonalMode = SeasonalMode.Additive, val phi: Double = 1.0, val concurrency: Concurrency = Concurrency.None) : SeriesStat<SeasonalSmoothingResult>

Triple exponential smoothing (Holt-Winters): adds a seasonal component of period to HoltStat's level/trend recurrence. Supports additive and multiplicative seasonality.