-
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 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.
Read more about ADAM ARIMA (and thus MSARIMA) in Svetunkov (2023), Chapter 9.
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)# Auto-select using information criteria
model = MSARIMA(arima_select=True)
model.fit(y)
# With maximum orders specified
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)| 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), DOI: 10.1201/9781003452652
- 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