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

Time-series observations as a 2D range (data points).
Non-seasonal autoregressive order (lags).
Non-seasonal differencing order (differences).
Non-seasonal moving-average order (lags).
Seasonal autoregressive order (lags).
Seasonal differencing order (differences).
Seasonal moving-average order (lags).
Seasonal period length (periods).
Number of future periods to forecast (periods).
Whether to enforce stationarity constraints (true/false).
Whether to enforce invertibility constraints (true/false).

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

Time-series observations as a 2D range (data points).
Maximum autoregressive lag order to evaluate (lags).
Maximum moving-average lag order to evaluate (lags).
Information criterion name aic, bic, or hqic (option).
Deterministic trend option n or c (option).

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

Time-series observations as a 2D range (data points).
Autoregressive order to estimate (lags).
Moving-average order to estimate (lags).
Whether to remove the mean before estimation (true/false).
Initial long autoregressive order used in first-stage residual estimation (lags).

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

Time-series observations as a 2D range (data points).
Number of future periods to forecast (periods).
Whether to use exponential trend form (true/false).
Whether to damp the trend component (true/false).
Initialization method such as estimated, heuristic, known, or legacy-heuristic (option).

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

Time-series observations as a 2D range (data points).
Number of future periods to forecast (periods).
Trend component type add, mul, additive, multiplicative, or none (option).
Seasonal component type add, mul, additive, multiplicative, or none (option).
Number of periods in one full seasonal cycle (periods).
Whether to damp the trend component (true/false).
Initialization method such as estimated, heuristic, known, or legacy-heuristic (option).

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

Time-series observations as a 2D range (data points).
Non-seasonal autoregressive order (lags).
Non-seasonal differencing order (differences).
Non-seasonal moving-average order (lags).
Seasonal autoregressive order (lags).
Seasonal differencing order (differences).
Seasonal moving-average order (lags).
Seasonal period length (periods).
Whether to remove the mean before estimation (true/false).
Whether to enforce invertibility constraints (true/false).

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

Time-series observations as a 2D range (data points).
Non-seasonal autoregressive order (lags).
Non-seasonal differencing order (differences).
Non-seasonal moving-average order (lags).
Seasonal autoregressive order (lags).
Seasonal differencing order (differences).
Seasonal moving-average order (lags).
Seasonal period length (periods).
Number of future periods to forecast (periods).
Deterministic trend specification such as n, c, t, or ct (option).
Whether to enforce stationarity constraints (true/false).
Whether to enforce invertibility constraints (true/false).

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

Time-series observations as a 2D range (data points).
Number of future periods to forecast (periods).
Initialization method such as estimated, heuristic, known, or legacy-heuristic (option).