-
Notifications
You must be signed in to change notification settings - Fork 22
MSARIMA
MSARIMA (Multiple Seasonal ARIMA) is an optimized implementation of ARIMA for handling multiple seasonal patterns. It is a wrapper of ADAM that skips zero polynomials, making it substantially faster and more accurate than SSARIMA for high-frequency data.
msarima(y, orders = list(ar = c(0), i = c(1), ma = c(1)), lags = c(1),
constant = FALSE, arma = NULL, model = NULL,
initial = c("backcasting", "optimal", "two-stage", "complete"),
ic = c("AICc", "AIC", "BIC", "BICc"),
loss = c("likelihood", "MSE", "MAE", "HAM",
"MSEh", "TMSE", "GTMSE", "MSCE", "GPL"),
h = 0, holdout = FALSE,
bounds = c("usual", "admissible", "none"),
silent = TRUE,
xreg = NULL, regressors = c("use", "select", "adapt"),
initialX = NULL, ...)
auto.msarima(y, orders = list(ar = c(3, 3), i = c(2, 1), ma = c(3, 3)),
lags = c(1, frequency(y)),
initial = c("backcasting", "optimal", "two-stage", "complete"),
ic = c("AICc", "AIC", "BIC", "BICc"),
loss = c("likelihood", "MSE", "MAE", "HAM",
"MSEh", "TMSE", "GTMSE", "MSCE", "GPL"),
h = 0, holdout = FALSE,
bounds = c("usual", "admissible", "none"),
silent = TRUE, xreg = NULL,
regressors = c("use", "select", "adapt"),
initialX = NULL, ...)class MSARIMA(ADAM):
def __init__(
self,
orders: dict | None = None,
lags: list[int] | None = None,
ar_order: int | list[int] = 0,
i_order: int | list[int] = 1,
ma_order: int | list[int] = 1,
arima_select: bool = False,
constant: bool | float = False,
arma: dict | None = None,
initial: str | dict | None = "backcasting",
initial_X: NDArray | None = None,
ic: Literal["AIC", "AICc", "BIC", "BICc"] = "AICc",
loss: str = "likelihood",
h: int | None = None,
holdout: bool = False,
bounds: Literal["usual", "admissible", "none"] = "usual",
verbose: int = 0,
regressors: Literal["use", "select", "adapt"] = "use",
**kwargs,
) -> None: ...
class AutoMSARIMA(AutoADAM):
def __init__(
self,
lags: list[int] | None = None,
ar_order: int | list[int] | None = [3, 3],
i_order: int | list[int] | None = [2, 1],
ma_order: int | list[int] | None = [3, 3],
orders: dict | None = None,
constant: bool | float = False,
initial: str | dict | None = "backcasting",
initial_X: NDArray | None = None,
ic: Literal["AIC", "AICc", "BIC", "BICc"] = "AICc",
loss: str = "likelihood",
h: int | None = None,
holdout: bool = False,
bounds: Literal["usual", "admissible", "none"] = "usual",
regressors: Literal["use", "select", "adapt"] = "use",
outliers: Literal["ignore", "use", "select"] = "ignore",
level: float = 0.99,
verbose: int = 0,
**kwargs,
) -> None: ...MSARIMA rejects ADAM-only kwargs (model, persistence, phi, distribution) with ValueError. AutoMSARIMA likewise rejects model, distribution, arima_select — order selection is always on.
MSARIMA efficiently handles complex seasonal structures like:
- Hourly data with daily (24) and weekly (168) patterns
- Daily data with weekly (7) and annual (365) patterns
- Sub-daily data with multiple intraday and interday cycles
The implementation differs from SSARIMA by directly mapping non-zero components, reducing the state dimension and improving computational efficiency.
from smooth import MSARIMA
import numpy as np
y = np.array([...]) # your time series
# Default: ARIMA(0,1,1)
model = MSARIMA()
model.fit(y)
print(model)
# ARIMA(1,1,1)
model = MSARIMA(ar_order=1, i_order=1, ma_order=1)
model.fit(y)
# SARIMA(1,1,1)(1,1,1)[12] via dict
model = MSARIMA(
orders={"ar": [1, 1], "i": [1, 1], "ma": [1, 1]},
lags=[1, 12],
)
model.fit(y)
# ARIMA(1,1,1) with drift
model = MSARIMA(ar_order=1, i_order=1, ma_order=1, constant=True)
model.fit(y)
print(f"Drift: {model.constant_value:.4f}")
# Fixed ARMA coefficients (not estimated)
model = MSARIMA(ar_order=1, i_order=1, ma_order=1,
arma={"ar": [0.5], "ma": [0.2]})
model.fit(y)
# Forecasts
forecasts = model.predict(h=12)
forecasts = model.predict(h=12, interval="prediction", level=0.95)# Preferred: use AutoMSARIMA for automatic order selection
from smooth import AutoMSARIMA
model = AutoMSARIMA(lags=[1, 12])
model.fit(y)
# Alternative: MSARIMA with arima_select=True (same result)
model = MSARIMA(
orders={"ar": [2, 1], "i": [1, 1], "ma": [2, 1], "select": True},
lags=[1, 24],
)
model.fit(y)library(smooth)
# Basic non-seasonal ARIMA(1,1,1)
msarima(y, orders=c(1,1,1), lags=1)
# SARIMA(1,1,1)(0,1,1)[12]
msarima(y, orders=list(ar=c(1,0), i=c(1,1), ma=c(1,1)), lags=c(1,12))
# Complex multiple seasonality
# SARIMA(1,1,1)(0,1,1)[24](2,0,1)[168](0,0,1)[720]
msarima(y,
orders=list(ar=c(1,0,2,0), i=c(1,1,0,0), ma=c(1,1,1,1)),
lags=c(1,24,168,720)
)
# With holdout validation
msarima(y, orders=list(ar=c(1,1), i=c(1,1), ma=c(1,1)),
lags=c(1,24), h=48, holdout=TRUE)
# Fixed ARMA coefficients
msarima(y, orders=c(1,1,1), arma=list(ar=0.5, ma=0.2))auto.msarima() is a wrapper of auto.adam().
# Automatic selection
auto.msarima(y, h=24, holdout=TRUE)
# With maximum orders
auto.msarima(y, orders=list(ar=c(2,1), i=c(1,1), ma=c(2,1)), lags=c(1,24))
# Check constant necessity
auto.msarima(y, constant=NULL)AutoMSARIMA (Python) / auto.msarima() (R) automatically selects the best
ARIMA orders using information criteria. It is a wrapper around AutoADAM with
model="NNN" and distribution="dnorm" fixed.
from smooth import AutoMSARIMA
# Automatic non-seasonal ARIMA
model = AutoMSARIMA(lags=[1])
model.fit(y)
print(model) # AutoMSARIMA: ARIMA([p],[d],[q])
# Automatic seasonal ARIMA (monthly data)
model = AutoMSARIMA(lags=[1, 12])
model.fit(y)
fc = model.predict(h=24)
# Reduce search space for speed
model = AutoMSARIMA(
lags=[1, 12],
ar_order=[2, 1],
i_order=[2, 1],
ma_order=[2, 1],
)
model.fit(y)
# With external regressors
model = AutoMSARIMA(lags=[1, 12], regressors="select")
model.fit(y, X=X)# Automatic selection
auto.msarima(y, h=24, holdout=TRUE)
# With maximum orders
auto.msarima(y, orders=list(ar=c(2,1), i=c(2,1), ma=c(2,1)),
lags=c(1,12))
# With external regressors
auto.msarima(y, lags=c(1,12), xreg=X)| Parameter | Type (R) | Type (Python) | Default | Description |
|---|---|---|---|---|
lags |
numeric vector | List[int]/None |
frequency(y) / None |
Seasonal period(s) |
orders |
list | Dict/None | see description / None | Max ARIMA orders. R default: list(ar=c(3,3),i=c(2,1),ma=c(3,3)). Python: dict with "ar", "i", "ma" keys (overrides scalar params). |
ar_order |
- | int/List[int] | - / [3, 3] | Max AR order(s) per lag level |
i_order |
- | int/List[int] | - / [2, 1] | Max integration order(s) per lag level |
ma_order |
- | int/List[int] | - / [3, 3] | Max MA order(s) per lag level |
constant |
logical/numeric | bool/float | FALSE / False | Include constant/drift term |
initial |
character | str/Dict | "backcasting" | Initialisation method |
initialX |
numeric vector | NDArray/None (initial_X) |
NULL / None | Initial regressor coefficients |
ic |
character | str | "AICc" | Information criterion for selection |
loss |
character | str | "likelihood" | Loss function |
h |
integer | int/None | 0 / None | Forecast horizon |
holdout |
logical | bool | FALSE / False | Use holdout validation |
bounds |
character | str | "usual" | Parameter bounds type |
regressors |
character | str | "use" | How to handle external regressors |
xreg |
matrix | - (pass X to .fit()) |
NULL / - | External regressors (R only; Python uses X in fit()) |
outliers |
- | str | - / "ignore" | Outlier handling: "ignore", "use", "select" (Python only) |
level |
- | float | - / 0.99 | Confidence level for outlier detection (Python only) |
The Python parameters model, distribution, and arima_select are fixed
("NNN", "dnorm", True) and cannot be overridden; passing them raises ValueError.
| Parameter | Type (R) | Type (Python) | Default | Description |
|---|---|---|---|---|
y |
vector/ts | NDArray | - | Time series data |
orders |
list/vector | Dict/None | None | ARIMA orders per lag (R-style dict) |
ar_order |
- | int/List[int] | 0 | AR order(s); Python-preferred alternative |
i_order |
- | int/List[int] | 1 | Integration order(s) |
ma_order |
- | int/List[int] | 1 | MA order(s) |
lags |
numeric vector | List[int]/None | None | Seasonal period(s) |
arima_select |
orders$select | bool | False | Automatic order selection |
constant |
logical/numeric | bool/float | False | Include constant/drift |
arma |
list | Dict/None | None | Fixed AR/MA parameter values |
initial |
character | str/Dict | "backcasting" | Initialization method |
initial_X |
initialX | NDArray/None | None | Initial regressor coefficients |
bounds |
character | str | "usual" | Parameter bounds |
ic |
character | str | "AICc" | Information criterion |
loss |
character | str | "likelihood" | Loss function |
h |
integer | int/None | None | Forecast horizon |
holdout |
logical | bool | False | Use holdout validation |
regressors |
character | str | "use" | How to handle regressors |
Each element in ar, i, ma vectors corresponds to the lag at the same position:
# SARIMA(1,1,1)(1,0,1)[12](0,1,1)[52]
orders = list(
ar = c(1, 1, 0), # AR(1) at lag 1, AR(1) at lag 12, AR(0) at lag 52
i = c(1, 0, 1), # I(1) at lag 1, I(0) at lag 12, I(1) at lag 52
ma = c(1, 1, 1) # MA(1) at all lags
)
lags = c(1, 12, 52)# Python equivalent using dict
model = MSARIMA(
orders={"ar": [1, 1, 0], "i": [1, 0, 1], "ma": [1, 1, 1]},
lags=[1, 12, 52],
)See Orders-and-Lags for full details.
Use arma to fix AR or MA coefficients at specified values instead of estimating them.
The dict keys "ar" and "ma" take lists of values matching the total AR/MA order.
# Fix only MA coefficient
model = MSARIMA(ar_order=0, i_order=1, ma_order=1, arma={"ma": [0.3]})
# Fix both AR and MA
model = MSARIMA(ar_order=1, i_order=1, ma_order=1,
arma={"ar": [0.5], "ma": [0.2]})
# Seasonal ARIMA — provide one value per total AR/MA term
# SARIMA(1,0,0)(0,0,1)[12]: fix AR at lag 1 and MA at lag 12
model = MSARIMA(
orders={"ar": [1, 0], "i": [1, 1], "ma": [0, 1]},
lags=[1, 12],
arma={"ar": [0.5], "ma": [0.3]},
)Fixed parameters do not appear in model.coef (nothing to estimate). They are accessible via model._arima["arma_parameters"].
-
"backcasting": Recommended for high-frequency data -
"optimal": Optimize initial states -
"two-stage": Backcast then optimize -
"complete": Full backcasting including regressors
More detailed explanation is provided in Section 11.4 of Svetunkov (2023).
# R: MSARIMAX model
msarima(y, orders=list(ar=c(1,0), i=c(1,1), ma=c(1,1)),
lags=c(1,24), xreg=X)# Python
model = MSARIMA(ar_order=[1, 0], i_order=[1, 1], ma_order=[1, 1], lags=[1, 24])
model.fit(y, X=X)| Element (R) | Element (Python) | Type (R) | Type (Python) | Description |
|---|---|---|---|---|
modelName() |
model_name |
character | str | Full model name (e.g., "ARIMA(0,1,1)") |
orders() |
_arima["ar_orders"] etc. |
list | Dict | ARIMA orders used |
lags() |
lags_used |
vector | List | Lags vector used |
arma |
_arima["arma_parameters"] |
list | list/None | AR/MA parameter values (fixed or initialized) |
constant |
constant_value |
numeric | float/None | Constant/drift value |
B |
coef |
vector | NDArray | Estimated parameters (empty when all ARMA fixed) |
fitted() |
fitted |
vector | Series | In-sample fitted values |
residuals() |
residuals |
vector | Series | Model residuals |
states |
states |
matrix | DataFrame | State matrix over time |
transition |
transition |
matrix | NDArray | Transition matrix F |
persistence |
persistence_vector |
vector | Dict | Persistence vector g |
measurement |
measurement |
matrix | NDArray | Measurement matrix W |
logLik |
loglik / loss_value
|
numeric | float | Log-likelihood / loss value |
AIC |
aic |
numeric | float | Akaike Information Criterion |
AICc |
aicc |
numeric | float | Corrected AIC |
BIC |
bic |
numeric | float | Bayesian Information Criterion |
distribution |
distribution_ |
character | str | Error distribution used |
scale |
scale / sigma
|
numeric | float | Scale parameter |
| Feature | MSARIMA | SSARIMA |
|---|---|---|
| Speed | Fast | Slow |
| Memory usage | Low | High |
| Multiple seasonality | Optimized | Full polynomial expansion |
| High-frequency data | Recommended | Can be slow |
Use MSARIMA (or ADAM) for:
- Hourly, sub-hourly data
- Multiple seasonal patterns
- Large datasets
- Svetunkov, I. (2023). Forecasting and Analytics with the Augmented Dynamic Adaptive Model (ADAM). Online: https://openforecast.org/adam/. DOI: 10.1201/9781003452652.
- ADAM ARIMA: Chapter 9.
- ADAM - Unified framework (Python/R)
- AutoADAM - Automatic distribution and ARIMA selection
- SSARIMA - Original State Space ARIMA
- ES - Exponential Smoothing
- Orders-and-Lags - ARIMA orders and lags specification
- Loss-Functions - Loss function options
- Explanatory-Variables - Using external regressors
- Initialisation - State initialization methods
- Bounds - Parameter restrictions