Forecasting Models
Overview
Time-series forecasting estimates future values from historical observations by modeling temporal dependence, trend, and seasonality. In applied analytics, forecasting models are central to capacity planning, demand management, budgeting, and risk control because decisions are often made on values that have not yet been observed. This category focuses on classical statistical forecasting methods that are interpretable, well-studied, and practical for business and engineering workflows. These tools are especially effective when teams need transparent assumptions and stable baseline forecasts.
The shared foundation is the decomposition of a series into level, trend, seasonality, and stochastic residuals. ARIMA-family methods represent autocorrelation through autoregressive and moving-average dynamics, often after differencing to improve stationarity, while exponential smoothing methods recursively update latent components with smoothing weights. Model quality is typically balanced with parsimony using information criteria such as AIC, BIC, and HQIC. In compact notation, many workflows optimize a criterion like \mathrm{IC} = -2\log L + k\,c(n), where L is likelihood and the penalty term controls complexity.
Implementation is powered by Statsmodels, particularly the time-series analysis module, which provides robust estimation, diagnostics, and forecasting routines for classical econometric and statistical models. The category wrappers expose these capabilities in spreadsheet-friendly form while preserving key controls such as model order, trend handling, seasonality, and parameter constraints.
For ARIMA-style forecasting and state-space modeling, ARIMA_FORECAST and SARIMAX_FORECAST generate forward projections from non-seasonal and seasonal autoregressive structures, with SARIMAX extending to richer seasonal/state-space formulations. INNOVATIONS_MLE estimates SARIMA parameters through innovations-based maximum likelihood, which is useful when parameter estimation is the primary goal before scenario forecasting. HANNAN_RISSANEN offers a multi-stage ARMA parameter estimator that is often used for fast initialization or exploratory identification. Together, these functions support end-to-end workflows from parameter estimation to production forecasts in domains such as sales, energy load, and operations planning.
For order identification and complexity control, ARMA_ORDER_IC searches over AR and MA lag combinations and returns the (p,q) pair minimizing the selected information criterion. This is a practical first step when analysts need a defensible model order without manual trial-and-error. It complements estimation functions by narrowing candidate structures before fitting final models. In iterative modeling cycles, this tool helps standardize model selection across many related series.
For exponential smoothing families, SES_FORECAST handles level-only dynamics, HOLT_FORECAST adds trend (optionally damped), and HW_FORECAST adds configurable seasonal structure through Holt-Winters recursions. These methods are often preferred when signal components are stable and the goal is fast, interpretable forecasting with minimal parameter tuning. They map naturally to business cadence data (weekly, monthly, quarterly), where trend and recurring seasonal effects dominate short-to-medium horizon behavior. Used alongside ARIMA-family models, they provide strong benchmark and production alternatives across forecasting maturity levels.
ARIMA_FORECAST
This function fits an autoregressive integrated moving average model to a univariate time series and returns point forecasts for a specified number of future periods.
The ARIMA model combines autoregressive terms, differencing, and moving-average terms to model serial dependence in time-series data:
\phi(L)(1-L)^d y_t = c + \theta(L)\varepsilon_t
where p controls autoregressive order, d controls differencing order, and q controls moving-average order.
Excel Usage
=ARIMA_FORECAST(endog, p, d, q, seasonal_p, seasonal_d, seasonal_q, seasonal_s, steps, enforce_stationarity, enforce_invertibility)
endog(list[list], required): Time-series observations as a 2D range (data points).p(int, optional, default: 1): Non-seasonal autoregressive order (lags).d(int, optional, default: 0): Non-seasonal differencing order (differences).q(int, optional, default: 0): Non-seasonal moving-average order (lags).seasonal_p(int, optional, default: 0): Seasonal autoregressive order (lags).seasonal_d(int, optional, default: 0): Seasonal differencing order (differences).seasonal_q(int, optional, default: 0): Seasonal moving-average order (lags).seasonal_s(int, optional, default: 0): Seasonal period length (periods).steps(int, optional, default: 1): Number of future periods to forecast (periods).enforce_stationarity(bool, optional, default: true): Whether to enforce stationarity constraints (true/false).enforce_invertibility(bool, optional, default: true): Whether to enforce invertibility constraints (true/false).
Returns (list[list]): Row vector containing forecasted values for the requested forecast horizon.
Example 1: One-step ARIMA forecast with default orders
Inputs:
| endog | steps | |||||||
|---|---|---|---|---|---|---|---|---|
| 10 | 12 | 13 | 15 | 14 | 16 | 18 | 17 | 1 |
Excel formula:
=ARIMA_FORECAST({10,12,13,15,14,16,18,17}, 1)
Expected output:
16.4953
Example 2: Two-step ARIMA forecast
Inputs:
| endog | p | d | q | steps | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 4 | 6 | 7 | 9 | 11 | 10 | 12 | 1 | 1 | 0 | 2 |
Excel formula:
=ARIMA_FORECAST({3,4,6,7,9,11,10,12}, 1, 1, 0, 2)
Expected output:
| Result | |
|---|---|
| 12.7183 | 12.9763 |
Example 3: Seasonal ARIMA structure with period four
Inputs:
| endog | p | d | q | seasonal_p | seasonal_d | seasonal_q | seasonal_s | steps | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 20 | 22 | 25 | 23 | 21 | 24 | 27 | 26 | 24 | 26 | 29 | 28 | 1 | 0 | 0 | 1 | 0 | 0 | 4 | 1 |
Excel formula:
=ARIMA_FORECAST({20,22,25,23,21,24,27,26,24,26,29,28}, 1, 0, 0, 1, 0, 0, 4, 1)
Expected output:
25.8609
Example 4: Scalar normalization path with single numeric input wrapped
Inputs:
| endog | p | d | q | steps | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 5 | 5 | 6 | 6 | 7 | 7 | 8 | 0 | 1 | 1 | 1 |
Excel formula:
=ARIMA_FORECAST({5,5,6,6,7,7,8}, 0, 1, 1, 1)
Expected output:
8
Python Code
Show Code
import numpy as np
from statsmodels.tsa.arima.model import ARIMA as sm_ARIMA
def arima_forecast(endog, p=1, d=0, q=0, seasonal_p=0, seasonal_d=0, seasonal_q=0, seasonal_s=0, steps=1, enforce_stationarity=True, enforce_invertibility=True):
"""
Fit an ARIMA model and return out-of-sample forecasts.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.arima.model.ARIMA.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
p (int, optional): Non-seasonal autoregressive order (lags). Default is 1.
d (int, optional): Non-seasonal differencing order (differences). Default is 0.
q (int, optional): Non-seasonal moving-average order (lags). Default is 0.
seasonal_p (int, optional): Seasonal autoregressive order (lags). Default is 0.
seasonal_d (int, optional): Seasonal differencing order (differences). Default is 0.
seasonal_q (int, optional): Seasonal moving-average order (lags). Default is 0.
seasonal_s (int, optional): Seasonal period length (periods). Default is 0.
steps (int, optional): Number of future periods to forecast (periods). Default is 1.
enforce_stationarity (bool, optional): Whether to enforce stationarity constraints (true/false). Default is True.
enforce_invertibility (bool, optional): Whether to enforce invertibility constraints (true/false). Default is True.
Returns:
list[list]: Row vector containing forecasted values for the requested forecast horizon.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 3:
return "Error: endog must contain at least 3 numeric values"
if steps < 1:
return "Error: steps must be at least 1"
model = sm_ARIMA(
series,
order=(int(p), int(d), int(q)),
seasonal_order=(int(seasonal_p), int(seasonal_d), int(seasonal_q), int(seasonal_s)),
enforce_stationarity=bool(enforce_stationarity),
enforce_invertibility=bool(enforce_invertibility)
)
fitted = model.fit()
forecast = np.asarray(fitted.forecast(steps=int(steps)), dtype=float).reshape(1, -1)
return forecast.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
ARMA_ORDER_IC
This function evaluates multiple ARMA models over a grid of autoregressive and moving-average orders and returns the order pair that minimizes the selected information criterion.
Information criteria balance goodness of fit and model complexity, and common choices are Akaike information criterion (AIC), Bayesian information criterion (BIC), and Hannan-Quinn information criterion (HQIC).
The returned result is the minimizing (p, q) order for the chosen criterion.
Excel Usage
=ARMA_ORDER_IC(y, max_ar, max_ma, ic, trend)
y(list[list], required): Time-series observations as a 2D range (data points).max_ar(int, optional, default: 4): Maximum autoregressive lag order to evaluate (lags).max_ma(int, optional, default: 2): Maximum moving-average lag order to evaluate (lags).ic(str, optional, default: “bic”): Information criterion name aic, bic, or hqic (option).trend(str, optional, default: “c”): Deterministic trend option n or c (option).
Returns (list[list]): Single-row output containing the selected AR and MA orders as [p, q].
Example 1: Select order using BIC defaults
Inputs:
| y | max_ar | max_ma | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 1.5 | 2.1 | 2 | 2.4 | 2.2 | 2.8 | 2.6 | 3 | 2 | 2 |
Excel formula:
=ARMA_ORDER_IC({1,2,1.5,2.1,2,2.4,2.2,2.8,2.6,3}, 2, 2)
Expected output:
| Result | |
|---|---|
| 2 | 2 |
Example 2: Select order using AIC
Inputs:
| y | max_ar | max_ma | ic | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5 | 4.8 | 5.1 | 5 | 5.4 | 5.3 | 5.7 | 5.6 | 5.9 | 6 | 2 | 1 | aic |
Excel formula:
=ARMA_ORDER_IC({5,4.8,5.1,5,5.4,5.3,5.7,5.6,5.9,6}, 2, 1, "aic")
Expected output:
| Result | |
|---|---|
| 2 | 1 |
Example 3: Select order using HQIC without deterministic trend
Inputs:
| y | max_ar | max_ma | ic | trend | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10 | 11 | 10.5 | 11.2 | 11 | 11.6 | 11.4 | 12 | 11.8 | 12.3 | 1 | 2 | hqic | n |
Excel formula:
=ARMA_ORDER_IC({10,11,10.5,11.2,11,11.6,11.4,12,11.8,12.3}, 1, 2, "hqic", "n")
Expected output:
| Result | |
|---|---|
| 1 | 2 |
Example 4: Select order with constant trend
Inputs:
| y | max_ar | max_ma | trend | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 2.3 | 2.7 | 3 | 3.5 | 3.9 | 4.2 | 4.8 | 5.1 | 5.6 | 1 | 1 | c |
Excel formula:
=ARMA_ORDER_IC({2,2.3,2.7,3,3.5,3.9,4.2,4.8,5.1,5.6}, 1, 1, "c")
Expected output:
| Result | |
|---|---|
| 1 | 1 |
Python Code
Show Code
from statsmodels.tsa.stattools import arma_order_select_ic as sm_arma_order_select_ic
def arma_order_ic(y, max_ar=4, max_ma=2, ic='bic', trend='c'):
"""
Select ARMA order using an information criterion.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.arma_order_select_ic.html
This example function is provided as-is without any representation of accuracy.
Args:
y (list[list]): Time-series observations as a 2D range (data points).
max_ar (int, optional): Maximum autoregressive lag order to evaluate (lags). Default is 4.
max_ma (int, optional): Maximum moving-average lag order to evaluate (lags). Default is 2.
ic (str, optional): Information criterion name aic, bic, or hqic (option). Valid options: AIC, BIC, HQIC. Default is 'bic'.
trend (str, optional): Deterministic trend option n or c (option). Default is 'c'.
Returns:
list[list]: Single-row output containing the selected AR and MA orders as [p, q].
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
y = to2d(y)
if not isinstance(y, list) or not all(isinstance(row, list) for row in y):
return "Error: Invalid input - y must be a 2D list"
series = []
for row in y:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 6:
return "Error: y must contain at least 6 numeric values"
criterion = str(ic).lower().strip()
if criterion not in ("aic", "bic", "hqic"):
return "Error: ic must be one of aic, bic, or hqic"
trend_value = str(trend).lower().strip()
if trend_value not in ("n", "c"):
return "Error: trend must be one of n or c"
result = sm_arma_order_select_ic(
series,
max_ar=int(max_ar),
max_ma=int(max_ma),
ic=criterion,
trend=trend_value
)
min_order = getattr(result, f"{criterion}_min_order", None)
if min_order is None or len(min_order) != 2:
return "Error: Failed to determine minimum order"
return [[int(min_order[0]), int(min_order[1])]]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
HANNAN_RISSANEN
This function estimates autoregressive and moving-average parameters for a stationary time series using the Hannan-Rissanen multi-step approach.
The procedure fits a high-order autoregression to obtain residuals, then estimates ARMA coefficients using least squares, with an optional bias-correction stage when conditions are satisfied.
The function returns a row vector of estimated ARMA parameter values.
Excel Usage
=HANNAN_RISSANEN(endog, ar_order, ma_order, demean, initial_ar_order)
endog(list[list], required): Time-series observations as a 2D range (data points).ar_order(int, optional, default: 0): Autoregressive order to estimate (lags).ma_order(int, optional, default: 0): Moving-average order to estimate (lags).demean(bool, optional, default: true): Whether to remove the mean before estimation (true/false).initial_ar_order(int, optional, default: 0): Initial long autoregressive order used in first-stage residual estimation (lags).
Returns (list[list]): Row vector containing estimated ARMA parameter values.
Example 1: Hannan-Rissanen estimation for ARMA(1,1)
Inputs:
| endog | ar_order | ma_order | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 5 | 5.2 | 5.1 | 5.4 | 5.3 | 5.6 | 5.5 | 5.8 | 5.7 | 6 | 1 | 1 |
Excel formula:
=HANNAN_RISSANEN({5,5.2,5.1,5.4,5.3,5.6,5.5,5.8,5.7,6}, 1, 1)
Expected output:
| Result | ||
|---|---|---|
| 0.466012 | 1.78856 | 0.0950253 |
Example 2: Hannan-Rissanen estimation for AR(2)
Inputs:
| endog | ar_order | ma_order | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 12 | 12.5 | 12.1 | 12.8 | 12.4 | 13 | 12.7 | 13.3 | 13 | 13.6 | 2 | 0 |
Excel formula:
=HANNAN_RISSANEN({12,12.5,12.1,12.8,12.4,13,12.7,13.3,13,13.6}, 2, 0)
Expected output:
| Result | ||
|---|---|---|
| 0.0857862 | 0.855313 | 0.0929974 |
Example 3: Hannan-Rissanen estimation for MA(1)
Inputs:
| endog | ar_order | ma_order | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 2.9 | 3.1 | 3 | 3.2 | 3.1 | 3.3 | 3.2 | 3.4 | 3.3 | 0 | 1 |
Excel formula:
=HANNAN_RISSANEN({3,2.9,3.1,3,3.2,3.1,3.3,3.2,3.4,3.3}, 0, 1)
Expected output:
| Result | |
|---|---|
| 0.197778 | 0.0257315 |
Example 4: Hannan-Rissanen with explicit initial AR order
Inputs:
| endog | ar_order | ma_order | initial_ar_order | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 8 | 8.3 | 8.1 | 8.5 | 8.2 | 8.6 | 8.4 | 8.8 | 8.6 | 9 | 1 | 1 | 4 |
Excel formula:
=HANNAN_RISSANEN({8,8.3,8.1,8.5,8.2,8.6,8.4,8.8,8.6,9}, 1, 1, 4)
Expected output:
| Result | ||
|---|---|---|
| -2.2046 | 5.07056 | 0.0426358 |
Python Code
Show Code
import numpy as np
from statsmodels.tsa.arima.model import hannan_rissanen as sm_hannan_rissanen
def hannan_rissanen(endog, ar_order=0, ma_order=0, demean=True, initial_ar_order=0):
"""
Estimate ARMA parameters using the Hannan-Rissanen procedure.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.arima.model.hannan_rissanen.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
ar_order (int, optional): Autoregressive order to estimate (lags). Default is 0.
ma_order (int, optional): Moving-average order to estimate (lags). Default is 0.
demean (bool, optional): Whether to remove the mean before estimation (true/false). Default is True.
initial_ar_order (int, optional): Initial long autoregressive order used in first-stage residual estimation (lags). Default is 0.
Returns:
list[list]: Row vector containing estimated ARMA parameter values.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 6:
return "Error: endog must contain at least 6 numeric values"
init_order = None if int(initial_ar_order) <= 0 else int(initial_ar_order)
params, _ = sm_hannan_rissanen(
series,
ar_order=int(ar_order),
ma_order=int(ma_order),
demean=bool(demean),
initial_ar_order=init_order
)
if hasattr(params, "params"):
values = np.asarray(params.params, dtype=float).ravel()
elif hasattr(params, "to_array"):
values = np.asarray(params.to_array(), dtype=float).ravel()
else:
values = np.asarray(params, dtype=float).ravel()
return [values.tolist()]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
HOLT_FORECAST
This function fits Holt’s exponential smoothing model with level and trend components and returns point forecasts.
Holt’s method updates both a level and a trend term over time:
\ell_t = \alpha y_t + (1-\alpha)(\ell_{t-1}+b_{t-1}), \quad b_t = \beta(\ell_t-\ell_{t-1}) + (1-\beta)b_{t-1}
Forecasts are computed by extrapolating the estimated level and trend.
Excel Usage
=HOLT_FORECAST(endog, steps, exponential, damped_trend, initialization_method)
endog(list[list], required): Time-series observations as a 2D range (data points).steps(int, optional, default: 1): Number of future periods to forecast (periods).exponential(bool, optional, default: false): Whether to use exponential trend form (true/false).damped_trend(bool, optional, default: false): Whether to damp the trend component (true/false).initialization_method(str, optional, default: “estimated”): Initialization method such as estimated, heuristic, known, or legacy-heuristic (option).
Returns (list[list]): Row vector containing forecasted values for the requested forecast horizon.
Example 1: One-step Holt forecast
Inputs:
| endog | steps | |||||
|---|---|---|---|---|---|---|
| 10 | 12 | 14 | 16 | 18 | 20 | 1 |
Excel formula:
=HOLT_FORECAST({10,12,14,16,18,20}, 1)
Expected output:
22.0002
Example 2: Two-step Holt forecast with damped trend
Inputs:
| endog | steps | damped_trend | |||||
|---|---|---|---|---|---|---|---|
| 4 | 5 | 7 | 9 | 11 | 13 | 2 | true |
Excel formula:
=HOLT_FORECAST({4,5,7,9,11,13}, 2, TRUE)
Expected output:
| Result | |
|---|---|
| 14.99 | 16.97 |
Example 3: Holt with exponential trend form
Inputs:
| endog | exponential | steps | |||||
|---|---|---|---|---|---|---|---|
| 2 | 2.5 | 3.2 | 4.1 | 5.3 | 6.8 | true | 1 |
Excel formula:
=HOLT_FORECAST({2,2.5,3.2,4.1,5.3,6.8}, TRUE, 1)
Expected output:
8.72385
Example 4: Holt with heuristic initialization
Inputs:
| endog | initialization_method | steps | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 30 | 31 | 33 | 35 | 38 | 40 | 41 | 43 | 45 | 46 | heuristic | 1 |
Excel formula:
=HOLT_FORECAST({30,31,33,35,38,40,41,43,45,46}, "heuristic", 1)
Expected output:
48.6
Python Code
Show Code
import numpy as np
from statsmodels.tsa.holtwinters import Holt as sm_Holt
def holt_forecast(endog, steps=1, exponential=False, damped_trend=False, initialization_method='estimated'):
"""
Fit Holt trend exponential smoothing and return forecasts.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.holtwinters.Holt.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
steps (int, optional): Number of future periods to forecast (periods). Default is 1.
exponential (bool, optional): Whether to use exponential trend form (true/false). Default is False.
damped_trend (bool, optional): Whether to damp the trend component (true/false). Default is False.
initialization_method (str, optional): Initialization method such as estimated, heuristic, known, or legacy-heuristic (option). Default is 'estimated'.
Returns:
list[list]: Row vector containing forecasted values for the requested forecast horizon.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 3:
return "Error: endog must contain at least 3 numeric values"
if steps < 1:
return "Error: steps must be at least 1"
model = sm_Holt(
series,
exponential=bool(exponential),
damped_trend=bool(damped_trend),
initialization_method=initialization_method
)
fitted = model.fit()
forecast = np.asarray(fitted.forecast(int(steps)), dtype=float).reshape(1, -1)
return forecast.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
HW_FORECAST
This function fits Holt-Winters exponential smoothing with configurable trend and seasonality and returns point forecasts.
The model combines level, trend, and seasonal recursions, and can be additive or multiplicative depending on the selected components.
Forecasts follow the estimated structural decomposition over the specified horizon.
Excel Usage
=HW_FORECAST(endog, steps, trend, seasonal, seasonal_periods, damped_trend, initialization_method)
endog(list[list], required): Time-series observations as a 2D range (data points).steps(int, optional, default: 1): Number of future periods to forecast (periods).trend(str, optional, default: “none”): Trend component type add, mul, additive, multiplicative, or none (option).seasonal(str, optional, default: “none”): Seasonal component type add, mul, additive, multiplicative, or none (option).seasonal_periods(int, optional, default: 0): Number of periods in one full seasonal cycle (periods).damped_trend(bool, optional, default: false): Whether to damp the trend component (true/false).initialization_method(str, optional, default: “estimated”): Initialization method such as estimated, heuristic, known, or legacy-heuristic (option).
Returns (list[list]): Row vector containing forecasted values for the requested forecast horizon.
Example 1: Holt-Winters used as level-only smoothing
Inputs:
| endog | trend | seasonal | steps | |||||
|---|---|---|---|---|---|---|---|---|
| 15 | 16 | 17 | 18 | 19 | 20 | none | none | 1 |
Excel formula:
=HW_FORECAST({15,16,17,18,19,20}, "none", "none", 1)
Expected output:
20
Example 2: Holt-Winters with additive trend only
Inputs:
| endog | trend | seasonal | steps | ||||||
|---|---|---|---|---|---|---|---|---|---|
| 5 | 6 | 8 | 9 | 11 | 13 | 14 | add | none | 2 |
Excel formula:
=HW_FORECAST({5,6,8,9,11,13,14}, "add", "none", 2)
Expected output:
| Result | |
|---|---|
| 15.7145 | 17.286 |
Example 3: Holt-Winters with additive seasonality
Inputs:
| endog | trend | seasonal | seasonal_periods | steps | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10 | 12 | 14 | 13 | 11 | 13 | 15 | 14 | 12 | 14 | 16 | 15 | add | add | 4 | 1 |
Excel formula:
=HW_FORECAST({10,12,14,13,11,13,15,14,12,14,16,15}, "add", "add", 4, 1)
Expected output:
13
Example 4: Holt-Winters with damped additive trend
Inputs:
| endog | trend | seasonal | damped_trend | steps | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 22 | 24 | 27 | 30 | 33 | 35 | 37 | 39 | add | none | true | 1 |
Excel formula:
=HW_FORECAST({22,24,27,30,33,35,37,39}, "add", "none", TRUE, 1)
Expected output:
41.0652
Python Code
Show Code
import numpy as np
from statsmodels.tsa.holtwinters import ExponentialSmoothing as sm_ExponentialSmoothing
def hw_forecast(endog, steps=1, trend='none', seasonal='none', seasonal_periods=0, damped_trend=False, initialization_method='estimated'):
"""
Fit Holt-Winters exponential smoothing and return forecasts.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
steps (int, optional): Number of future periods to forecast (periods). Default is 1.
trend (str, optional): Trend component type add, mul, additive, multiplicative, or none (option). Default is 'none'.
seasonal (str, optional): Seasonal component type add, mul, additive, multiplicative, or none (option). Default is 'none'.
seasonal_periods (int, optional): Number of periods in one full seasonal cycle (periods). Default is 0.
damped_trend (bool, optional): Whether to damp the trend component (true/false). Default is False.
initialization_method (str, optional): Initialization method such as estimated, heuristic, known, or legacy-heuristic (option). Default is 'estimated'.
Returns:
list[list]: Row vector containing forecasted values for the requested forecast horizon.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
def normalize_component(value):
if value is None:
return None
text = str(value).strip().lower()
if text in ("none", "n", ""):
return None
return text
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 4:
return "Error: endog must contain at least 4 numeric values"
if steps < 1:
return "Error: steps must be at least 1"
trend_value = normalize_component(trend)
seasonal_value = normalize_component(seasonal)
seasonal_periods_value = None if int(seasonal_periods) <= 0 else int(seasonal_periods)
model = sm_ExponentialSmoothing(
series,
trend=trend_value,
damped_trend=bool(damped_trend),
seasonal=seasonal_value,
seasonal_periods=seasonal_periods_value,
initialization_method=initialization_method
)
fitted = model.fit()
forecast = np.asarray(fitted.forecast(int(steps)), dtype=float).reshape(1, -1)
return forecast.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
INNOVATIONS_MLE
This function estimates parameters of a SARIMA specification by maximizing the likelihood using the innovations algorithm.
The model order is controlled by non-seasonal (p,d,q) and seasonal (P,D,Q,s) components. The estimation method enforces stationarity and can enforce invertibility constraints for moving-average terms.
The result is returned as a row vector of estimated parameter values.
Excel Usage
=INNOVATIONS_MLE(endog, p, d, q, seasonal_p, seasonal_d, seasonal_q, seasonal_s, demean, enforce_invertibility)
endog(list[list], required): Time-series observations as a 2D range (data points).p(int, optional, default: 0): Non-seasonal autoregressive order (lags).d(int, optional, default: 0): Non-seasonal differencing order (differences).q(int, optional, default: 0): Non-seasonal moving-average order (lags).seasonal_p(int, optional, default: 0): Seasonal autoregressive order (lags).seasonal_d(int, optional, default: 0): Seasonal differencing order (differences).seasonal_q(int, optional, default: 0): Seasonal moving-average order (lags).seasonal_s(int, optional, default: 0): Seasonal period length (periods).demean(bool, optional, default: true): Whether to remove the mean before estimation (true/false).enforce_invertibility(bool, optional, default: true): Whether to enforce invertibility constraints (true/false).
Returns (list[list]): Row vector containing estimated SARIMA parameter values.
Example 1: Innovations MLE for ARMA(1,1)
Inputs:
| endog | p | d | q | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10 | 10.5 | 11.2 | 10.9 | 11.5 | 12 | 11.8 | 12.3 | 12.1 | 12.7 | 1 | 0 | 1 |
Excel formula:
=INNOVATIONS_MLE({10,10.5,11.2,10.9,11.5,12,11.8,12.3,12.1,12.7}, 1, 0, 1)
Expected output:
| Result | ||
|---|---|---|
| 0.906275 | -0.045126 | 0.231343 |
Example 2: Innovations MLE for AR(1)
Inputs:
| endog | p | d | q | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4 | 4.4 | 4.1 | 4.6 | 4.3 | 4.8 | 4.5 | 5 | 4.7 | 5.1 | 1 | 0 | 0 |
Excel formula:
=INNOVATIONS_MLE({4,4.4,4.1,4.6,4.3,4.8,4.5,5,4.7,5.1}, 1, 0, 0)
Expected output:
| Result | |
|---|---|
| 0.239045 | 0.113806 |
Example 3: Innovations MLE for MA(1)
Inputs:
| endog | p | d | q | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 7 | 6.9 | 7.2 | 7.1 | 7.4 | 7.3 | 7.6 | 7.5 | 7.7 | 7.8 | 0 | 0 | 1 |
Excel formula:
=INNOVATIONS_MLE({7,6.9,7.2,7.1,7.4,7.3,7.6,7.5,7.7,7.8}, 0, 0, 1)
Expected output:
| Result | |
|---|---|
| 0.433657 | 0.0600301 |
Example 4: Innovations MLE without demeaning
Inputs:
| endog | p | d | q | demean | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 2.2 | 2.5 | 2.7 | 2.9 | 3.1 | 3 | 3.3 | 3.5 | 3.6 | 1 | 0 | 1 | false |
Excel formula:
=INNOVATIONS_MLE({2,2.2,2.5,2.7,2.9,3.1,3,3.3,3.5,3.6}, 1, 0, 1, FALSE)
Expected output:
| Result | ||
|---|---|---|
| 0.996018 | 0.413066 | 0.0338986 |
Python Code
Show Code
import numpy as np
from statsmodels.tsa.arima.model import innovations_mle as sm_innovations_mle
def innovations_mle(endog, p=0, d=0, q=0, seasonal_p=0, seasonal_d=0, seasonal_q=0, seasonal_s=0, demean=True, enforce_invertibility=True):
"""
Estimate SARIMA parameters using innovations maximum likelihood.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.arima.model.innovations_mle.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
p (int, optional): Non-seasonal autoregressive order (lags). Default is 0.
d (int, optional): Non-seasonal differencing order (differences). Default is 0.
q (int, optional): Non-seasonal moving-average order (lags). Default is 0.
seasonal_p (int, optional): Seasonal autoregressive order (lags). Default is 0.
seasonal_d (int, optional): Seasonal differencing order (differences). Default is 0.
seasonal_q (int, optional): Seasonal moving-average order (lags). Default is 0.
seasonal_s (int, optional): Seasonal period length (periods). Default is 0.
demean (bool, optional): Whether to remove the mean before estimation (true/false). Default is True.
enforce_invertibility (bool, optional): Whether to enforce invertibility constraints (true/false). Default is True.
Returns:
list[list]: Row vector containing estimated SARIMA parameter values.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 6:
return "Error: endog must contain at least 6 numeric values"
params, _ = sm_innovations_mle(
series,
order=(int(p), int(d), int(q)),
seasonal_order=(int(seasonal_p), int(seasonal_d), int(seasonal_q), int(seasonal_s)),
demean=bool(demean),
enforce_invertibility=bool(enforce_invertibility)
)
if hasattr(params, "params"):
values = np.asarray(params.params, dtype=float).ravel()
elif hasattr(params, "to_array"):
values = np.asarray(params.to_array(), dtype=float).ravel()
else:
values = np.asarray(params, dtype=float).ravel()
return [values.tolist()]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SARIMAX_FORECAST
This function fits a seasonal ARIMA model in state-space form and returns point forecasts for future periods.
SARIMAX extends ARIMA by allowing explicit seasonal dynamics and optional exogenous regressors:
\Phi(L^s)\phi(L)(1-L)^d(1-L^s)^D y_t = A(t) + \Theta(L^s)\theta(L)\varepsilon_t
The function supports non-seasonal and seasonal orders and returns forecasts as a row vector.
Excel Usage
=SARIMAX_FORECAST(endog, p, d, q, seasonal_p, seasonal_d, seasonal_q, seasonal_s, steps, trend, enforce_stationarity, enforce_invertibility)
endog(list[list], required): Time-series observations as a 2D range (data points).p(int, optional, default: 1): Non-seasonal autoregressive order (lags).d(int, optional, default: 0): Non-seasonal differencing order (differences).q(int, optional, default: 0): Non-seasonal moving-average order (lags).seasonal_p(int, optional, default: 0): Seasonal autoregressive order (lags).seasonal_d(int, optional, default: 0): Seasonal differencing order (differences).seasonal_q(int, optional, default: 0): Seasonal moving-average order (lags).seasonal_s(int, optional, default: 0): Seasonal period length (periods).steps(int, optional, default: 1): Number of future periods to forecast (periods).trend(str, optional, default: “n”): Deterministic trend specification such as n, c, t, or ct (option).enforce_stationarity(bool, optional, default: true): Whether to enforce stationarity constraints (true/false).enforce_invertibility(bool, optional, default: true): Whether to enforce invertibility constraints (true/false).
Returns (list[list]): Row vector containing forecasted values for the requested forecast horizon.
Example 1: One-step SARIMAX forecast with default order
Inputs:
| endog | steps | |||||||
|---|---|---|---|---|---|---|---|---|
| 30 | 31 | 33 | 32 | 35 | 36 | 37 | 39 | 1 |
Excel formula:
=SARIMAX_FORECAST({30,31,33,32,35,36,37,39}, 1)
Expected output:
38.9517
Example 2: Two-step SARIMAX forecast with differencing
Inputs:
| endog | p | d | q | steps | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 8 | 9 | 11 | 12 | 14 | 15 | 17 | 18 | 1 | 1 | 0 | 2 |
Excel formula:
=SARIMAX_FORECAST({8,9,11,12,14,15,17,18}, 1, 1, 0, 2)
Expected output:
| Result | |
|---|---|
| 18.753 | 19.3201 |
Example 3: SARIMAX with constant trend term
Inputs:
| endog | trend | steps | |||||||
|---|---|---|---|---|---|---|---|---|---|
| 5 | 6 | 7 | 9 | 10 | 11 | 13 | 14 | c | 1 |
Excel formula:
=SARIMAX_FORECAST({5,6,7,9,10,11,13,14}, "c", 1)
Expected output:
13.7427
Example 4: Seasonal SARIMAX with period four
Inputs:
| endog | p | d | q | seasonal_p | seasonal_d | seasonal_q | seasonal_s | steps | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12 | 14 | 16 | 15 | 13 | 15 | 17 | 16 | 14 | 16 | 18 | 17 | 1 | 0 | 0 | 1 | 0 | 0 | 4 | 1 |
Excel formula:
=SARIMAX_FORECAST({12,14,16,15,13,15,17,16,14,16,18,17}, 1, 0, 0, 1, 0, 0, 4, 1)
Expected output:
14.9982
Python Code
Show Code
import numpy as np
from statsmodels.tsa.statespace.sarimax import SARIMAX as sm_SARIMAX
def sarimax_forecast(endog, p=1, d=0, q=0, seasonal_p=0, seasonal_d=0, seasonal_q=0, seasonal_s=0, steps=1, trend='n', enforce_stationarity=True, enforce_invertibility=True):
"""
Fit a SARIMAX model and return out-of-sample forecasts.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.statespace.sarimax.SARIMAX.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
p (int, optional): Non-seasonal autoregressive order (lags). Default is 1.
d (int, optional): Non-seasonal differencing order (differences). Default is 0.
q (int, optional): Non-seasonal moving-average order (lags). Default is 0.
seasonal_p (int, optional): Seasonal autoregressive order (lags). Default is 0.
seasonal_d (int, optional): Seasonal differencing order (differences). Default is 0.
seasonal_q (int, optional): Seasonal moving-average order (lags). Default is 0.
seasonal_s (int, optional): Seasonal period length (periods). Default is 0.
steps (int, optional): Number of future periods to forecast (periods). Default is 1.
trend (str, optional): Deterministic trend specification such as n, c, t, or ct (option). Default is 'n'.
enforce_stationarity (bool, optional): Whether to enforce stationarity constraints (true/false). Default is True.
enforce_invertibility (bool, optional): Whether to enforce invertibility constraints (true/false). Default is True.
Returns:
list[list]: Row vector containing forecasted values for the requested forecast horizon.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 3:
return "Error: endog must contain at least 3 numeric values"
if steps < 1:
return "Error: steps must be at least 1"
model = sm_SARIMAX(
series,
order=(int(p), int(d), int(q)),
seasonal_order=(int(seasonal_p), int(seasonal_d), int(seasonal_q), int(seasonal_s)),
trend=trend,
enforce_stationarity=bool(enforce_stationarity),
enforce_invertibility=bool(enforce_invertibility)
)
fitted = model.fit(disp=False)
forecast = np.asarray(fitted.forecast(steps=int(steps)), dtype=float).reshape(1, -1)
return forecast.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SES_FORECAST
This function fits a level-only exponential smoothing model and returns point forecasts for future periods.
Simple exponential smoothing updates the level recursively using a smoothing parameter \alpha:
\ell_t = \alpha y_t + (1-\alpha)\ell_{t-1}
Forecasts at future horizons use the final estimated level value.
Excel Usage
=SES_FORECAST(endog, steps, initialization_method)
endog(list[list], required): Time-series observations as a 2D range (data points).steps(int, optional, default: 1): Number of future periods to forecast (periods).initialization_method(str, optional, default: “estimated”): Initialization method such as estimated, heuristic, known, or legacy-heuristic (option).
Returns (list[list]): Row vector containing forecasted values for the requested forecast horizon.
Example 1: One-step SES forecast
Inputs:
| endog | steps | |||||
|---|---|---|---|---|---|---|
| 10 | 11 | 12 | 13 | 14 | 15 | 1 |
Excel formula:
=SES_FORECAST({10,11,12,13,14,15}, 1)
Expected output:
15
Example 2: Three-step SES forecast
Inputs:
| endog | steps | |||||
|---|---|---|---|---|---|---|
| 20 | 19 | 21 | 22 | 23 | 24 | 3 |
Excel formula:
=SES_FORECAST({20,19,21,22,23,24}, 3)
Expected output:
| Result | ||
|---|---|---|
| 24 | 24 | 24 |
Example 3: SES with heuristic initialization
Inputs:
| endog | initialization_method | steps | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | heuristic | 2 |
Excel formula:
=SES_FORECAST({5,6,8,9,10,11,12,13,14,15}, "heuristic", 2)
Expected output:
| Result | |
|---|---|
| 15 | 15 |
Example 4: SES from single-row range input
Inputs:
| endog | steps | ||||
|---|---|---|---|---|---|
| 2 | 3 | 3 | 4 | 5 | 1 |
Excel formula:
=SES_FORECAST({2,3,3,4,5}, 1)
Expected output:
5
Python Code
Show Code
import numpy as np
from statsmodels.tsa.holtwinters import SimpleExpSmoothing as sm_SimpleExpSmoothing
def ses_forecast(endog, steps=1, initialization_method='estimated'):
"""
Fit simple exponential smoothing and return forecasts.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.holtwinters.SimpleExpSmoothing.html
This example function is provided as-is without any representation of accuracy.
Args:
endog (list[list]): Time-series observations as a 2D range (data points).
steps (int, optional): Number of future periods to forecast (periods). Default is 1.
initialization_method (str, optional): Initialization method such as estimated, heuristic, known, or legacy-heuristic (option). Default is 'estimated'.
Returns:
list[list]: Row vector containing forecasted values for the requested forecast horizon.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
endog = to2d(endog)
if not isinstance(endog, list) or not all(isinstance(row, list) for row in endog):
return "Error: Invalid input - endog must be a 2D list"
series = []
for row in endog:
for value in row:
try:
series.append(float(value))
except (TypeError, ValueError):
continue
if len(series) < 2:
return "Error: endog must contain at least 2 numeric values"
if steps < 1:
return "Error: steps must be at least 1"
model = sm_SimpleExpSmoothing(series, initialization_method=initialization_method)
fitted = model.fit()
forecast = np.asarray(fitted.forecast(int(steps)), dtype=float).reshape(1, -1)
return forecast.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator