forecast

package
v1.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package forecast holds OpenMRP's standard monthly demand forecaster.

Seasonal EMA is used by both the analytics demand-forecast endpoint and the production scheduler, so it lives here rather than in either caller. It mirrors dashboard/packages/utils/src/seasonal-ema.ts; the two must stay in step or the schedule and the dashboard will disagree about the same demand.

Method:

  1. Seasonal factors — each calendar month's average divided by the overall average, then shrunk toward 1. Most items sell in only a handful of months a year, so the raw factors fit twelve parameters to a few observations and largely memorise noise; shrinking keeps whatever shape is real and discards the amplitude.
  2. Deseasonalize, then smooth to a current base run rate (alpha = 2 / (min(observations, 12) + 1), so recent months weigh more) carrying a damped additive trend.
  3. Forecast = (level + damped slope) x seasonal factor.
  4. Fixed-width confidence band from the last 12 residuals x seasonal factor x z.

The trend term is additive on a deseasonalized series and damped, so it converges to level + slope*phi/(1-phi) instead of compounding. This is not the Holt-Winters that was removed: that trend was multiplicative and produced runaway exponential forecasts. Without any trend at all the forecaster over-forecast a declining book by roughly a fifth, month after month, because nothing in the model could lower the level fast enough to keep up.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Observation

type Observation struct {
	MonthStart time.Time
	Value      float64
}

Observation is one complete month of history. The series must be sorted ascending and must exclude the current partial month, which would otherwise read as a collapse in demand.

type Point

type Point struct {
	Date       time.Time
	Forecast   float64
	LowerBound float64
	UpperBound float64
}

Point is one forecast month. Date is stamped end-of-period (one month past the month being forecast) to match the dashboard's display convention.

func SeasonalEMA

func SeasonalEMA(completeMonths []Observation, baseForecastStart time.Time, numMonths int, zScore float64) []Point

SeasonalEMA forecasts numMonths forward from baseForecastStart, which is the start of the last complete month. Point k covers baseForecastStart + (k + 1) months.

Returns an empty slice for an empty series rather than guessing a level.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL