Skip to content
Ivan Svetunkov edited this page May 27, 2026 · 20 revisions

ADAM - Augmented Dynamic Adaptive Model

ADAM is the primary unified framework in the smooth package, combining ETS (Error-Trend-Seasonal), ARIMA, and regression components into a single state-space model using the Single Source of Error (SSOE) approach.

Mathematical Form

The ADAM model is specified in state-space form as:

y_t = o_t(w(v_{t-l}, x_t) + r(v_{t-l})ε_t)
v_t = f(v_{t-l}, a_{t-1}) + g(v_{t-l}, a_{t-1}, x_t)ε_t

Where:

  • y_t: Observed value at time t
  • o_t: Occurrence indicator (for intermittent data)
  • v_t: State vector (level, trend, seasonal, ARIMA components, regression parameters)
  • l: Vector of lags
  • x_t: Vector of exogenous variables
  • w(·): Measurement function
  • r(·): Error function (additive or multiplicative)
  • f(·): Transition function (state evolution)
  • g(·): Persistence function (smoothing parameters)
  • ε_t: Error term

Key Features

  • Unified Framework: Seamlessly combines ETS, ARIMA and regression in a single model
  • Multiple Seasonality: Supports multiple seasonal periods (e.g., daily + weekly)
  • Automatic Selection: Branch & Bound algorithm for efficient model selection
  • Flexible Distributions: Normal, Laplace, Gamma, Log-Normal, Inverse Gaussian, S, Generalized Normal
  • Intermittent Demand: Built-in occurrence models for sparse data (see OM)
  • External Regressors: Include covariates with adaptive or fixed coefficients

Model Specification

ETS Models

Models are specified using a three-letter (or four-letter in case of damped trend) string "ETS":

  • E (Error): "A" (Additive), "M" (Multiplicative)
  • T (Trend): "N" (None), "A" (Additive), "Ad" (Additive Damped), "M" (Multiplicative), "Md" (Multiplicative Damped)
  • S (Seasonal): "N" (None), "A" (Additive), "M" (Multiplicative)

Examples:

  • model="ANN": Simple Exponential Smoothing
  • model="AAN": Holt's Linear Trend
  • model="AAdA": Holt-Winters Additive with damped trend
  • model="MAM": Multiplicative Holt-Winters

Read more about ETS in Svetunkov (2023), Chapters 4 - 7.

Automatic Selection Codes

  • "ZZZ": Select best model using Branch & Bound
  • "XXX": Select only additive components
  • "YYY": Select only multiplicative components
  • "ZXZ": Auto-select error and seasonal, additive trend only (default, safer)
  • "FFF": Full search across all 30 ETS model types
  • "PPP": Check pure additive and pure multiplicative models only
  • "SSS": Pool of safe models from the forecast package. Letters can be substituted with "X" and "Y" to narrow the pool down.
  • "CCC": AIC-based combination of ETS models. Also supports narrower pools, e.g. "CCN".
  • Vector/list of models: c("ANN","AAN","AAA") in R, ["ANN","AAN","AAA"] in Python — selects best from the specified pool
  • Including a combination model in the list (e.g. ["ANN","AAN","CNN"]) triggers IC-weighted combination of the non-C models in the list.

Model selection is explained in Svetunkov (2023), Section 15.1.

ARIMA Components

Specified via list in orders, e.g. orders=list(ar=c(1,2), i=c(1,1), ma=c(2,2)). Requires lags to be specified explicitly.

To switch off ARIMA, provide model="NNN" in the adam() call.

In Python, use ar_order, i_order, ma_order or the R-style orders dict:

# SARIMA(1,1,1)(1,1,1)[12]
model = ADAM(model="NNN",
             ar_order=[1, 1], i_order=[1, 1], ma_order=[1, 1],
             lags=[1, 12])
model.fit(y)

Precedence between orders and ar_order / i_order / ma_order

ADAM (and AutoADAM) resolves the ARIMA-order arguments with a single precedence rule:

  1. orders (dict) wins. When supplied, the scalar ar_order / i_order / ma_order parameters are ignored and a UserWarning is emitted to flag the conflict.
  2. Otherwise, the scalar triplet is used when any of ar_order / i_order / ma_order has a non-zero value. In ADAM these are treated as fixed orders.
  3. Otherwise, no ARIMA component is fitted.

Read more about ARIMA in Svetunkov (2023), Chapter 8 and Chapter 9.

Fixed ARMA Parameters (arma)

Use arma to fix AR or MA coefficients at user-specified values instead of estimating them. Provide a dict (Python) or list (R) with keys "ar" and/or "ma". Values must be a list of floats matching the total AR or MA order respectively.

# Python — fix only MA
model = ADAM(model="NNN", ar_order=0, i_order=1, ma_order=1,
             arma={"ma": [0.3]})
model.fit(y)

# Fix both AR and MA
model = ADAM(model="NNN", ar_order=1, i_order=1, ma_order=1,
             arma={"ar": [0.5], "ma": [0.2]})
model.fit(y)

# Seasonal ARIMA — list one value per total AR/MA term across all lags
# SARIMA(1,0,0)(0,0,1)[12]: fix AR=0.5 at lag 1, MA=0.3 at lag 12
model = ADAM(model="NNN",
             ar_order=[1, 0], i_order=[1, 1], ma_order=[0, 1], lags=[1, 12],
             arma={"ar": [0.5], "ma": [0.3]})
model.fit(y)
# R — fix both AR and MA
model <- adam(y, model="NNN", orders=c(1,1,1), arma=list(ar=0.5, ma=0.2))

Fixed parameters are not included in model.coef / coef(model) since they are not estimated. In Python they are accessible via model._arima["arma_parameters"].

Constant / Drift

The constant parameter adds an intercept or drift term to the model.

  • constant=TRUE / constant=True — estimate the constant as a free parameter.
  • constant=FALSE / constant=False (default) — no constant.
  • A numeric value — fix the constant at that value without estimating it.

The model name reflects the role of the constant:

Condition Label in model name
ETS model, or ARIMA with any i_order > 0 with drift
Pure ARIMA with all i_order = 0 with constant

Examples of model names: ETS(ANN) with drift, ARIMA(1,1,1) with drift, ARIMA(1,0,1) with constant.

# R
model <- adam(y, model="AAN", constant=TRUE)
model <- adam(y, model="NNN", orders=c(1,1,1), constant=TRUE)
model$constant   # fitted drift value
# Python
model = ADAM(model="AAN", constant=True)
model.fit(y)
model.constant_value   # fitted drift value

model = ADAM(model="NNN", ar_order=1, i_order=1, ma_order=1, constant=True)
model.fit(y)

# Fixed (not estimated) constant
model = ADAM(model="AAN", constant=0.5)
model.fit(y)

Loss Functions

Main loss functions (see Supported Loss Functions subsection below for more):

  • "likelihood": Maximum likelihood (default)
  • "MSE": Mean Squared Error
  • "MAE": Mean Absolute Error
  • "HAM": Half-Absolute Moment
  • "LASSO": use LASSO to shrink the parameters of the model;
  • "RIDGE": use RIDGE to shrink the parameters of the model;
  • "GTMSE": Geometric Trace Mean Squared Error,
  • "GPL": Generalised Predictive Likelihood,
  • custom loss - define your own loss function and use it in the model estimation.

Read more about loss functions in Svetunkov (2023), Chapter 11.

Persistence Parameters

Fixed smoothing parameters can be provided:

Python usage:

model = ADAM(
    model="AAA",
    lags=12,
    persistence={"alpha": 0.3, "beta": 0.1, "gamma": 0.05}
)

R usage:

model = adam(y, model="AAA", lags=12,
    persistence=list(alpha=0.3, beta=0.1, gamma=0.05))
  • alpha: Level smoothing (0 to 1)
  • beta: Trend smoothing (0 to alpha)
  • gamma: Seasonal smoothing (0 to 1-alpha)

If some of parameters are not provided, they will be estimated.

Initialisation Methods

  • "backcasting": Use backcasting (default, faster)
  • "optimal": Optimize all initial states
  • "two-stage": Backcast then optimize
  • "complete": Pure backcasting without optimization
  • provided: User can provide a vector or a list of parameters for the function to use.

More detailed explanation of those is provided in Section 11.4 of Svetunkov (2023).

Python Usage

from smooth import ADAM
import numpy as np

# Sample data
y = np.array([112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118] * 3)

# Automatic model selection
model = ADAM(model="ZXZ", lags=12, ic="AICc")
model.fit(y)

# Model output
print(model)

# Generate forecasts with intervals
forecasts = model.predict(h=12, interval="prediction", level=0.95)

# Access fitted parameters
print(f"Model: {model.model_name}")  # e.g., "ETS(AAN)"
print(f"ETS type: {model.model_type}")  # e.g., "AAN"
print(f"Alpha: {model.persistence_vector['persistence_level']:.3f}")
print(f"AICc: {model.aicc}")

Common Use Cases

# 1. Automatic Forecasting
model = ADAM(model="ZXZ", lags=12)

# 2. Multiple Seasonality (hourly with daily/weekly)
model = ADAM(model="AAA", lags=[24, 168])

# 3. Advanced loss functions. Mean Absolute Error
model = ADAM(model="AAA", lags=12, loss="MAE")

# 4. Advanced loss functions. Multistep loss
model = ADAM(model="AAA", lags=12, loss="GTMSE", h=12)

# 5. Custom loss functions
def loss_function(actual, fitted, B):
    return np.mean(np.abs(actual - fitted)^3)

model = ADAM(model="AAA", lags=12, loss=loss_function)

# 6. Select from a specific pool of models
model = ADAM(model=["ANN", "AAN", "MNN"], lags=[1])

# 7. Model combination (IC-weighted ensemble)
model = ADAM(model="CCC", lags=12)

# 8. Combination from a custom pool
model = ADAM(model=["ANN", "AAN", "MNN", "CNN"], lags=[1])

R Usage

library(smooth)

# Automatic model selection
model <- adam(y, model="ZZZ", lags=12)
print(model)
forecast(model, h=12)

# Pure MSARIMA
model <- adam(y, model="NNN", orders=list(ar=c(1,1), i=c(1,1), ma=c(1,1)), lags=c(1,12))

# ETS(A,A,N) With external regressors
ourData <- cbind(y, X)
model <- adam(ourData, model="AAN", formula=y~x1+x2)

# ETS(A,A,N) + AR(1)  with holdout of 18 last observations
model <- adam(y, model="AAN", orders=c(1,0,0), h=18, holdout=TRUE)

Parameters

Core Parameters

Parameter Type (R) Type (Python) Default Description
model character/vector str/List[str] "ZXZ" Model specification string or list
lags numeric vector int/List[int]/None frequency(y) Seasonal period(s)
orders list Dict[str, Any]/None NULL/None ARIMA orders; Python also accepts dict (see Orders-and-Lags)
ar_order - int/List[int] 0 AR order(s); Python-preferred alternative to orders
i_order - int/List[int] 0 Integration order(s); Python-preferred alternative to orders
ma_order - int/List[int] 0 MA order(s); Python-preferred alternative to orders

Other Model Parameters

Parameter Type (R) Type (Python) Default Description
constant logical/numeric bool/float FALSE/False Include constant/drift term; True estimates it, a number fixes it
arma list Dict[str, Any]/None NULL/None Fixed ARMA coefficients; dict with "ar" and/or "ma" keys
outliers character str "ignore" Outlier handling: "ignore" skips detection; "use" includes detected dummies as fixed regressors; "select" expands each dummy with lag/lead columns and uses regressors="select"
outliers_level - float - / 0.99 Confidence level for outlier detection (Python only; in R use level in auto.adam())

Estimation Parameters

Parameter Type (R) Type (Python) Default Description
distribution character str/None "default" Error distribution
loss character str "likelihood" Loss function for estimation
ic character str "AICc" Information criterion for model selection
bounds character str "usual" Parameter bounds type
initial character/list/vector str/Dict/None "backcasting" Initialization method
persistence list/vector Dict[str, float]/None NULL/None Fixed smoothing parameters
phi numeric float/None NULL/None Dampening parameter
h integer int/None 0 Forecast horizon
holdout logical bool FALSE Use holdout validation
ets character str "conventional" ETS formulation: "conventional" (Hyndman et al. 2008) or "adam" (ADAM reformulation, less explosive multiplicative trends). Experimental.

Supported Loss Functions

  • "likelihood": Maximum likelihood (default)
  • "MSE", "MAE", "HAM": Standard error measures
  • "MSEh", "MAEh", "HAMh": Multi-step versions
  • "TMSE", "TMAE", "THAM": Trace versions
  • "GTMSE", "GTAME", "GTHAM": Geometric trace versions
  • "GPL": Generalised Predictive Likelihood
  • "LASSO", "RIDGE": Regularization

Supported Distributions

  • "dnorm": Normal (default for additive errors)
  • "dgamma": Gamma (default for multiplicative errors)
  • "dlaplace": Laplace (heavy-tailed)
  • "dlnorm": Log-Normal (positive data). The scale calculation routes 1 + errors (or 1 + errors/yFitted) through complex arithmetic — log(as.complex(...)) in R, log((...).astype(complex)) in Python — and takes the modulus, so the scale remains finite and continuous when residuals drop below -1 instead of producing a log(negative) NaN.
  • "dinvgauss": Inverse Gaussian
  • "ds": S distribution (extremely heavy-tailed)
  • "dgnorm": Generalized Normal

Methods

Element (R) Element (Python) Type (R) Type (Python) Description
- fit() result - NDArray Fits the model to the provided data
forecast predict() result vector NDArray Point forecast for h steps ahead

Read more in Fitted-Values-and-Forecasts.

Fitted Attributes

Model Information

Element (R) Element (Python) Type (R) Type (Python) Description
modelName() model_name character str Full model name (e.g., "ETS(AAN)", "ETS(AAA)+ARIMA(1,1,1)")
modelType() model_type character str ETS type code only (e.g., "AAN", "AAdN")
timeElapsed time_elapsed difftime float Time elapsed for model estimation (seconds)
call - call - The function call used
bounds - character - Type of bounds used in estimation

Data and Fitted Values

Element (R) Element (Python) Type (R) Type (Python) Description
data data or actuals matrix/ts NDArray In-sample data used for training
holdout holdout_data vector/ts NDArray/None Holdout part of data
fitted fitted vector NDArray Vector of fitted values
residuals residuals vector NDArray Vector of residuals

State Space Components

Element (R) Element (Python) Type (R) Type (Python) Description
states states matrix NDArray Matrix of states over time
persistence persistence_vector vector Dict Smoothing parameters for the estimated values of α, β, γ, δ
phi phi_ numeric float/None Dampening parameter value (None if no dampening)
transition transition matrix NDArray Transition matrix F
measurement measurement matrix NDArray Measurement matrix W
initial initial_value list Dict Initial state values dict
initialEstimated - vector - Which initials were estimated
initialType initial_type character str Initialization method used

ARIMA Components

Element (R) Element (Python) Type (R) Type (Python) Description
orders orders list Dict ARIMA orders used
arma _arima["arma_parameters"] list list/None AR/MA parameter values (fixed or initialized)
constant constant_value numeric float/None Constant/drift value
lags lags_used vector List Vector of lags used
lagsAll - vector - Vector of internal lags

Model Fit Statistics

Element (R) Element (Python) Type (R) Type (Python) Description
nParam n_param matrix Any Parameter count information
loss loss_ character str Loss function type used
lossValue loss_value numeric float Value of the loss function
logLik loglik numeric float Log-likelihood value
distribution distribution_ character str Distribution function used
scale scale or sigma numeric float Scale parameter value
AIC aic numeric float Akaike Information Criterion
AICc aicc numeric float Corrected AIC
BIC bic numeric float Bayesian Information Criterion
BICc bicc numeric float Corrected BIC
ICw - vector - IC weights if combination was done
accuracy accuracy list Dict/None Out-of-sample accuracy measures (populated when holdout=TRUE/True)

Other Elements

Element (R) Element (Python) Type (R) Type (Python) Description
B coef or b_value vector NDArray Vector of all estimated parameters
occurrence - OM/OMG object - Fitted occurrence model for intermittent demand; see OM
formula - formula - Formula for explanatory variables
profile profile matrix Any Profile matrix used in construction
profileInitial - matrix - Initial profile matrix
lambda - numeric - LASSO/RIDGE parameter
res - list - Optimisation result from nloptr()
other - list - Additional parameters

Accessing Elements (R)

model <- adam(y, model="AAA", lags=12)

# Model name
modelName(model)

# Type of the ETS model
modelType(model)

# ARIMA orders and lags
orders(model)
lags(model)

# Smoothing parameters
model$persistence

# Initial states
model$initial

# Fitted values and residuals
fitted(model)
residuals(model)

# State matrix
model$states

# Information criteria (via methods)
AIC(model)
BIC(model)
logLik(model)

# Coefficients
coef(model)

# Summary with confidence intervals
summary(model)

Accessing Elements (Python)

model = ADAM(model="AAA", lags=[12])
model.fit(y)

# Model name and type
model.model_name  # Full name: "ETS(AAA)"
model.model_type  # ETS code: "AAA"

# Smoothing parameters (dict with persistence_level, persistence_trend, persistence_seasonal)
model.persistence_vector
model.persistence_vector['persistence_level']  # alpha

# Dampening parameter (None if no damping)
model.phi_

# Initial states
model.initial_value

# Fitted values and residuals
model.fitted
model.residuals

# State matrix
model.states

# Information criteria
model.aic
model.aicc
model.bic

# All estimated parameters
model.coef

# Distribution and loss function (trailing _ for fitted values)
model.distribution_
model.loss_
model.loss_value

# Scale parameter
model.scale  # or model.sigma

References

  • Svetunkov, I. (2023). Forecasting and Analytics with the Augmented Dynamic Adaptive Model (ADAM). Chapman and Hall/CRC. Online book: https://openforecast.org/adam/
  • Hyndman, R.J., et al. (2008). Forecasting with Exponential Smoothing: The State Space Approach. Springer.

See Also

Related Functions

  • ES - ETS wrapper of ADAM
  • CES - Complex Exponential Smoothing
  • SSARIMA - State Space ARIMA
  • MSARIMA - Multiple Seasonal ARIMA

Parameter Documentation

Clone this wiki locally