foresight

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 10 Imported by: 0

README

foresight-go

Go Reference CI

Time series forecasting in Go that picks its model by what would have worked.

foresight fits several models to a series, replays the past to see how each would have done, chooses by out-of-sample error and reports intervals taken from the errors actually observed. It uses the standard library only and every result is deterministic.

This is the Go edition of the Rust crate foresight. It is written in Go, not wrapped: no cgo, nothing to link.

Website: https://milkway.github.io/foresight-go/ · Reference: https://pkg.go.dev/github.com/milkway/foresight-go · Português

Install

go get github.com/milkway/foresight-go

Go 1.22 or later.

Use

import foresight "github.com/milkway/foresight-go"

// monthly data whose first observation is in March
y := foresight.Monthly(values, 2)

// replay the last 36 months, 12 months ahead, with every built-in model
report, err := foresight.DefaultBacktest().Run(y, foresight.Defaults())
if err != nil {
	log.Fatal(err)
}

best := report.Best()
fmt.Printf("%s: MAPE %.1f%%\n", best.Name, best.Score)
for _, p := range best.Forecast {
	i, _ := p.Interval(0.80)
	fmt.Printf("%2d %.0f [%.0f, %.0f]\n", p.Horizon, p.Mean, i.Lower, i.Upper)
}

// the total of the next six months, with its own interval
halfYear, _ := best.Cumulative(6)

One model on its own:

// seasonal ARIMA on the log scale
fit, err := foresight.Log(foresight.Airline()).Fit(y)
nextYear := fit.Forecast(12)

// orders chosen from the data, inspected
auto, err := foresight.AutoArima{}.Select(foresight.Monthly(logValues, 2))
fmt.Println(auto.Order())

A trend that bends, with dated events:

model := foresight.Prophet{Events: []foresight.Event{
	{Name: "campaign", Positions: []int{10, 34, 58, 82, 106, 130}}, // future ones included
	{Name: "new_law", Step: true, StepFrom: 80},                     // a lasting change of level
}}
fit, err := model.Estimate(y)
fmt.Println(fit.Changepoints(), fit.Effects())

A model of your own joins the backtest by implementing Model.

What is in it

Piece What it does
Series values + seasonal period; slices keep season and position
Model / Fitted fit once, forecast any horizon, inspect parameters
Models Mean, Naive, Drift, SeasonalNaive, Theta, HoltWinters, LogLinear (optionally deflated by a price index), Arima (seasonal, exact maximum likelihood, optionally with regressors), AutoArima (differences by tests, orders by stepwise search), Ets (the exponential smoothing family in state space form), AutoEts, Prophet (trend with changepoints, Fourier seasonality, dated events and steps), Tbats (several seasonal periods, not necessarily whole numbers), Croston (intermittent demand, with the SBA and TSB variants)
Stl, Mstl, Decomposed trend, seasonal patterns and remainder by LOESS, for one or several periods; any model on the seasonally adjusted series
Ensemble several models combined: plain average, median, weights by inverse error or stacked weights
Interpolate, Outliers, Clean gaps filled and outliers found and replaced, with the season taken into account
Transformed any model on the log or another Box-Cox scale (Log, WithBoxCox, WithGuerrero)
Regressors external variables aligned with the data, Fourier terms, SeasonalDummies
Defaults, Thorough ready sets of candidates: the models that fit in a moment, and those plus the automatic choices and the ensembles
Backtest rolling origin (expanding or fixed window) on all cores, or on as many as SetMaxThreads allows; MAPE, MAE, RMSE, MASE and bias by horizon; average of the best models; choice by out-of-sample error
Intervals empirical quantiles of the backtest errors, by horizon and for cumulative totals
Measures and tests MAPE, Bias, MAE, RMSE, MASE, Quantile, ACF, KPSS, NDiffs, NSDiffs, SeasonalStrength

How it differs from the usual toolkits

Most forecasting libraries choose a model by an in-sample information criterion and derive intervals from distributional assumptions. Here the choice and the intervals both come from forecasts made without seeing the future they are judged against. The interval for a total (say, the rest of a fiscal year) is measured on totals, because adding up monthly limits overstates its uncertainty.

Checked

Against What Agreement
The Rust crate backtest of four models on two public series: errors and bias by horizon, quantiles, forecasts, intervals and the choice the same numbers (relative difference under 10⁻⁹)
The Rust crate Prophet, KPSS, strength of seasonality the same numbers (under 10⁻⁸)
The Rust crate ARIMA, regression with ARIMA errors, ETS: likelihood the same (under 10⁻⁶)
The Rust crate ARIMA and ETS forecasts; automatic orders and automatic ETS on three series forecasts within the precision of the search; the same models chosen
The Rust crate STL, MSTL, forecasts by decomposition, Croston, SBA and TSB, outliers and cleaning the same numbers (under 10⁻⁸)
The Rust crate ensembles: weights and forecasts; TBATS: structure chosen, likelihood and forecasts; backtest of 18 candidates the same structure and the same choice; forecasts within the precision of the search
R package forecast 9.0.2 seasonal naive, random walk with drift exact
R package forecast 9.0.2 Theta forecasts within 0.1%

The tests are in rust_test.go, models_test.go, more_test.go and r_test.go. The Rust crate is in turn compared with the R packages forecast and prophet.

Data

  • testdata/piaui_revenue.csv: monthly ICMS and FPE revenue of the state of Piauí, Brazil, March 2017 to June 2026 (Siconfi/STN, RREO Anexo 03), with the chained IPCA price index (BCB/SGS 433). Public data.
  • testdata/air_passengers.csv: the classic monthly airline passengers series (Box & Jenkins, 1976).

Status

Early: the API may change before 1.0.

Changes

See CHANGELOG.md.

Development

scripts/dev-check.sh   # gofmt, go vet, go test

Authors

See CITATION.cff to cite the software.

License

MIT. See LICENSE.

Documentation

Overview

Package foresight forecasts time series and picks its model by what would have worked.

It fits several models to a series, replays the past to see how each would have done (a rolling-origin backtest), chooses by out-of-sample error and reports intervals taken from the errors actually observed, including intervals for the total of the next k periods. It has no dependencies outside the standard library and every result is deterministic.

y := foresight.Monthly(values, 2) // first observation in March
report, err := foresight.DefaultBacktest().Run(y, foresight.Defaults())
if err != nil {
	log.Fatal(err)
}
best := report.Best()
for _, p := range best.Forecast {
	i, _ := p.Interval(0.80)
	fmt.Println(p.Horizon, p.Mean, i.Lower, i.Upper)
}
total, _ := best.Cumulative(6) // the next six periods, with its own interval

A single model is used through the Model interface:

fit, err := foresight.Theta{}.Fit(foresight.NonSeasonal(values))
next := fit.Forecast(3)

Besides the models there are decompositions (Stl, Mstl), combinations of models (Ensemble) and the cleaning of gaps and outliers (Clean).

This is the Go edition of the Rust crate of the same name (https://crates.io/crates/foresight). The two are checked against each other and against the R packages forecast and prophet on public data.

Example

Replay the past with every built-in model, take the best and forecast.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	y := foresight.Monthly(sales(), 0) // the first observation is in January
	report, err := foresight.DefaultBacktest().Run(y, foresight.Defaults())
	if err != nil {
		fmt.Println(err)
		return
	}
	best := report.Best()
	fmt.Printf("%s, MAPE %.1f%%\n", best.Name, best.Score)
	for _, p := range best.Forecast[:3] {
		i, _ := p.Interval(0.80)
		fmt.Printf("%d: %.1f [%.1f, %.1f]\n", p.Horizon, p.Mean, i.Lower, i.Upper)
	}
	total, _ := best.Cumulative(6)
	fmt.Printf("next six months: %.0f\n", total.Mean)
}
Output:
log_linear, MAPE 3.1%
1: 164.2 [154.7, 172.1]
2: 120.2 [113.5, 125.3]
3: 136.7 [128.8, 142.6]
next six months: 862

Index

Examples

Constants

View Source
const KPSS5Percent = 0.463

KPSS5Percent is the 5% critical value of the KPSS test for level stationarity.

View Source
const SeasonalStrengthThreshold = 0.64

SeasonalStrengthThreshold is the seasonal strength above which a seasonal difference is taken.

Variables

View Source
var (
	// ErrFewOrigins: the series is too short for at least one pair at the
	// longest horizon.
	ErrFewOrigins = errors.New("foresight: series too short for the backtest")
	// ErrNoCandidate: no candidate gave finite forecasts at every origin and
	// from the whole series.
	ErrNoCandidate = errors.New("foresight: no candidate could be fitted at every origin")
	// ErrLevels: a level of the intervals is not above 0 and below 1.
	ErrLevels = errors.New("foresight: levels must be above 0 and below 1")
)

Errors of a backtest.

View Source
var (
	// ErrTooShort: the series has too few observations for the model.
	ErrTooShort = errors.New("foresight: series too short for the model")
	// ErrNotFinite: the series has values that are not finite numbers.
	ErrNotFinite = errors.New("foresight: series has values that are not finite")
	// ErrNotPositive: the model needs values greater than zero.
	ErrNotPositive = errors.New("foresight: model needs positive values")
	// ErrNotSeasonal: the model needs a seasonal period of at least 2.
	ErrNotSeasonal = errors.New("foresight: model needs a seasonal series")
	// ErrNoFit: the estimation did not reach a usable result.
	ErrNoFit = errors.New("foresight: model could not be fitted")
	// ErrConfig: the configuration of the model is not valid: a negative
	// order, a value that is not one of the named ones, a model that is
	// missing.
	ErrConfig = errors.New("foresight: invalid configuration of the model")
	// ErrHorizon: the horizon asked of [Forecast] is negative.
	ErrHorizon = errors.New("foresight: negative horizon")
	// ErrForecast: a forecast is not a finite number, as when regressors stop
	// short of the horizon or a transformation cannot be brought back.
	ErrForecast = errors.New("foresight: forecast is not finite")
)

Errors returned by the models when a series does not suit them. A model never makes up a fit.

View Source
var ErrLength = errors.New("foresight: lengths differ")

ErrLength is returned when two things that must have the same number of observations do not.

View Source
var ErrRegressors = errors.New("foresight: regressors do not cover the series or are collinear")

ErrRegressors is returned when the regressors do not cover the history or the horizon, or cannot be told apart from each other or from the constant.

Functions

func ACF

func ACF(y []float64, maxLag int) []float64

ACF returns the autocorrelations of y at lags 1 to maxLag; nothing for a maxLag of zero or less.

func Bias

func Bias(actual, forecast []float64) float64

Bias is the mean of (forecast − actual) / actual, in percent: positive when the forecasts run above what happened. Pairs whose actual value is zero are left out.

func Clean added in v0.3.0

func Clean(values []float64, period int) ([]float64, bool)

Clean returns the series with the gaps filled and the outliers replaced. It reports false when fewer than 8 values are known.

func Difference added in v0.2.0

func Difference(y []float64, lag int) []float64

Difference returns y differenced once at the given lag (1 for the ordinary difference). A lag of zero or less, or one that is not shorter than y, gives nothing.

func Forecast

func Forecast(m Model, y Series, h int) ([]float64, error)

Forecast fits the model and forecasts the h periods after the last observation.

Besides the errors of the model, it returns ErrHorizon for a negative h, ErrConfig for a nil model, ErrRegressors when the regressors of the model do not reach the horizon and ErrForecast when a forecast is not finite: regressors that stop short inside another model, or a transformation that cannot be brought back.

func Interpolate added in v0.3.0

func Interpolate(values []float64, period int) ([]float64, bool)

Interpolate fills the gaps. Without seasonality (period under 2, or a series not longer than two full cycles) by straight lines between the neighbours; with it, the straight lines are drawn on the seasonally adjusted series and the seasonal pattern is put back, so a gap in December is filled with a December. It reports false when no value is known.

func KPSS added in v0.2.0

func KPSS(y []float64) (float64, bool)

KPSS returns the statistic of the test of Kwiatkowski, Phillips, Schmidt & Shin (1992) for the null hypothesis that the series is stationary around a constant level, with a Bartlett window of ⌊3√n / 13⌋ lags. Large values reject stationarity; the 5% critical value is KPSS5Percent. It reports false for fewer than 3 observations or a statistic that is not finite.

func MAE

func MAE(actual, forecast []float64) float64

MAE is the mean absolute error.

func MAPE

func MAPE(actual, forecast []float64) float64

MAPE is the mean absolute percentage error, in percent. Pairs whose actual value is zero are left out. NaN when there is no pair.

func MASE

func MASE(actual, forecast []float64, scale float64) float64

MASE is the mean absolute scaled error given the scale from MASEScale.

func MASEScale

func MASEScale(train []float64, period int) (float64, bool)

MASEScale is the scale of the mean absolute scaled error: the in-sample mean absolute error of the seasonal naive forecast (naive when period is 1). It reports false when the training data is no longer than one period or the scale is zero.

func MaxThreads added in v0.3.1

func MaxThreads() int

MaxThreads returns the most goroutines a backtest or an ensemble will use: what was set with SetMaxThreads, or the number of cores Go may use.

func NDiffs added in v0.2.0

func NDiffs(y []float64, limit int) int

NDiffs returns the number of ordinary differences needed for the series to pass the KPSS test at 5%, at most limit.

func NSDiffs added in v0.2.0

func NSDiffs(y []float64, period int) int

NSDiffs returns the number of seasonal differences (0 or 1) suggested by the strength of the seasonality.

func Quantile

func Quantile(v []float64, p float64) (float64, bool)

Quantile returns the quantile p of v with linear interpolation (type 7, the default in R); p under 0 is read as 0 and over 1 as 1. v does not need to be sorted; values that are not numbers are sorted after all the others, so the quantiles that reach them are not numbers either. It reports false for an empty slice or a p that is not a number.

func RMSE

func RMSE(actual, forecast []float64) float64

RMSE is the root mean squared error.

func SeasonalStrength added in v0.2.0

func SeasonalStrength(y []float64, period int) (float64, bool)

SeasonalStrength returns the strength of seasonality in [0, 1] (Wang, Smith & Hyndman, 2006): 1 − Var(remainder) / Var(seasonal + remainder), from a classical additive decomposition (centred moving average and seasonal means). It reports false for non-seasonal or short series (fewer than two cycles plus one observation).

func SetMaxThreads added in v0.3.1

func SetMaxThreads(n int)

SetMaxThreads limits the goroutines used at a time by each backtest and each ensemble, in the whole process. Zero, the default, stands for every core Go may use (GOMAXPROCS); a negative number is read as zero.

The results do not depend on the number of goroutines.

Types

type Arima added in v0.2.0

type Arima struct {
	// P, D and Q are the orders of the autoregression, of the differences
	// and of the moving average; none may be negative.
	P, D, Q int
	// Seasonal orders, ignored for series without seasonality.
	SeasonalP, SeasonalD, SeasonalQ int
	// Constant says whether a mean or a drift is estimated.
	Constant Constant
	// Regressors are external variables, with rows for the history and for
	// the periods to forecast. The zero value is none.
	Regressors Regressors
}

Arima is ARIMA(P, D, Q)(SeasonalP, SeasonalD, SeasonalQ) with the seasonal period of the series.

The series is differenced (D ordinary and SeasonalD seasonal differences) and an ARMA model is fitted to the result by exact Gaussian maximum likelihood, computed with the innovations algorithm. The search runs over partial autocorrelations, so the estimates are always stationary and invertible. The likelihood of a mixed model can have more than one peak, so the search starts from three points and keeps the best.

With Regressors, the model is a regression whose errors follow the ARIMA model; the coefficients of the regression and of the model are estimated together.

For series whose swings grow with the level, fit on the log scale with Log.

func Airline added in v0.2.0

func Airline() Arima

Airline returns the "airline model", ARIMA(0,1,1)(0,1,1): a good default for seasonal series, usually on the log scale.

Example

Seasonal ARIMA on the log scale, the model that does best on many monthly series.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	model := foresight.Log(foresight.Airline())
	fit, err := model.Fit(foresight.Monthly(sales(), 0))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(model.Name())
	for _, v := range fit.Forecast(3) {
		fmt.Printf("%.0f\n", v)
	}
}
Output:
log_arima_011_011
164
121
137

func (Arima) Description added in v0.2.0

func (a Arima) Description() string

Description is a one-line description of the model.

func (Arima) Estimate added in v0.2.0

func (a Arima) Estimate(y Series) (*ArimaFit, error)

Estimate fits the model and returns everything that was estimated. It returns ErrConfig for a negative order or a Constant that is not one of the named choices.

func (Arima) Fit added in v0.2.0

func (a Arima) Fit(y Series) (Fitted, error)

Fit estimates the model; see Arima.Estimate.

func (Arima) Name added in v0.2.0

func (a Arima) Name() string

Name is the identifier of the model, with its orders.

type ArimaFit added in v0.2.0

type ArimaFit struct {

	// AR holds φ₁, φ₂, …: X(t) = φ₁X(t−1) + … + Z(t) + θ₁Z(t−1) + …
	AR []float64
	// MA holds θ₁, θ₂, …
	MA []float64
	// SeasonalAR holds Φ₁, Φ₂, … at the seasonal lags.
	SeasonalAR []float64
	// SeasonalMA holds Θ₁, Θ₂, … at the seasonal lags.
	SeasonalMA []float64
	// HasConstant says whether a constant was estimated; Constant is then
	// the mean of the differenced series.
	HasConstant bool
	Constant    float64
	// Regression has the coefficient of each regressor.
	Regression []Param
	// Sigma2 is the innovation variance (maximum likelihood, not corrected
	// for degrees of freedom).
	Sigma2 float64
	// LogLikelihood is the Gaussian log-likelihood; AIC, AICc and BIC are
	// the information criteria that come from it. For an exact fit, whose
	// likelihood has no bound, a very large number stands for it, so the
	// criteria stay finite and comparable.
	LogLikelihood float64
	AIC           float64
	AICc          float64
	BIC           float64
	// Residuals are the one-step prediction errors of the differenced
	// series.
	Residuals []float64
	// contains filtered or unexported fields
}

ArimaFit is an estimated ARIMA model.

func (*ArimaFit) Forecast added in v0.2.0

func (f *ArimaFit) Forecast(h int) []float64

Forecast returns the forecasts for the h periods after the last observation. Where the regressors have no value for a period, the forecast is not a number. It returns nothing for an h of zero or less, or for a fit that did not come from Arima.Estimate.

func (*ArimaFit) ForecastVariance added in v0.2.0

func (f *ArimaFit) ForecastVariance(h int) []float64

ForecastVariance returns the variance of the forecast error 1 to h periods ahead, on the scale the model was fitted on. It returns nothing for an h of zero or less, or for a fit that did not come from Arima.Estimate.

func (*ArimaFit) IsWellBehaved added in v0.2.0

func (f *ArimaFit) IsWellBehaved(margin float64) bool

IsWellBehaved reports whether every root of the four polynomials is farther from the unit circle than margin (such as 1.01).

func (*ArimaFit) Order added in v0.2.0

func (f *ArimaFit) Order() (p, d, q int)

Order returns the orders (p, d, q).

func (*ArimaFit) Params added in v0.2.0

func (f *ArimaFit) Params() []Param

Params returns the coefficients, the orders and the fit.

func (*ArimaFit) Period added in v0.2.0

func (f *ArimaFit) Period() int

Period returns the seasonal period of the series the model was fitted on.

func (*ArimaFit) SeasonalOrder added in v0.2.0

func (f *ArimaFit) SeasonalOrder() (p, d, q int)

SeasonalOrder returns the seasonal orders (P, D, Q).

type AutoArima added in v0.2.0

type AutoArima struct {
	// Limits of the search: the highest orders and the most differences. A
	// zero stands for the default of that limit alone: 5, 5, 2, 2, 2 and 1.
	// A negative number is a limit of zero: MaxSeasonalP: -1 allows no
	// seasonal autoregression, MaxD: -1 no ordinary difference.
	MaxP, MaxQ, MaxSeasonalP, MaxSeasonalQ, MaxD, MaxSeasonalD int
	// FixDifferences uses D and SeasonalD, which may not be negative,
	// instead of testing.
	FixDifferences bool
	D, SeasonalD   int
	// Criterion ranks the models (default ByAICc).
	Criterion Criterion
	// MaxModels is the most models the search will fit (default 94, also
	// for a negative number).
	MaxModels int
	// Regressors are external variables of a regression with ARIMA errors;
	// the differences are then decided on what the regression leaves
	// unexplained.
	Regressors Regressors
}

AutoArima is seasonal ARIMA with orders chosen from the data (Hyndman & Khandakar, 2008).

The differences come first: a seasonal difference when the seasonality is strong (NSDiffs), then as many ordinary differences as the KPSS test asks for (NDiffs). The remaining orders are found by a stepwise search: starting from four simple models, the best one is varied — each order up or down by one, alone and in pairs, with and without a constant — for as long as the information criterion improves. Models with roots too close to the unit circle are discarded.

As a Model, the orders are chosen again at every fit, so a backtest judges the whole procedure, not one lucky specification.

The zero value has the usual limits; see DefaultAutoArima.

func DefaultAutoArima added in v0.2.0

func DefaultAutoArima() AutoArima

DefaultAutoArima returns the defaults spelled out.

func (AutoArima) Description added in v0.2.0

func (AutoArima) Description() string

Description is a one-line description of the model.

func (AutoArima) Fit added in v0.2.0

func (a AutoArima) Fit(y Series) (Fitted, error)

Fit chooses the orders and estimates the model; see AutoArima.Select.

func (AutoArima) Name added in v0.2.0

func (AutoArima) Name() string

Name is the identifier of the model.

func (AutoArima) Select added in v0.2.0

func (a AutoArima) Select(y Series) (*ArimaFit, error)

Select chooses the orders and returns the estimated model. It returns ErrConfig for fixed differences that are negative.

type AutoEts added in v0.2.0

type AutoEts struct {
	// Criterion ranks the models (default ByAICc).
	Criterion Criterion
}

AutoEts is the ETS model with the best information criterion among those that suit the series.

Every combination of error, trend (none, additive, damped) and season (none, additive, multiplicative) is fitted, leaving out the ones with multiplicative parts when the series has values that are not positive, additive errors with a multiplicative season, whose forecast variance is unbounded, and the seasonal ones when the period is over 24, which would take one state per position of the cycle.

As a Model, the choice is made again at every fit, so a backtest judges the whole procedure.

Example

The member of the exponential smoothing family that suits the series best.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	fit, err := foresight.AutoEts{}.Select(foresight.Monthly(sales(), 0))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("ETS(%s)\n", fit.Model().Code())
}
Output:
ETS(MAM)

func (AutoEts) Description added in v0.2.0

func (AutoEts) Description() string

Description is a one-line description of the model.

func (AutoEts) Fit added in v0.2.0

func (a AutoEts) Fit(y Series) (Fitted, error)

Fit chooses the model and estimates it; see AutoEts.Select.

func (AutoEts) Name added in v0.2.0

func (AutoEts) Name() string

Name is the identifier of the model.

func (AutoEts) Select added in v0.2.0

func (a AutoEts) Select(y Series) (*EtsFit, error)

Select chooses the model and returns it estimated.

type Backtest

type Backtest struct {
	// Origins is how many of the last periods are forecast origins
	// (default 36).
	Origins int
	// Horizon is the longest horizon forecast and evaluated (default 12).
	Horizon int
	// MinTrain is the number of training observations at the first origin
	// (default 48). Shorter series get fewer origins.
	MinTrain int
	// Window trains on the last Window observations only, at every origin
	// and for the final forecast; zero uses everything before the origin.
	Window int
	// Combine also evaluates the simple average of the best Combine models
	// (default 2; 1 disables it).
	Combine int
	// Levels is the coverage of the intervals, such as 0.8 for the 10%–90%
	// quantiles, each one above 0 and below 1 (default 0.80 and 0.95).
	Levels []float64
	// Metric ranks the candidates (default RankByMAPE).
	Metric Metric
	// Sequential fits the origins one at a time, on the calling goroutine,
	// instead of on several cores (see [SetMaxThreads]); the ensembles among
	// the candidates then start no goroutines either. The result is the same
	// either way.
	Sequential bool
}

Backtest is the configuration of a rolling-origin evaluation.

  1. Rolling origin: for each of the last Origins periods, every candidate is fitted ONLY on the data before the origin and forecasts 1 to Horizon periods ahead; errors are measured against what happened. Horizon h has Origins − h + 1 pairs.
  2. Selection: the candidate with the lowest error averaged over the horizons, the simple average of the best few models included.
  3. Empirical intervals: no normality assumed. For each horizon, the quantiles of the relative error r = actual/forecast − 1 seen in the backtest; the interval is forecast × (1 + q).
  4. Cumulative intervals: the same for the ratio of sums over the first k periods of each origin, because adding up the limits of k intervals overstates the uncertainty of a total.

The zero value of each field stands for its default; DefaultBacktest returns them spelled out.

func DefaultBacktest

func DefaultBacktest() Backtest

DefaultBacktest returns the defaults, which suit monthly data: 36 origins, 12 periods ahead, at least 48 observations to train, the average of the two best models, intervals of 80% and 95%.

func (Backtest) Run

func (b Backtest) Run(y Series, candidates []Candidate) (*Report, error)

Run evaluates the candidates on y, chooses one and forecasts Horizon periods with every candidate that went through the whole backtest.

A candidate takes part only if it gives Horizon finite forecasts at every origin and from the whole series; the others (those without a model, those that fail, those that panic) are left out of the report.

It returns ErrFewOrigins when the series is too short for at least one pair at the longest horizon, ErrLevels when a level is not above 0 and below 1, and ErrNoCandidate when no candidate is left. There is no other error.

type Band

type Band struct {
	Level, Lower, Upper float64
}

Band holds the quantiles of a relative error r (actual/forecast − 1) for one coverage level: the interval is forecast × (1 + Lower) to forecast × (1 + Upper).

type BoxCox added in v0.2.0

type BoxCox struct {
	// Lambda is λ; zero is the logarithm.
	Lambda float64
}

BoxCox is a transformation of the Box-Cox family: the logarithm for λ = 0, (y^λ − 1)/λ otherwise. It is defined for positive values.

func Guerrero added in v0.2.0

func Guerrero(y Series) (BoxCox, bool)

Guerrero returns the transformation with the λ in [−1, 2] that makes the variability most even across the cycles of the series (Guerrero, 1993): it minimises the coefficient of variation of sd / mean^(1 − λ) over blocks of one period (two observations when there is no seasonality). It reports false without at least two blocks of positive values.

func (BoxCox) Apply added in v0.2.0

func (b BoxCox) Apply(y float64) float64

Apply transforms a value.

func (BoxCox) Invert added in v0.2.0

func (b BoxCox) Invert(z float64) float64

Invert brings a value back to the original scale. This is the median of the forecast distribution, not its mean.

type Candidate

type Candidate struct {
	// Name identifies the candidate in the report.
	Name string
	// Description is a line about the candidate, for display.
	Description string
	// Model is what is fitted. A candidate without one takes no part.
	Model Model
}

Candidate is a model taking part in a backtest, under a name of the caller's choice.

Example

A model of your own joins the backtest by implementing Model.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	candidates := []foresight.Candidate{
		foresight.NewCandidate(foresight.SeasonalNaive{}).Named("same_month", "Same month of last year"),
		foresight.NewCandidate(foresight.LogLinear{Window: 60}),
	}
	report, err := foresight.Backtest{Combine: 1}.Run(foresight.Monthly(sales(), 0), candidates)
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, c := range report.Candidates {
		fmt.Printf("%s: MAPE %.1f%%\n", c.Name, c.Score)
	}
}
Output:
same_month: MAPE 6.6%
log_linear: MAPE 3.3%

func Defaults

func Defaults() []Candidate

Defaults returns a reasonable set of candidates for a backtest: the benchmarks and every model that needs no external data and fits in a moment.

func NewCandidate

func NewCandidate(m Model) Candidate

NewCandidate returns a candidate with the model's own name and description. A nil model gives the zero Candidate, which takes no part in a backtest.

func Thorough added in v0.3.0

func Thorough() []Candidate

Thorough returns Defaults plus two ensembles of them, exponential smoothing chosen automatically, alone and after an STL decomposition, and ARIMA with automatic orders, on the original and on the log scale. The choices are made again at every origin of the backtest, which takes seconds rather than milliseconds.

func (Candidate) Named

func (c Candidate) Named(name, description string) Candidate

Named returns the candidate under another name and description.

type CandidateReport

type CandidateReport struct {
	// Name and Description are those of the candidate; an average is named
	// after its components.
	Name        string
	Description string
	// Components are the names of the models involved: one, or several for
	// an average.
	Components []string
	// Horizons has the measures by horizon; index 0 is horizon 1.
	Horizons []HorizonStats
	// Score is the ranking metric averaged over the horizons; +Inf when it
	// could not be computed.
	Score float64
	// Params are the parameters fitted on the whole series (none for an
	// average).
	Params []Param
	// Trajectories are the backtest forecasts, [origin][h − 1].
	Trajectories [][]float64
	// Forecast is the forecast from the whole series, with the intervals of
	// the backtest.
	Forecast []Point
}

CandidateReport is the backtest and the forecast of one candidate (a model or an average of models).

func (CandidateReport) Cumulative

func (c CandidateReport) Cumulative(k int) (Point, bool)

Cumulative returns the forecast of the SUM of the first k periods, with intervals from the backtest of sums. It reports false when k is under 1 or beyond the horizon.

type Changepoint added in v0.2.0

type Changepoint struct {
	// Position is relative to the first observation.
	Position int
	// Change is the change in slope, in units of the series per period.
	Change float64
}

Changepoint is a point where the trend did bend.

type Choice added in v0.3.0

type Choice int

Choice is something a model decides by itself unless told.

const (
	// Choose lets the model decide.
	Choose Choice = iota
	// Yes fixes the answer: it is so.
	Yes
	// No fixes the answer: it is not so.
	No
)

type Constant added in v0.2.0

type Constant int

Constant says whether an ARIMA model estimates a constant: the mean when the series is not differenced, the drift when it is differenced once. With two or more differences there is never a constant.

const (
	// ConstantByDefault estimates the mean of a series that is not
	// differenced and nothing otherwise.
	ConstantByDefault Constant = iota
	// WithConstant estimates the mean or the drift.
	WithConstant
	// WithoutConstant estimates neither.
	WithoutConstant
)

type Criterion added in v0.2.0

type Criterion int

Criterion is the information criterion that ranks models.

const (
	// ByAICc ranks by the AIC corrected for small samples (the default).
	ByAICc Criterion = iota
	// ByAIC ranks by the AIC.
	ByAIC
	// ByBIC ranks by the BIC.
	ByBIC
)

type Croston added in v0.3.0

type Croston struct {
	// Variant is the method (default CrostonMethod).
	Variant Intermittent
	// Alpha is the smoothing of the demand sizes (and of the intervals),
	// above 0 and up to 1 (default 0.1).
	Alpha float64
	// Beta is the smoothing of the probability of demand, for TSB (default:
	// the same as Alpha). The other variants do not use it.
	Beta float64
	// Optimised chooses the smoothing that minimises the squared error of
	// the rate against what was demanded, instead of a fixed value.
	Optimised bool
}

Croston forecasts the demand per period of intermittent series, where most periods have no demand at all.

The values must not be negative. The forecast is the same for every horizon: the rate at which demand is expected to arrive.

Example

Demand that comes now and then: the rate per period.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

func main() {
	y := []float64{0, 0, 3, 0, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 2, 0, 0, 0}
	fit, err := foresight.Croston{Variant: foresight.SBA}.Fit(foresight.NonSeasonal(y))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%.2f per period\n", fit.Forecast(1)[0])
}
Output:
0.88 per period

func (Croston) Description added in v0.3.0

func (c Croston) Description() string

Description is a one-line description of the model.

func (Croston) Fit added in v0.3.0

func (c Croston) Fit(y Series) (Fitted, error)

Fit estimates the model. It returns ErrConfig for a variant that is not one of the named ones.

func (Croston) Name added in v0.3.0

func (c Croston) Name() string

Name is the identifier of the model, after its variant; "croston_invalid" for a variant that is not one of the named ones.

type Decomposed added in v0.3.0

type Decomposed struct {
	// Model is the model of the seasonally adjusted series.
	Model Model
	// Periods are the seasonal periods to take out, instead of the period of
	// the series.
	Periods []int
	// Robust down-weights outliers in the decomposition.
	Robust bool
}

Decomposed runs a model on the seasonally adjusted series and adds the seasonal patterns of the last cycle to its forecasts.

The decomposition is Mstl, so the series may have several seasonal periods; by default the period is the one of the series. The model inside sees a series without seasonality, at the same position in the original data, so what goes by position (regressors, events, a deflator) stays aligned. The series has to be longer than two cycles of a period for it to be taken out. For patterns that grow with the level, wrap the whole in Log.

func (Decomposed) Description added in v0.3.0

func (d Decomposed) Description() string

Description is a one-line description of the model.

func (Decomposed) Fit added in v0.3.0

func (d Decomposed) Fit(y Series) (Fitted, error)

Fit decomposes the series and fits the model inside on what is left. It returns ErrConfig without a model inside.

func (Decomposed) Name added in v0.3.0

func (d Decomposed) Name() string

Name is the identifier of the model: "stl_" and the name of the model inside ("stl_invalid" without one).

type Decomposition added in v0.3.0

type Decomposition struct {
	// Periods are the seasonal periods taken out, in increasing order.
	Periods []int
	// Trend is the smooth part of the series.
	Trend []float64
	// Seasonal has one seasonal component per period, in the order of
	// Periods.
	Seasonal [][]float64
	// Remainder is what trend and seasonality leave unexplained.
	Remainder []float64
}

Decomposition is a series split into trend, one seasonal pattern per period and remainder: the three add up to the series.

func (Decomposition) SeasonalStrength added in v0.3.0

func (d Decomposition) SeasonalStrength(i int) (float64, bool)

SeasonalStrength returns the strength in [0, 1] of the seasonal component of index i. It reports false when there is no such component.

func (Decomposition) SeasonallyAdjusted added in v0.3.0

func (d Decomposition) SeasonallyAdjusted() []float64

SeasonallyAdjusted returns the series without its seasonal patterns.

func (Decomposition) TrendStrength added in v0.3.0

func (d Decomposition) TrendStrength() float64

TrendStrength returns the strength of the trend in [0, 1]: 1 − Var(remainder) / Var(trend + remainder) (Wang, Smith & Hyndman, 2006).

type Drift

type Drift struct{}

Drift is the random walk with drift: the last observation plus the average change per period over the history.

func (Drift) Description

func (Drift) Description() string

Description is a one-line description of the model.

func (Drift) Fit

func (Drift) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs two observations.

func (Drift) Name

func (Drift) Name() string

Name is the identifier of the model.

type Ensemble added in v0.3.0

type Ensemble struct {
	// Members are the models combined; each needs a model.
	Members []Candidate
	// Weighting says how they are combined (default InverseError).
	Weighting Weighting
	// Origins is how many of the last periods are forecast to learn the
	// weights (default 12).
	Origins int
	// Horizon is how far ahead each of those forecasts goes (default: one
	// seasonal cycle, at most 12 periods).
	Horizon int
	// Top keeps only the members with the smallest error; zero keeps all.
	Top int
}

Ensemble is a model made of other models.

The weights are learnt from the series itself: the last Origins periods are forecast by every member from the data before them, as in a backtest, and the errors decide how much each member counts. Then the members are fitted on the whole series and their forecasts combined. Members that cannot be fitted are left out.

Being a model, an ensemble can be a candidate in a Backtest, next to its own members: its weights are then learnt again at every origin, from what was known at that point.

The forecasts that teach the weights are made on several cores (see SetMaxThreads), except inside a backtest, where the ensemble keeps to the goroutine that fits it.

Example

Several models combined, the better ones counting more: here the three that would have forecast the last year best.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	model := foresight.Ensemble{Members: foresight.Defaults(), Top: 3}
	fit, err := model.Fit(foresight.Monthly(sales(), 0))
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, p := range fit.Params() {
		fmt.Println(p.Name)
	}
}
Output:
weight_log_linear
weight_log_prophet
weight_holt_winters

func (Ensemble) Description added in v0.3.0

func (e Ensemble) Description() string

Description is a one-line description of the ensemble and its members.

func (Ensemble) Fit added in v0.3.0

func (e Ensemble) Fit(y Series) (Fitted, error)

Fit learns the weights and fits the members on the whole series. It returns ErrConfig for a weighting that is not one of the named ones or a member without a model, and ErrNoCandidate when no member can be fitted.

func (Ensemble) Name added in v0.3.0

func (e Ensemble) Name() string

Name is the identifier of the model, after its weighting; "ensemble_invalid" for a weighting that is not one of the named ones.

type ErrorKind added in v0.2.0

type ErrorKind int

ErrorKind says how the error enters the observation of an ETS model.

const (
	// AdditiveError: y = μ + ε.
	AdditiveError ErrorKind = iota
	// MultiplicativeError: y = μ (1 + ε); needs positive values.
	MultiplicativeError
)

type Ets added in v0.2.0

type Ets struct {
	// Error, Trend and Season are the three components; the zero value of
	// each is the plain one (additive error, no trend, no season).
	Error  ErrorKind
	Trend  Trend
	Season Season
}

Ets is one member of the exponential smoothing family in state space form (Hyndman, Koehler, Snyder & Grose, 2002): an error, a trend and a seasonal component.

Simple exponential smoothing is Ets{}, Holt's linear method Ets{Trend: AdditiveTrend}, the multiplicative Holt-Winters method Ets{MultiplicativeError, AdditiveTrend, MultiplicativeSeason}. The smoothing parameters and the initial states are estimated together by maximum likelihood.

func EtsCandidates added in v0.2.0

func EtsCandidates(period int, positive bool) []Ets

EtsCandidates returns the models considered for a series of the given period, with or without values that are not positive. Seasonal models are left out for a period under 2 or over 24.

func EtsFromCode added in v0.2.0

func EtsFromCode(code string) (Ets, bool)

EtsFromCode returns the model of the usual three-letter code, error–trend–season, with Ad for a damped trend: "ANN", "AAdN", "MAM"… It reports false for anything else.

func (Ets) Code added in v0.2.0

func (e Ets) Code() string

Code returns the three-letter code of the model; "invalid" when a component is not one of the named ones.

func (Ets) Description added in v0.2.0

func (e Ets) Description() string

Description is a one-line description of the model.

func (Ets) Estimate added in v0.2.0

func (e Ets) Estimate(y Series) (*EtsFit, error)

Estimate fits the model and returns everything that was estimated. It returns ErrConfig when a component is not one of the named ones.

func (Ets) Fit added in v0.2.0

func (e Ets) Fit(y Series) (Fitted, error)

Fit estimates the model; see Ets.Estimate.

func (Ets) Name added in v0.2.0

func (e Ets) Name() string

Name is the identifier of the model, after its code; "ets_invalid" when a component is not one of the named ones.

type EtsFit added in v0.2.0

type EtsFit struct {

	// Alpha is the smoothing of the level.
	Alpha float64
	// Beta is the smoothing of the trend, Gamma of the seasonal pattern and
	// Phi the damping of the trend; they are NaN when the model has no such
	// part.
	Beta, Gamma, Phi float64

	// Sigma2 is the variance of the errors (relative errors for
	// multiplicative models).
	Sigma2 float64
	// LogLikelihood is the log-likelihood up to the usual constant, as
	// reported by ets in R; AIC, AICc and BIC are the information criteria
	// that come from it.
	LogLikelihood float64
	AIC           float64
	AICc          float64
	BIC           float64
	// Residuals are the errors of the one-step forecasts (relative for
	// multiplicative models).
	Residuals []float64
	// Fitted are the one-step forecasts of the history.
	Fitted []float64
	// contains filtered or unexported fields
}

EtsFit is an estimated ETS model.

func (*EtsFit) Forecast added in v0.2.0

func (f *EtsFit) Forecast(h int) []float64

Forecast returns the forecasts for the h periods after the last observation; nothing for an h of zero or less, or for a fit that did not come from Ets.Estimate.

func (*EtsFit) InitialLevelAndTrend added in v0.2.0

func (f *EtsFit) InitialLevelAndTrend() (level, trend float64)

InitialLevelAndTrend returns the level and the trend before the first observation.

func (*EtsFit) InitialSeasonal added in v0.2.0

func (f *EtsFit) InitialSeasonal() []float64

InitialSeasonal returns the seasonal pattern before the first observation, by position in the cycle (position 0 is the first observation).

func (*EtsFit) LevelAndTrend added in v0.2.0

func (f *EtsFit) LevelAndTrend() (level, trend float64)

LevelAndTrend returns the level and the trend after the last observation.

func (*EtsFit) Model added in v0.2.0

func (f *EtsFit) Model() Ets

Model returns the model that was fitted.

func (*EtsFit) Params added in v0.2.0

func (f *EtsFit) Params() []Param

Params returns the smoothing parameters, the initial states, the components and the fit.

type Event added in v0.2.0

type Event struct {
	// Name identifies the effect of the event among the parameters.
	Name string
	// Positions are where a recurring event happens, in the ORIGINAL data
	// (see [Series.Index]), past and future: one effect is estimated for all
	// its occurrences. Positions beyond the history are how the forecast
	// knows the event is coming.
	Positions []int
	// Step makes the event a lasting change of level, from StepFrom on, such
	// as a change in the law.
	Step     bool
	StepFrom int
}

Event is something dated that moves the series.

type Fitted

type Fitted interface {
	// Forecast returns point forecasts for the h periods after the last
	// observation, and nothing for an h of zero or less. They are not finite
	// where the model cannot say: past the rows of its regressors, for
	// instance. [Forecast] checks that.
	Forecast(h int) []float64
	// Params returns the estimated parameters.
	Params() []Param
}

Fitted is a model estimated on a series. It is plain data: it can be kept and asked for forecasts from several goroutines at once.

type HoltWinters

type HoltWinters struct{}

HoltWinters is exponential smoothing with level, damped additive trend (φ) and multiplicative seasonal indices.

α, β, γ and φ come from a grid search (3,040 combinations) minimising the sum of squared relative one-step-ahead errors on the training data, the first cycle left out as warm-up. It needs a seasonal period of at least 2, positive values and three full cycles.

func (HoltWinters) Description

func (HoltWinters) Description() string

Description is a one-line description of the model.

func (HoltWinters) Fit

func (HoltWinters) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs a seasonal series of three full cycles of positive values.

func (HoltWinters) Name

func (HoltWinters) Name() string

Name is the identifier of the model.

type HorizonStats

type HorizonStats struct {
	// N is the number of forecast/actual pairs evaluated.
	N int
	// MAPE is the mean absolute percentage error, in percent.
	MAPE float64
	// Bias is the mean of (forecast − actual)/actual, in percent; positive
	// when the forecasts ran high.
	Bias float64
	// MAE is the mean absolute error.
	MAE float64
	// RMSE is the root mean squared error.
	RMSE float64
	// MASE is the mean absolute error scaled by the in-sample seasonal naive
	// error of each training set.
	MASE float64
	// Bands are the quantiles of the relative error at this horizon, one per
	// level.
	Bands []Band
	// Cumulative are the quantiles of the relative error of the SUM of the
	// first h periods.
	Cumulative []Band
}

HorizonStats is what the backtest measured at one horizon. Measures that could not be computed are NaN.

type Intermittent added in v0.3.0

type Intermittent int

Intermittent says how the demand rate of an intermittent series is estimated.

const (
	// CrostonMethod (Croston, 1972): the size of the demands and the
	// interval between them are smoothed separately; the rate is
	// size ÷ interval.
	CrostonMethod Intermittent = iota
	// SBA (Syntetos & Boylan, 2005): Croston's rate times 1 − α/2, which
	// removes its upward bias.
	SBA
	// TSB (Teunter, Syntetos & Babai, 2011): the probability of a demand is
	// smoothed at every period, so the rate falls while nothing is sold.
	TSB
)

type Interval

type Interval struct {
	Level, Lower, Upper float64
}

Interval is an interval around a forecast, with its coverage: Lower is never above Upper.

type LogLinear

type LogLinear struct {
	// Window is the number of most recent observations used in the fit.
	// Zero means six cycles, at least 24: enough to catch the recent trend
	// without dragging old breaks along.
	Window int
	// Deflator is a price index aligned with the ORIGINAL data: Deflator[i]
	// deflates the observation whose position is i (see [Series.Index]).
	// Only positions inside the training data are read, so handing the full
	// index to a backtest does not leak the future.
	Deflator []float64
}

LogLinear is a log-linear regression: log(y/I) = a + b·t + seasonal dummies, by least squares over the last Window observations, where I is a price index (1 without a deflator).

The back-transformation is corrected for bias with Duan's smearing factor (the mean of exp(residual)). With a deflator, real forecasts are re-inflated by the index growth over the last cycle, held constant over the horizon. It needs positive values and three full cycles.

func (LogLinear) Description

func (l LogLinear) Description() string

Description is a one-line description of the model.

func (LogLinear) Fit

func (l LogLinear) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs three full cycles of positive values and, with a deflator, an index that reaches the end of the series.

func (LogLinear) Name

func (l LogLinear) Name() string

Name is the identifier of the model.

type Mean

type Mean struct{}

Mean forecasts the mean of the history at every horizon.

func (Mean) Description

func (Mean) Description() string

Description is a one-line description of the model.

func (Mean) Fit

func (Mean) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs one observation.

func (Mean) Name

func (Mean) Name() string

Name is the identifier of the model.

type Metric

type Metric int

Metric is the error measure averaged over the horizons to rank the candidates.

const (
	// RankByMAPE ranks by mean absolute percentage error (the default).
	RankByMAPE Metric = iota
	// RankByMAE ranks by mean absolute error.
	RankByMAE
	// RankByRMSE ranks by root mean squared error.
	RankByRMSE
	// RankByMASE ranks by mean absolute scaled error.
	RankByMASE
)

type Model

type Model interface {
	// Name is a short identifier, such as "holt_winters".
	Name() string
	// Description is a one-line description of the method.
	Description() string
	// Fit estimates the model. It returns an error when the series is too
	// short or otherwise unsuitable.
	//
	// A model that fits other models hands them the series it was given, a
	// slice of it or [Series.WithValues], rather than a new Series: that is
	// how an ensemble inside learns that it is being fitted in a worker of a
	// backtest and must not start goroutines of its own.
	Fit(y Series) (Fitted, error)
}

Model is a forecasting method, before seeing any data.

Fitting is separate from forecasting so that a fitted model can be inspected and asked for any horizon without being estimated again. Models are plain configuration and safe to share between goroutines.

type Mstl added in v0.3.0

type Mstl struct {
	// Periods are the seasonal periods; those under 2 are left out.
	Periods []int
	// Windows are the seasonal windows, one per period in increasing order
	// of period; the last one is repeated if there are more periods than
	// windows. The default is 11, 15, 19… for the first, second, third…
	// period.
	Windows []int
	// Iterations are the rounds over the periods (default 2).
	Iterations int
	// Robust down-weights outliers in every fit.
	Robust bool
}

Mstl is STL applied in turn to each of several seasonal periods (Bandara, Hyndman & Bergmeir, 2021).

The periods are taken from the shortest to the longest; each pattern is estimated on the series without the others, twice over. Periods that do not fit more than twice in the series are left out. The trend comes from the last fit.

func (Mstl) Decompose added in v0.3.0

func (m Mstl) Decompose(y []float64) (Decomposition, error)

Decompose decomposes the values. It returns an error when the series is not longer than two cycles of any of the periods, or the values are not finite.

type Naive

type Naive struct{}

Naive forecasts the last observation at every horizon (a random walk).

func (Naive) Description

func (Naive) Description() string

Description is a one-line description of the model.

func (Naive) Fit

func (Naive) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs one observation.

func (Naive) Name

func (Naive) Name() string

Name is the identifier of the model.

type Outlier added in v0.3.0

type Outlier struct {
	// Index is the position in the series.
	Index int
	// Value is what was observed.
	Value float64
	// Replacement is what the neighbours and the season suggest instead.
	Replacement float64
}

Outlier is an observation that does not fit with the others.

func Outliers added in v0.3.0

func Outliers(values []float64, period int) ([]Outlier, bool)

Outliers finds the observations whose distance from trend and seasonality is more than three interquartile ranges beyond the quartiles of those distances.

Trend and seasonality come from a robust STL decomposition; the seasonal pattern is only taken out when it is strong (strength of at least 0.6, measured with interquartile ranges), as a weak one would be mostly noise. Series without seasonality get a robust local linear trend. Gaps are filled before looking. It reports false when the series has fewer than 8 known values.

Example

A value that does not belong, found and replaced.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	y := sales()
	y[40] *= 3
	found, _ := foresight.Outliers(y, 12)
	for _, o := range found {
		fmt.Printf("position %d: %.0f, rather %.0f\n", o.Index, o.Value, o.Replacement)
	}
}
Output:
position 40: 364, rather 121

type Param

type Param struct {
	Name  string
	Value float64
}

Param is a named number estimated by a model, for display and audit trails.

type Point

type Point struct {
	// Horizon is the number of periods ahead (for a cumulative forecast, how
	// many were added up).
	Horizon int
	// Mean is the point forecast.
	Mean float64
	// Intervals has one interval per level of the backtest.
	Intervals []Interval
}

Point is a forecast with its intervals.

func (Point) Interval

func (p Point) Interval(level float64) (Interval, bool)

Interval returns the interval with the given coverage, if it was asked for.

type Prophet added in v0.2.0

type Prophet struct {
	// Changepoints is the number of candidate changepoints (default 25).
	// Use NoChangepoints for a straight line.
	Changepoints int
	// NoChangepoints fits a straight line.
	NoChangepoints bool
	// ChangepointRange is the share of the history, from the start, where
	// changepoints may fall (default 0.8).
	ChangepointRange float64
	// ChangepointPriorScale is the flexibility of the trend: larger values
	// let it bend more (default 0.05).
	ChangepointPriorScale float64
	// SeasonalityPriorScale is the flexibility of the seasonal pattern
	// (default 10).
	SeasonalityPriorScale float64
	// FourierOrder is the number of harmonics of the seasonal pattern
	// (default 10, or half the period when that is less, which describes any
	// pattern of that period). Use NoSeasonality for none. There is no
	// seasonal pattern before two full cycles of history either.
	FourierOrder int
	// NoSeasonality leaves the seasonal pattern out.
	NoSeasonality bool
	// EventPriorScale is the flexibility of the effects of events
	// (default 10).
	EventPriorScale float64
	// Events are recurring events and lasting changes of level.
	Events []Event
}

Prophet is the Prophet model (Taylor & Letham, 2018): a piecewise linear trend that may bend at changepoints, a Fourier seasonal pattern and dated events, fitted by maximum a posteriori.

y(t) = g(t) + s(t) + events(t) + noise, where g is a line whose slope may change at each of a set of candidate changepoints spread over the first part of the history. The changes have a Laplace prior, so most of them come out as exactly zero and the trend bends only where the data insists; the seasonal and event coefficients have normal priors.

What is and is not here, compared with the original: observations are equally spaced and the seasonal period is the one of the series; growth is linear and the components are additive (for multiplicative behaviour, fit on the log scale with Log); events are given by position instead of by calendar. The estimate is the exact optimum of the same posterior, found without Stan.

The zero value has the defaults of Prophet; see DefaultProphet.

Example

A trend that bends, with an event that recurs and is known ahead.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	y := sales()
	for _, t := range []int{5, 29, 53, 77} {
		y[t] += 30 // a campaign every other June
	}
	model := foresight.Prophet{Events: []foresight.Event{
		{Name: "campaign", Positions: []int{5, 29, 53, 77, 101}},
	}}
	fit, err := model.Estimate(foresight.Monthly(y, 0))
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, e := range fit.Effects() {
		fmt.Printf("%s: %+.0f\n", e.Name, e.Value)
	}
}
Output:
campaign: +29

func DefaultProphet added in v0.2.0

func DefaultProphet() Prophet

DefaultProphet returns the defaults of Prophet spelled out: 25 candidate changepoints over the first 80% of the history with prior scale 0.05, seasonal and event prior scales of 10.

func (Prophet) Description added in v0.2.0

func (Prophet) Description() string

Description is a one-line description of the model.

func (Prophet) Estimate added in v0.2.0

func (p Prophet) Estimate(y Series) (*ProphetFit, error)

Estimate fits the model and returns everything that was estimated.

func (Prophet) Fit added in v0.2.0

func (p Prophet) Fit(y Series) (Fitted, error)

Fit estimates the model; see Prophet.Estimate.

func (Prophet) Name added in v0.2.0

func (Prophet) Name() string

Name is the identifier of the model.

type ProphetFit added in v0.2.0

type ProphetFit struct {
	// contains filtered or unexported fields
}

ProphetFit is an estimated Prophet model.

func (*ProphetFit) Changepoints added in v0.2.0

func (f *ProphetFit) Changepoints() []Changepoint

Changepoints returns the changepoints where the trend did bend.

func (*ProphetFit) Effects added in v0.2.0

func (f *ProphetFit) Effects() []Param

Effects returns the estimated effect of each event, in units of the series.

func (*ProphetFit) Events added in v0.2.0

func (f *ProphetFit) Events(i int) float64

Events returns the effect of the events at the relative position i.

func (*ProphetFit) FittedValues added in v0.2.0

func (f *ProphetFit) FittedValues() []float64

FittedValues returns the values fitted to the history.

func (*ProphetFit) Forecast added in v0.2.0

func (f *ProphetFit) Forecast(h int) []float64

Forecast returns the forecasts for the h periods after the last observation; nothing for an h of zero or less, or for a fit that did not come from Prophet.Estimate.

func (*ProphetFit) Params added in v0.2.0

func (f *ProphetFit) Params() []Param

Params returns the slopes of the trend, the number of changepoints, the noise and the effects of the events; nothing for a fit that did not come from Prophet.Estimate.

func (*ProphetFit) Seasonal added in v0.2.0

func (f *ProphetFit) Seasonal(i int) float64

Seasonal returns the seasonal effect at the relative position i.

func (*ProphetFit) Sigma added in v0.2.0

func (f *ProphetFit) Sigma() float64

Sigma returns the standard deviation of the noise, in units of the series.

func (*ProphetFit) Trend added in v0.2.0

func (f *ProphetFit) Trend(i int) float64

Trend returns the trend at the relative position i (0 is the first observation; the length of the history and beyond are the future).

type Regressors added in v0.2.0

type Regressors struct {
	// contains filtered or unexported fields
}

Regressors are named columns of values aligned with the ORIGINAL data: row i belongs to the observation whose position is i (see Series.Index). The rows go on past the end of the history, because a forecast needs the values of the regressors over the horizon.

The zero value has no columns. The methods return a new value and leave the receiver as it was.

func Fourier added in v0.2.0

func Fourier(period float64, order, rows int) Regressors

Fourier returns sines and cosines of the first order harmonics of a cycle of the given period, which need not be a whole number, for rows positions: a smooth seasonal pattern with few coefficients. The sine that is zero everywhere (the harmonic at half a whole period) is left out, and so are the harmonics beyond half the period, which would repeat the earlier ones. A period that is not a positive finite number, or a negative number of rows, gives no columns.

func SeasonalDummies added in v0.2.0

func SeasonalDummies(period, rows int) Regressors

SeasonalDummies returns one indicator for each position of the cycle but the first. A period under 2, or a negative number of rows, gives no columns.

func (Regressors) And added in v0.2.0

func (r Regressors) And(other Regressors) Regressors

And returns the regressors with the columns of another set added.

func (Regressors) Columns added in v0.2.0

func (r Regressors) Columns() [][]float64

Columns returns the columns. They are shared, not copied.

func (Regressors) Covers added in v0.2.0

func (r Regressors) Covers(end int) bool

Covers reports whether there are rows for the positions 0 to end−1 and all of them are finite. An end of zero or less asks for nothing, which is covered.

func (Regressors) Names added in v0.2.0

func (r Regressors) Names() []string

Names returns the names of the columns.

func (Regressors) Rows added in v0.2.0

func (r Regressors) Rows() int

Rows returns the number of rows that every column has.

func (Regressors) Width added in v0.2.0

func (r Regressors) Width() int

Width returns the number of columns.

func (Regressors) With added in v0.2.0

func (r Regressors) With(name string, values []float64) Regressors

With returns the regressors with one more column.

type Report

type Report struct {
	// Candidates are the models in the order given, then the average of the
	// best ones.
	Candidates []CandidateReport
	// Chosen is the index of the chosen candidate.
	Chosen int
	// Origins is the number of origins actually used.
	Origins int
	// FirstOrigin is the position in the series of the first period
	// forecast in the backtest.
	FirstOrigin int
	// Horizon is the longest horizon forecast and evaluated.
	Horizon int
	// Metric is the measure that ranked the candidates.
	Metric Metric
}

Report is the result of a backtest.

func (*Report) Best

func (r *Report) Best() *CandidateReport

Best returns the chosen candidate. For a report that did not come from Backtest.Run (no candidates, or Chosen out of range) it returns an empty CandidateReport.

func (*Report) Candidate

func (r *Report) Candidate(name string) (*CandidateReport, bool)

Candidate looks a candidate up by name.

type Season added in v0.2.0

type Season int

Season is the seasonal component of an ETS model.

const (
	// NoSeason: no seasonal pattern.
	NoSeason Season = iota
	// AdditiveSeason: a pattern added to the level.
	AdditiveSeason
	// MultiplicativeSeason: a pattern that multiplies the level; needs
	// positive values.
	MultiplicativeSeason
)

type SeasonalNaive

type SeasonalNaive struct {
	// Growth scales the last cycle by the growth between the last two.
	Growth bool
}

SeasonalNaive forecasts the same season of the last cycle, optionally scaled by recent growth.

With Growth, ŷ(T+k) = y(T+k−m) × g, where g is the sum of the last cycle over the sum of the one before; forecasts beyond one cycle compound g. Both sums have to be positive.

func (SeasonalNaive) Description

func (s SeasonalNaive) Description() string

Description is a one-line description of the model.

func (SeasonalNaive) Fit

func (s SeasonalNaive) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs one full cycle, two with Growth.

func (SeasonalNaive) Name

func (s SeasonalNaive) Name() string

Name is the identifier of the model.

type SeasonalPeriod added in v0.3.0

type SeasonalPeriod struct {
	Period    float64
	Harmonics int
}

SeasonalPeriod is a seasonal period of a TBATS model and the number of harmonics that describe its pattern.

type Series

type Series struct {
	// contains filtered or unexported fields
}

Series is a view over regularly spaced observations, oldest first.

Besides the values, a series knows its seasonal period (12 for monthly data with a yearly cycle, 4 for quarterly, 1 for none) and where it sits in the original data: slicing keeps the absolute position, so the season of each observation and the alignment with external data (a price index, a regressor) survive any Head, Tail or Slice.

The values are not copied: a Series shares them with the slice it was made from. The zero Series{} is an empty series without seasonality.

func Monthly

func Monthly(values []float64, firstMonth int) Series

Monthly returns a series of monthly data with a yearly cycle; firstMonth is the calendar month of the first observation, 0 for January.

func NewSeries

func NewSeries(values []float64, period int) Series

NewSeries returns a series with the given seasonal period; a period under 1 is read as 1 (no seasonality). The first observation is taken to be at season 0; see Series.WithPhase.

func NonSeasonal

func NonSeasonal(values []float64) Series

NonSeasonal returns a series without seasonality.

func Quarterly

func Quarterly(values []float64, firstQuarter int) Series

Quarterly returns a series of quarterly data with a yearly cycle; firstQuarter is 0 for the first quarter.

func (Series) Head

func (s Series) Head(n int) Series

Head returns the first n observations (all of them if n is larger).

func (Series) Index

func (s Series) Index(i int) int

Index returns the position in the original data of observation i, which may be past the end: Len() is the first period to be forecast.

func (Series) IsFinite

func (s Series) IsFinite() bool

IsFinite reports whether every value is a finite number.

func (Series) IsPositive

func (s Series) IsPositive() bool

IsPositive reports whether every value is finite and greater than zero, which is what multiplicative and logarithmic models need.

func (Series) Len

func (s Series) Len() int

Len returns the number of observations.

func (Series) Period

func (s Series) Period() int

Period returns the seasonal period: 1 for a series without seasonality, the zero Series{} included.

func (Series) Season

func (s Series) Season(i int) int

Season returns the season (0 to Period()-1) of observation i, which, like in Index, may be past the end.

func (Series) Slice

func (s Series) Slice(from, to int) Series

Slice returns the observations from position from up to, but not including, position to, clamped to the series.

func (Series) Start

func (s Series) Start() int

Start returns the position, in the original data, of the first observation.

func (Series) Tail

func (s Series) Tail(n int) Series

Tail returns the last n observations (all of them if n is larger).

func (Series) Values

func (s Series) Values() []float64

Values returns the observations. The slice is shared, not copied.

func (Series) WithPhase

func (s Series) WithPhase(phase int) Series

WithPhase sets the season of the first observation of this view.

func (Series) WithValues

func (s Series) WithValues(values []float64) (Series, error)

WithValues returns the same series (period, season and position) over other values, such as a transformation of the original ones.

type Stl added in v0.3.0

type Stl struct {
	// Period is the seasonal period, at least 2.
	Period int
	// SeasonalWindow is the LOESS window over the cycles, an odd number,
	// usually 7 or more: the smaller, the faster the pattern may change. An
	// even number is taken as the next odd one, and the least is 3. Zero
	// keeps the same pattern in every cycle.
	SeasonalWindow int
	// TrendWindow and LowPassWindow are the LOESS windows of the trend and
	// of the low-pass filter; zero stands for the defaults.
	TrendWindow, LowPassWindow int
	// SeasonalLinear fits the seasonal pattern by local lines instead of
	// local constants; FlatTrend and FlatLowPass fit the trend and the
	// low-pass filter by local constants instead of local lines.
	SeasonalLinear, FlatTrend, FlatLowPass bool
	// Robust down-weights outliers: 15 robustness rounds of one pass each
	// instead of a single round of two passes.
	//
	// Compared with stl(robust = TRUE) in R, the result is the same to 12
	// digits for up to 11 rounds; from the 12th on the two drift apart in
	// the third digit, R's values no longer settling from one round to the
	// next.
	Robust bool
	// Inner and Outer are the passes of the inner loop and the robustness
	// rounds of the outer loop; zero stands for the defaults.
	Inner, Outer int
}

Stl is STL, the seasonal-trend decomposition by LOESS (Cleveland, Cleveland, McRae & Terpenning, 1990), for one seasonal period.

The defaults are those of stl in R: trend window 1.5·period / (1 − 1.5/seasonal window), rounded up to the next odd number, low-pass window the next odd number after the period, local constant fitting for the seasonal pattern and local linear for the rest, and LOESS evaluated at every tenth of each window and interpolated in between.

As in R, the series has to be longer than two full cycles.

Example

Trend, seasonal pattern and what is left.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

// Eight years of monthly data with growth, a yearly pattern and some noise.
func sales() []float64 {
	pattern := []float64{1.1, 0.8, 0.9, 1.0, 1.0, 0.9, 1.0, 1.0, 0.9, 1.0, 1.1, 1.3}
	out := make([]float64, 96)
	level := 100.0
	for t := range out {
		noise := float64((t*37)%11-5) * 1.5
		out[t] = level*pattern[t%12] + noise
		level += 0.5
	}
	return out
}

func main() {
	d, err := foresight.Stl{Period: 12}.Decompose(sales())
	if err != nil {
		fmt.Println(err)
		return
	}
	strength, _ := d.SeasonalStrength(0)
	fmt.Printf("trend %.0f to %.0f, seasonal strength %.2f\n", d.Trend[0], d.Trend[95], strength)
}
Output:
trend 99 to 149, seasonal strength 0.89

func (Stl) Decompose added in v0.3.0

func (s Stl) Decompose(y []float64) (Decomposition, error)

Decompose decomposes the values. It returns an error for a period under 2, a series that is not longer than two full cycles (as in R's stl) or values that are not finite.

type Tbats added in v0.3.0

type Tbats struct {
	// Periods are the seasonal periods, which need not be whole numbers.
	// With none, the period of the series is used.
	Periods []float64
	// Harmonics fixes the number of harmonics of each period, in increasing
	// order of period, instead of choosing them.
	Harmonics []int
	// BoxCox says whether the model runs on a Box-Cox scale (λ between 0 and
	// 1, estimated with the other parameters); Trend whether there is a
	// trend; Damped whether it is damped; ArmaErrors whether the errors may
	// follow an ARMA process.
	BoxCox, Trend, Damped, ArmaErrors Choice
	// FixOrders uses P and Q as the orders of the ARMA errors instead of
	// choosing them. Neither may be negative.
	FixOrders bool
	P, Q      int
}

Tbats is TBATS (De Livera, Hyndman & Snyder, 2011): exponential smoothing with seasonal patterns made of sines and cosines.

Because a pattern is a handful of harmonics rather than one state per position of the cycle, the period may be long (365 days) or not a whole number (52.18 weeks, 365.25 days), and several periods can be combined. What is left after level, trend and seasonality may follow an ARMA process, and the whole may run on a Box-Cox scale.

Whatever is not fixed is chosen by AIC: the number of harmonics of each period, trend and damping, the transformation and the ARMA errors. The initial states are found by least squares for each set of parameters, which leaves the search with the few smoothing parameters only.

It is the slowest model of the package: choosing the structure of a monthly series of ten years takes seconds.

func (Tbats) Description added in v0.3.0

func (Tbats) Description() string

Description is a one-line description of the model.

func (Tbats) Fit added in v0.3.0

func (t Tbats) Fit(y Series) (Fitted, error)

Fit chooses the structure and estimates the model; see Tbats.Select.

func (Tbats) Name added in v0.3.0

func (Tbats) Name() string

Name is the identifier of the model.

func (Tbats) Select added in v0.3.0

func (t Tbats) Select(y Series) (*TbatsFit, error)

Select chooses what was left open and returns the estimated model. It returns ErrConfig for a negative P or Q.

type TbatsFit added in v0.3.0

type TbatsFit struct {

	// Sigma2 is the variance of the errors on the scale of the fit.
	Sigma2 float64
	// contains filtered or unexported fields
}

TbatsFit is an estimated TBATS model.

func (*TbatsFit) AIC added in v0.3.0

func (f *TbatsFit) AIC() float64

AIC returns the information criterion of the model.

func (*TbatsFit) Arma added in v0.3.0

func (f *TbatsFit) Arma() (p, q int)

Arma returns the orders (p, q) of the ARMA errors.

func (*TbatsFit) Forecast added in v0.3.0

func (f *TbatsFit) Forecast(h int) []float64

Forecast returns the forecasts for the h periods after the last observation; nothing for an h of zero or less, or for a fit that did not come from Tbats.Select.

func (*TbatsFit) InitialStates added in v0.3.0

func (f *TbatsFit) InitialStates() []float64

InitialStates returns the states before the first observation.

func (*TbatsFit) Lambda added in v0.3.0

func (f *TbatsFit) Lambda() (float64, bool)

Lambda returns λ of the Box-Cox transformation, if one was used.

func (*TbatsFit) Likelihood added in v0.3.0

func (f *TbatsFit) Likelihood() float64

Likelihood returns n ln Σε² − 2(λ − 1) Σ ln y: the likelihood as TBATS reports it, the lower the better.

func (*TbatsFit) Params added in v0.3.0

func (f *TbatsFit) Params() []Param

Params returns the smoothing parameters, the structure chosen and the fit.

func (*TbatsFit) Residuals added in v0.3.0

func (f *TbatsFit) Residuals() []float64

Residuals returns the errors of the one-step forecasts, on the scale of the fit.

func (*TbatsFit) Seasonal added in v0.3.0

func (f *TbatsFit) Seasonal() []SeasonalPeriod

Seasonal returns the seasonal periods and the harmonics of each.

func (*TbatsFit) Smoothing added in v0.3.0

func (f *TbatsFit) Smoothing() (alpha, beta float64)

Smoothing returns the smoothing of the level and of the trend.

func (*TbatsFit) Trend added in v0.3.0

func (f *TbatsFit) Trend() (damping float64, ok bool)

Trend returns the damping of the trend (1 for none), if there is a trend.

type Theta

type Theta struct{}

Theta is the Theta method (Assimakopoulos & Nikolopoulos, 2000), in the form shown by Hyndman & Billah (2003) to be simple exponential smoothing with drift: the smoothed level plus half the slope of the linear trend.

Seasonal series are first tested for seasonality (autocorrelation at the seasonal lag, 90% level); when the test passes and the values are positive, the series is seasonally adjusted by classical multiplicative decomposition and the forecasts are re-seasonalised. The smoothing parameter and the initial level minimise the sum of squared one-step errors.

Example

One model on its own.

package main

import (
	"fmt"

	foresight "github.com/milkway/foresight-go"
)

func main() {
	y := []float64{12, 14, 13, 15, 17, 16, 18, 20}
	fit, err := foresight.Theta{}.Fit(foresight.NonSeasonal(y))
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, v := range fit.Forecast(3) {
		fmt.Printf("%.2f\n", v)
	}
}
Output:
20.52
21.04
21.55

func (Theta) Description

func (Theta) Description() string

Description is a one-line description of the model.

func (Theta) Fit

func (Theta) Fit(y Series) (Fitted, error)

Fit estimates the model; it needs three observations.

func (Theta) Name

func (Theta) Name() string

Name is the identifier of the model.

type Transformed added in v0.2.0

type Transformed struct {
	// Model is the model of the transformed values.
	Model Model
	// Transform is the transformation, unless Automatic.
	Transform BoxCox
	// Automatic chooses λ by [Guerrero] at each fit.
	Automatic bool
}

Transformed runs a model on Box-Cox transformed values and brings the forecasts back to the original scale. The series must be positive.

Use Log, WithBoxCox or WithGuerrero to make one.

func Log added in v0.2.0

func Log(m Model) Transformed

Log returns the model on the log scale.

func WithBoxCox added in v0.2.0

func WithBoxCox(m Model, lambda float64) Transformed

WithBoxCox returns the model on the Box-Cox scale with the given λ.

func WithGuerrero added in v0.2.0

func WithGuerrero(m Model) Transformed

WithGuerrero returns the model on the Box-Cox scale with λ chosen by Guerrero at each fit.

func (Transformed) Description added in v0.2.0

func (t Transformed) Description() string

Description is a one-line description of the model.

func (Transformed) Fit added in v0.2.0

func (t Transformed) Fit(y Series) (Fitted, error)

Fit transforms the series and fits the model inside. It returns ErrConfig without a model inside.

func (Transformed) Name added in v0.2.0

func (t Transformed) Name() string

Name is the identifier of the model: "log_" or "boxcox_" and the name of the model inside ("log_invalid" without one).

type Trend added in v0.2.0

type Trend int

Trend is the trend component of an ETS model.

const (
	// NoTrend: the level alone.
	NoTrend Trend = iota
	// AdditiveTrend: a slope added at every period.
	AdditiveTrend
	// DampedTrend is additive, flattening out over the horizon.
	DampedTrend
)

type Weighting added in v0.3.0

type Weighting int

Weighting says how the forecasts of the members of an ensemble are combined.

const (
	// InverseError weights in inverse proportion to the mean squared error
	// each member had when forecasting the end of the history (the default).
	InverseError Weighting = iota
	// EqualWeights is the plain average.
	EqualWeights
	// Median is the median, which a member gone astray cannot drag along.
	Median
	// Stacked uses the weights, none negative and adding up to one, that
	// would have given the combination with the smallest squared error over
	// the end of the history. Members that add nothing get exactly zero.
	Stacked
)

Jump to

Keyboard shortcuts

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