Predictive Analytics Discussion 3: ARIMA

Setup

### R Environment
  # Clear the workspace
  rm(list = ls()) # Clear environment
  gc()            # Clear unused memory
##          used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
## Ncells 519613 27.8    1149965 61.5         NA   669285 35.8
## Vcells 955384  7.3    8388608 64.0      16384  1840107 14.1
  cat("\f")       # Clear the console
  dev.off         # Clear the charts
## function (which = dev.cur()) 
## {
##     if (which == 1) 
##         stop("cannot shut down device 1 (the null device)")
##     .External(C_devoff, as.integer(which))
##     dev.cur()
## }
## <bytecode: 0x7fedf6a7aec8>
## <environment: namespace:grDevices>
  #make vector containing the packages
  packages <- c("ggplot2",
                "knitr",
                "fpp3",
                "forecast",
                "dplyr",
                "fable")
  #Install packages
  for (i in 1:length(packages)) {# Iterate through each package in the 'packages' vector.
    if (!packages[i] %in% rownames(installed.packages())) {#check if package is installed
      install.packages(packages[i], #install package if it isn't already
                       repos = "http://cran.rstudio.com/",
                       dependencies = TRUE)}
    library(packages[i], character.only = TRUE)} # Load the package into the R session.
## ── Attaching packages ────────────────────────────────────────────── fpp3 0.5 ──
## ✔ tibble      3.2.1     ✔ tsibbledata 0.4.1
## ✔ dplyr       1.1.1     ✔ feasts      0.3.2
## ✔ tidyr       1.3.0     ✔ fable       0.3.3
## ✔ lubridate   1.9.2     ✔ fabletools  0.4.1
## ✔ tsibble     1.1.4
## ── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
## ✖ lubridate::date()    masks base::date()
## ✖ dplyr::filter()      masks stats::filter()
## ✖ tsibble::intersect() masks base::intersect()
## ✖ tsibble::interval()  masks lubridate::interval()
## ✖ dplyr::lag()         masks stats::lag()
## ✖ tsibble::setdiff()   masks base::setdiff()
## ✖ tsibble::union()     masks base::union()
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
  # Remove unnecessary values from environment
  rm(i,packages)

### Data
  # Import the data
  IR <- read.csv("/Users/cam/Desktop/PREDICTIVE ANALYTICS/Discussions/Data/10YR_IR.csv")
  
  # Adjust variable formats where necessary
  IR$DATE <- as.Date(IR$DATE, format = "%m/%d/%y")
  
  IR <- IR %>%
      rename(RATE = REAINTRATREARAT10Y)
  
  ## Separate into training and testing data
  
  # Training
  IR_ts <- subset(IR, DATE <= max(IR$DATE) - months(6))
  
  # testing data
  IR_test <- subset(IR, DATE > max(IR$DATE) - months(6))
  
  # Convert to time series
  IR_ts <- ts(IR_ts$RATE,
              start = c(2014,3),
              frequency = 12
              )
  IR_test <- ts(IR_test$RATE,
                start = c(2023,10),
                frequency = 12
                )

Observing the data - 10-Year Real Interest Rate

Source: FRED - 10YR IR

The dataset used in this discussion comes from FRED and contains monthly data for the past 10 years.

# Show summary stats
  summary(IR)
##       DATE                 RATE        
##  Min.   :2014-03-01   Min.   :-0.4071  
##  1st Qu.:2016-09-01   1st Qu.: 0.3466  
##  Median :2019-03-01   Median : 0.6245  
##  Mean   :2019-03-02   Mean   : 0.6884  
##  3rd Qu.:2021-09-01   3rd Qu.: 1.0606  
##  Max.   :2024-03-01   Max.   : 2.0943
#Show head of table
  head(IR)
##         DATE      RATE
## 1 2014-03-01 0.5804532
## 2 2014-04-01 0.7022221
## 3 2014-05-01 0.6268541
## 4 2014-06-01 0.6245294
## 5 2014-07-01 0.5909950
## 6 2014-08-01 0.6494057
# Show plot of data
  ggplot(IR, aes(x = DATE, y = RATE)) +
    geom_line() +
    labs(x = "Date",
         y = "Real Interest Rate (%)",
         title = "10-Year Real Interest Rate")

Models

ARIMA Model

# Create Arima model

  arima_mod <- auto.arima(IR_ts)
  
  # forecast arima model
  arima_forecast <- forecast(arima_mod, h = 6)
  
  autoplot(arima_mod)

  # Display ETS model
  autoplot(IR_ts)+
    autolayer(arima_forecast)+
    labs(x = "Date",
         y = "Real IR",
         title = "ARIMA Forecast") +
    autolayer(IR_test,
              series = "True Values")

# Evaluate accuracy
  # Make combined df
  arima_data <- arima_forecast$mean
  arima_data <- data.frame(IR_test,arima_data)
  
  
  # Residuals
  arima_data$residuals <- arima_data$IR_test - arima_data$arima_data
  
  # MSE (for )
  MSE_arima <- mean(arima_data$residuals^2)
  
  print(paste("MSE for predictions: ",MSE_arima))
## [1] "MSE for predictions:  0.15235030662069"
  # Summarize the model to ge
  print(summary(arima_mod))
## Series: IR_ts 
## ARIMA(2,0,1) with non-zero mean 
## 
## Coefficients:
##          ar1     ar2     ma1    mean
##       0.1011  0.7996  0.6983  0.7433
## s.e.  0.1556  0.1398  0.1935  0.2785
## 
## sigma^2 = 0.03973:  log likelihood = 23.21
## AIC=-36.43   AICc=-35.88   BIC=-22.7
## 
## Training set error measures:
##                       ME      RMSE       MAE      MPE     MAPE      MASE
## Training set 0.002388211 0.1958325 0.1416181 27.95411 62.24141 0.2826038
##                      ACF1
## Training set -0.002893051

ETS Model

# Create ets model
  ets_mod <- ets(IR_ts)
  
  # forecast ets model
  ets_forecast <- forecast(ets_mod, h = 6)
  
  autoplot(ets_mod)

  # Display ETS model
  autoplot(IR_ts)+
    autolayer(ets_forecast)+
    labs(x = "Date",
         y = "Real IR",
         title = "ETS Forecast") +
    autolayer(IR_test,
              series = "True Values")

# Evaluate accuracy
  # Make combined df
  ets_data <- ets_forecast$mean
  ets_data <- data.frame(IR_test,ets_data)
  
  
  # Residuals
  ets_data$residuals <- ets_data$IR_test - ets_data$ets_data
  
  # MSE (for )
  MSE_ets <- mean(ets_data$residuals^2)
  
  print(paste("MSE for predictions: ",MSE_ets))
## [1] "MSE for predictions:  0.0709431981151992"
  # Summarize the model to ge
  print(summary(ets_mod))
## ETS(A,N,N) 
## 
## Call:
##  ets(y = IR_ts) 
## 
##   Smoothing parameters:
##     alpha = 0.7938 
## 
##   Initial states:
##     l = 0.6023 
## 
##   sigma:  0.2022
## 
##      AIC     AICc      BIC 
## 181.9802 182.1965 190.2150 
## 
## Training set error measures:
##                      ME      RMSE       MAE      MPE     MAPE      MASE
## Training set 0.01169328 0.2004211 0.1430129 30.05544 59.18304 0.2853871
##                     ACF1
## Training set -0.01717967

Conclusion

After examining the two models, it appears that the ANN ETS model was a better predictor for the data. The first thing to note is that it was considerably more accurate than the ARIMA model (ANN: 0.07, ARIMA: 0.15). Second, while both appear to have a negative bias, the scale of said bias is lower for ANN. It should be noted that the data is quite volatile and lacks any clear trend or seasonality. Therefore, a different model aside from these two would be more efficient.