Introduction to arimasel: Cartesian Product ARIMA Model Selection

1. Motivation

The Box-Jenkins methodology remains the dominant framework for univariate time series modelling. Its classical identification step relies on the Autocorrelation Function (ACF) and Partial Autocorrelation Function (PACF) plots. However, these plots often present conflicting or ambiguous pictures, particularly for mixed ARIMA(p,d,q) models, making reliable identification difficult in practice.

The arimasel package proposes an alternative algorithm grounded in the mathematical theory of Cartesian products of sets. Rather than examining ACF/PACF plots or using stepwise search (as in auto.arima), the algorithm:

  1. Accepts user-defined index sets \(P\), \(D\), and \(Q\).
  2. Computes the Cartesian product \(P \times D \times Q\).
  3. Fits every ARIMA\((p,d,q)\) triple exhaustively.
  4. Ranks all converged models by four information criteria simultaneously: AIC, AICc, BIC, and HQIC.
  5. Quantifies model uncertainty via Akaike weights.
  6. Supports best-model and ensemble forecasting.

2. Enumerating Candidates with cp_sets()

cp_sets(p_set = 0:2, d_set = 0:1, q_set = 0:2)
#> Cartesian Product  P x D x Q
#>   P = {0, 1, 2}
#>   D = {0, 1}
#>   Q = {0, 1, 2}
#>   |P| x |D| x |Q| = 3 x 2 x 3 = 18 candidate model(s)
#> 
#> Candidate ARIMA models:
#> ARIMA(0,0,0)  ARIMA(0,0,1)  ARIMA(0,0,2)  ARIMA(1,0,0)  ARIMA(1,0,1)  ARIMA(1,0,2)  ARIMA(2,0,0)  ARIMA(2,0,1)  ARIMA(2,0,2)  ARIMA(0,1,0)  ARIMA(0,1,1)  ARIMA(0,1,2)  ARIMA(1,1,0)  ARIMA(1,1,1)  ARIMA(1,1,2)  ARIMA(2,1,0)  ARIMA(2,1,1)  ARIMA(2,1,2)

The function confirms \(|P| \times |D| \times |Q| = 3 \times 2 \times 3 = 18\) candidate models.

3. Data

The package ships with three Nigerian macroeconomic time series.

data(gdp_ng)
data(exchange_ng)
data(inflation_ng)

par(mfrow = c(1, 3), mar = c(4, 4, 3, 1))
plot(gdp_ng,      main = "GDP Growth (%)",    ylab = "%")
plot(exchange_ng, main = "USD/NGN Rate",      ylab = "NGN")
plot(inflation_ng,main = "CPI Inflation (%)", ylab = "%")

par(mfrow = c(1, 1))

4. Pre-screening: Stationarity and Differencing

stationarity_test(gdp_ng)
#> Registered S3 method overwritten by 'quantmod':
#>   method            from
#>   as.zoo.data.frame zoo
#> Warning in tseries::kpss.test(x_vec): p-value greater than printed p-value
#> 
#> Stationarity Test Battery  (alpha = 0.05)
#> n = 34 observations
#> 
#>                   Test Statistic p_value     Conclusion
#>    ADF (H0: unit root)   -1.8808  0.1795 Non-stationary
#>     PP (H0: unit root)  -15.0002  0.1639 Non-stationary
#>  KPSS (H0: stationary)    0.1995  0.1000     Stationary
#> 
#> Consensus : Non-stationary  |  Suggested d : 1
#>                    Test Statistic p_value     Conclusion
#> 1   ADF (H0: unit root)   -1.8808  0.1795 Non-stationary
#> 2    PP (H0: unit root)  -15.0002  0.1639 Non-stationary
#> 3 KPSS (H0: stationary)    0.1995  0.1000     Stationary
d_rec <- suggest_d(gdp_ng)
cat("Recommended d:", d_rec, "\n")
#> Recommended d: 2

5. Cartesian Product ARIMA Selection

result <- cart_arima(gdp_ng,
                     p_set     = 0:3,
                     d_set     = 0:1,
                     q_set     = 0:3,
                     criterion = "AIC",
                     top_n     = 10L)
print(result)
#> 
#> Cartesian Product ARIMA Model Selection
#> =========================================
#> Call      : cart_arima(x = gdp_ng, p_set = 0:3, d_set = 0:1, q_set = 0:3, 
#>  Call      :     criterion = "AIC", top_n = 10L)
#> Obs (n)   : 34
#> Candidates: 32  |  Converged: 32  |  Failed: 0
#> Criterion : AIC
#> Best model: ARIMA(0,1,0)
#> 
#> Top 10 models (ranked by AIC):
#>  Rank        Model AIC AICc BIC HQIC Delta Weight
#>     1 ARIMA(0,1,0) 155  155 156  155 0.000 0.1381
#>     2 ARIMA(1,1,1) 155  156 159  156 0.053 0.1345
#>     3 ARIMA(0,1,1) 155  156 158  156 0.576 0.1036
#>     4 ARIMA(0,1,2) 156  156 160  157 1.012 0.0833
#>     5 ARIMA(1,1,0) 156  156 159  157 1.267 0.0733
#>     6 ARIMA(2,1,0) 156  157 161  158 1.381 0.0692
#>     7 ARIMA(1,0,0) 157  157 161  158 1.899 0.0534
#>     8 ARIMA(2,1,1) 157  158 163  159 2.052 0.0495
#>     9 ARIMA(1,1,2) 157  158 163  159 2.052 0.0495
#>    10 ARIMA(0,1,3) 158  159 164  160 2.998 0.0309
summary(result)
#> 
#> === arimasel: Cartesian Product ARIMA Summary ===
#> 
#> Call: cart_arima(x = gdp_ng, p_set = 0:3, d_set = 0:1, q_set = 0:3, 
#> 
#>  Call:     criterion = "AIC", top_n = 10L)
#> 
#> Search space:
#>   P = {0,1,2,3}, D = {0,1}, Q = {0,1,2,3}
#>   Total candidates: 32  |  Converged: 32
#> 
#> Best model by primary criterion:
#>   ARIMA(0,1,0)  (criterion: AIC)
#> 
#> Criterion vote table:
#>         Model Votes          Criteria
#>  ARIMA(0,1,0)     4 AIC/AICc/BIC/HQIC
#> 
#> Top 10 model comparison:
#>         Model p d q LogLik AIC AICc BIC HQIC Rank Delta Weight
#>  ARIMA(0,1,0) 0 1 0  -76.3 155  155 156  155    1 0.000 0.1381
#>  ARIMA(1,1,1) 1 1 1  -74.4 155  156 159  156    2 0.053 0.1345
#>  ARIMA(0,1,1) 0 1 1  -75.6 155  156 158  156    3 0.576 0.1036
#>  ARIMA(0,1,2) 0 1 2  -74.8 156  156 160  157    4 1.012 0.0833
#>  ARIMA(1,1,0) 1 1 0  -76.0 156  156 159  157    5 1.267 0.0733
#>  ARIMA(2,1,0) 2 1 0  -75.0 156  157 161  158    6 1.381 0.0692
#>  ARIMA(1,0,0) 1 0 0  -75.3 157  157 161  158    7 1.899 0.0534
#>  ARIMA(2,1,1) 2 1 1  -74.4 157  158 163  159    8 2.052 0.0495
#>  ARIMA(1,1,2) 1 1 2  -74.4 157  158 163  159    9 2.052 0.0495
#>  ARIMA(0,1,3) 0 1 3  -74.8 158  159 164  160   10 2.998 0.0309
#> 
#> Best model coefficients:
#> numeric(0)
#> 
#> sigma^2: 5.9821  |  Log-likelihood: -76.340

6. Re-ranking by Different Criteria

arima_table(result, criterion = "BIC", top_n = 5)
#>          Model p d q  LogLik     AIC    AICc     BIC    HQIC Rank Delta Weight
#> 1 ARIMA(0,1,0) 0 1 0 -76.340 154.680 154.805 156.206 155.200    1 0.000 0.4281
#> 2 ARIMA(0,1,1) 0 1 1 -75.628 155.256 155.643 158.309 156.297    2 2.103 0.1496
#> 3 ARIMA(1,1,0) 1 1 0 -75.974 155.947 156.334 159.000 156.988    3 2.794 0.1059
#> 4 ARIMA(1,1,1) 1 1 1 -74.366 154.733 155.533 159.312 156.294    4 3.106 0.0906
#> 5 ARIMA(0,1,2) 0 1 2 -74.846 155.692 156.492 160.271 157.253    5 4.065 0.0561

7. Akaike Weights

ic_vals <- setNames(result$full_table$AIC,
                    result$full_table$Model)
arima_weights(ic_vals[1:6])
#>          Model IC_value Delta Weight EvidenceRatio
#> 1 ARIMA(0,1,0)  154.680 0.000 0.2294          1.00
#> 2 ARIMA(1,1,1)  154.733 0.053 0.2234          1.03
#> 3 ARIMA(0,1,1)  155.256 0.576 0.1720          1.33
#> 4 ARIMA(0,1,2)  155.692 1.012 0.1383          1.66
#> 5 ARIMA(1,1,0)  155.947 1.267 0.1218          1.88
#> 6 ARIMA(2,1,0)  156.061 1.381 0.1150          1.99

8. Criterion Vote Table

result$vote_table
#>          Model Votes          Criteria
#> 1 ARIMA(0,1,0)     4 AIC/AICc/BIC/HQIC

9. Visualising the Results

plot(result, type = "criteria", top_n = 8)

plot(result, type = "weights", top_n = 8)

plot(result, type = "surface", criterion = "AIC")

plot(result, type = "fitted")

10. Residual Diagnostics

arima_diagnose(result, lags = 15)
#> 
#> Residual diagnostics for ARIMA(0,1,0)
#> n (residuals) = 34
#> sigma^2 = 5.9821
#> Shapiro-Wilk: W = 0.9839, p-value = 0.8859  [Cannot reject normality]
#> Ljung-Box: No significant autocorrelation detected (alpha = 0.05).

11. Forecasting

11.1 Best-model forecast

fc <- arima_forecast(result, h = 8, level = c(80, 95), plot = TRUE)

cat("Point forecasts:\n")
#> Point forecasts:
round(fc$mean, 2)
#> [1] 2.9 2.9 2.9 2.9 2.9 2.9 2.9 2.9

11.2 Ensemble forecast

fc_ens <- arima_forecast(result, h = 8, ensemble = TRUE,
                         top_k = 4L, plot = TRUE)

12. Monthly Series: Exchange Rate

res_ex <- cart_arima(exchange_ng,
                     p_set = 0:2, d_set = 1L, q_set = 0:2,
                     criterion = "BIC")
print(res_ex)
#> 
#> Cartesian Product ARIMA Model Selection
#> =========================================
#> Call      : cart_arima(x = exchange_ng, p_set = 0:2, d_set = 1L, q_set = 0:2, 
#>  Call      :     criterion = "BIC")
#> Obs (n)   : 168
#> Candidates: 9  |  Converged: 9  |  Failed: 0
#> Criterion : BIC
#> Best model: ARIMA(0,1,0)
#> 
#> Top 9 models (ranked by BIC):
#>  Rank        Model  AIC AICc  BIC HQIC Delta Weight
#>     1 ARIMA(0,1,0) 1624 1624 1627 1625  0.00 0.8478
#>     2 ARIMA(0,1,1) 1626 1626 1632 1628  5.10 0.0661
#>     3 ARIMA(1,1,0) 1626 1626 1632 1628  5.11 0.0660
#>     4 ARIMA(0,1,2) 1627 1627 1637 1631  9.67 0.0068
#>     5 ARIMA(2,1,0) 1627 1627 1637 1631  9.68 0.0067
#>     6 ARIMA(1,1,1) 1628 1628 1637 1631 10.03 0.0056
#>     7 ARIMA(1,1,2) 1629 1629 1642 1634 14.79 0.0005
#>     8 ARIMA(2,1,1) 1629 1629 1642 1634 14.80 0.0005
#>     9 ARIMA(2,1,2) 1631 1632 1647 1638 19.91 0.0000
arima_forecast(res_ex, h = 12, plot = TRUE)

13. Comparing with auto.arima

compare_arima(gdp_ng, p_set = 0:3, d_set = 0:1, q_set = 0:3,
              holdout = 5L)
#> Fitting cart_arima...
#> Fitting auto.arima...
#> 
#> --- Model Comparison ---
#>      Method        Model AIC AICc BIC HQIC OOS_RMSE OOS_MAE
#>  cart_arima ARIMA(0,1,0) 129  129 131  130     2.07    1.84
#>  auto.arima ARIMA(1,0,0) 133  134 137  134     2.24    1.53
#> 
#> Winner (most metric wins): cart_arima

14. Summary

The arimasel package provides a transparent, exhaustive, multi-criteria approach to ARIMA model identification. Key advantages over stepwise methods:

  • Exhaustive: every \((p,d,q)\) in the Cartesian product is evaluated.
  • Multi-criteria: simultaneous ranking by AIC, AICc, BIC, and HQIC.
  • Uncertainty quantification: Akaike weights and evidence ratios.
  • Ensemble forecasting: weighted averaging across top-\(k\) models.
  • Reproducible: fully deterministic given the input sets.

References

Awe, O. O. (2026). arimasel: Cartesian Product-Based ARIMA Model Identification and Selection. R package version 0.1.0.

Akaike, H. (1974). A new look at the statistical model identification. IEEE Transactions on Automatic Control, 19(6), 716–723.

Box, G. E. P., Jenkins, G. M., Reinsel, G. C., and Ljung, G. M. (2015). Time Series Analysis: Forecasting and Control (5th ed.). John Wiley & Sons.

Burnham, K. P. and Anderson, D. R. (2002). Model Selection and Multimodel Inference: A Practical Information-Theoretic Approach (2nd ed.). Springer.

Hannan, E. J. and Quinn, B. G. (1979). The determination of the order of an autoregression. Journal of the Royal Statistical Society, Series B, 41(2), 190–195.