SARIMA (Seasonal ARIMA) › Implementation in Statsmodels

Michael BrenndoerferAugust 11, 20256 min read
Machine Learning from ScratchAll chapters
Part 8 of 9Time Series
Chapter 58SARIMA (Seasonal ARIMA) › Implementation in Statsmodels
Reading section 6 of 9 · Implementation in Statsmodels · 6 minSection 6 of 9 · 6 min

Book contents

Section 6 of 9 · 6 min read

SARIMA (Seasonal ARIMA) › Implementation in StatsmodelsOne section · Sections in this chapter6 / 9 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Now let's see how the SARIMA formula we've discussed translates into actual code. We'll implement SARIMA using the statsmodels library, which provides time series analysis tools. As we work through the implementation, you'll see how each component of the formula.differencing, autoregressive terms, and moving average terms.is handled by the library, making the connection between theory and practice concrete.

Statsmodels is a good choice here because it offers robust statistical inference, diagnostic tools, and detailed model summaries that are important for understanding SARIMA model performance.

In[6]:
Code
import warnings

import numpy as np
import pandas as pd

warnings.filterwarnings("ignore")

# Generate realistic monthly sales data with trend and seasonality
np.random.seed(42)
n_months = 60  # 5 years of data
dates = pd.date_range(start="2019-01-01", periods=n_months, freq="ME")

# Create components: trend, seasonal, and noise
trend = np.linspace(100, 150, n_months)  # Gradual upward trend
seasonal = 25 * np.sin(2 * np.pi * np.arange(n_months) / 12) + 15 * np.cos(
    2 * np.pi * np.arange(n_months) / 6
)
noise = np.random.normal(0, 8, n_months)

# Combine components
sales_data = trend + seasonal + noise
sales_series = pd.Series(sales_data, index=dates, name="Monthly_Sales")

# Calculate summary statistics
mean_sales = sales_series.mean()
std_sales = sales_series.std()
Out[7]:
Console
Generated time series with 60 months of data
Mean: 123.76, Std: 24.44

First 12 months of sales data:
January 2019: $118.97K
February 2019: $119.74K
March 2019: $121.03K
April 2019: $124.73K
May 2019: $115.67K
June 2019: $122.36K
July 2019: $132.72K
August 2019: $107.07K
September 2019: $73.87K
October 2019: $71.97K
November 2019: $75.62K
December 2019: $100.60K

The generated time series shows a clear upward trend from approximately $100K to $150K over 5 years, with seasonal fluctuations. The mean and standard deviation provide a baseline for understanding the data's central tendency and variability before modeling.

In[8]:
Code
from statsmodels.tsa.arima.model import ARIMA

# Fit SARIMA model - we'll use SARIMA(1,1,1)(1,1,1)12
# This means: p=1, d=1, q=1 (non-seasonal) and P=1, D=1, Q=1 (seasonal) with s=12
sarima_model = ARIMA(
    sales_series, order=(1, 1, 1), seasonal_order=(1, 1, 1, 12)
)
sarima_fit = sarima_model.fit()
Out[9]:
Console
SARIMA Model Summary:
                                    SARIMAX Results                                     
========================================================================================
Dep. Variable:                    Monthly_Sales   No. Observations:                   60
Model:             ARIMA(1, 1, 1)x(1, 1, 1, 12)   Log Likelihood                -170.784
Date:                          Thu, 30 Jul 2026   AIC                            351.568
Time:                                  22:15:31   BIC                            360.819
Sample:                              01-31-2019   HQIC                           355.049
                                   - 12-31-2023                                         
Covariance Type:                            opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
ar.L1         -0.0349      0.264     -0.132      0.895      -0.552       0.482
ma.L1         -0.8403      0.168     -4.989      0.000      -1.170      -0.510
ar.S.L12       0.0021      0.427      0.005      0.996      -0.836       0.840
ma.S.L12      -0.9980    132.733     -0.008      0.994    -261.149     259.153
sigma2        54.3165   7190.086      0.008      0.994    -1.4e+04    1.41e+04
===================================================================================
Ljung-Box (L1) (Q):                   0.30   Jarque-Bera (JB):                 3.01
Prob(Q):                              0.58   Prob(JB):                         0.22
Heteroskedasticity (H):               0.89   Skew:                             0.61
Prob(H) (two-sided):                  0.82   Kurtosis:                         2.81
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

The model summary provides diagnostic information including parameter estimates, standard errors, confidence intervals, and information criteria. The coefficients indicate how strongly current values depend on past values and past forecast errors, both for non-seasonal and seasonal components.

Out[10]:
Console
Key Model Parameters:
Non-seasonal AR coefficient (φ₁): -0.0349
Non-seasonal MA coefficient (θ₁): -0.8403
Seasonal AR coefficient (Φ₁): 0.0021
Seasonal MA coefficient (Θ₁): -0.9980
Model AIC: 351.57
Model BIC: 360.82

The parameter values indicate the strength of relationships in the model. Positive AR coefficients suggest that high values tend to follow high values, while MA coefficients capture how the model adjusts based on past forecast errors. The AIC and BIC values allow comparison with alternative model specifications, with lower values typically indicating better model fit adjusted for complexity.

In[11]:
Code
# Generate forecasts for the next 12 months
forecast_steps = 12
forecast_result = sarima_fit.forecast(steps=forecast_steps)
forecast_ci = sarima_fit.get_forecast(steps=forecast_steps).conf_int()

# Create forecast dates
forecast_dates = pd.date_range(
    start=sales_series.index[-1] + pd.DateOffset(months=1),
    periods=forecast_steps,
    freq="ME",
)
Out[12]:
Console
12-Month Forecast:
January 2024: $168.33K (95% CI: $152.39K - $184.26K)
February 2024: $164.23K (95% CI: $148.17K - $180.28K)
March 2024: $163.14K (95% CI: $146.89K - $179.38K)
April 2024: $166.81K (95% CI: $150.39K - $183.23K)
May 2024: $167.12K (95% CI: $150.51K - $183.72K)
June 2024: $177.60K (95% CI: $160.82K - $194.38K)
July 2024: $174.12K (95% CI: $157.16K - $191.08K)
August 2024: $156.32K (95% CI: $139.19K - $173.46K)
September 2024: $127.92K (95% CI: $110.61K - $145.23K)
October 2024: $117.24K (95% CI: $99.76K - $134.72K)
November 2024: $132.24K (95% CI: $114.60K - $149.89K)
December 2024: $155.07K (95% CI: $137.25K - $172.88K)

The forecasts show expected values for the next 12 months along with 95% confidence intervals. The confidence intervals widen as we forecast further into the future. The forecasts capture both the upward trend and seasonal patterns observed in the historical data.

Out[13]:
Visualization
Time series forecast plot showing historical monthly sales data and SARIMA model predictions for the next 12 months with uncertainty bands.
SARIMA forecasting results showing 12-month-ahead predictions with 95% confidence intervals. Historical sales are shown as a solid indigo line, forecasts as a dashed coral line, and forecast uncertainty as a translucent coral band.

The implementation demonstrates the SARIMA modeling process. We generate realistic sales data with both trend and seasonal components, fit a SARIMA(1,1,1)(1,1,1)12 model, and generate 12-month forecasts with confidence intervals. The model captures both the upward trend and the seasonal patterns.

Key Parameters

Below are some of the main parameters that affect how the SARIMA model works and performs.

  • order: A tuple (p, d, q) specifying the non-seasonal ARIMA parameters. p is the order of the autoregressive part, d is the degree of differencing, and q is the order of the moving average part. Common starting values are (1,1,1) for many time series.

  • seasonal_order: A tuple (P, D, Q, s) specifying the seasonal ARIMA parameters. P is the seasonal autoregressive order, D is the seasonal differencing order, Q is the seasonal moving average order, and s is the seasonal period (e.g., 12 for monthly data with annual seasonality). Start with (1,1,1,12) for monthly data.

  • trend: Optional parameter to include a constant term in the model. Can be 'c' for constant, 't' for linear trend, 'ct' for both, or 'n' for neither. Default is 'c' which includes a constant term.

  • enforce_stationarity: Boolean (default: True) that determines whether to enforce stationarity constraints on autoregressive parameters. Setting to False allows non-stationary models but may lead to unreliable forecasts.

  • enforce_invertibility: Boolean (default: True) that determines whether to enforce invertibility constraints on moving average parameters. Invertibility ensures the model can be expressed in terms of past observations.

  • method: Optimization method for parameter estimation. Options include 'css-ml' (conditional sum of squares then maximum likelihood, default), 'ml' (maximum likelihood), or 'css' (conditional sum of squares). 'css-ml' typically provides good balance between speed and accuracy.

Key Methods

The following are the most commonly used methods for interacting with SARIMA models.

  • fit(): Estimates model parameters using maximum likelihood or conditional sum of squares. Returns a fitted model object that supports parameter inspection, diagnostic checks, and forecasting.

  • forecast(steps): Generates point forecasts for the specified number of steps ahead. Returns a pandas Series with forecasted values.

  • get_forecast(steps): Generates forecasts with confidence intervals. Returns a forecast object with .predicted_mean for point forecasts and .conf_int() for confidence intervals.

  • predict(start, end): Generates in-sample or out-of-sample predictions for specified time periods. Useful for generating predictions on historical data or specific future dates.

  • summary(): Displays a model summary including parameter estimates and their uncertainty, information criteria (AIC, BIC), and diagnostic statistics.