R Markdown

library(readxl)
library(forecast)
## Warning: package 'forecast' was built under R version 4.4.3
library(tseries)
## Warning: package 'tseries' was built under R version 4.4.3
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
# Load database
fix_db = read_excel("db_FIX.xlsx")
data = fix_db

# Make sure the date is Date
fix_db$fecha = as.Date(fix_db$fecha)

#Initial visual exploratory analysis
plot(fix_db$fecha, fix_db$fix, type = "l",
     main = "FIX Exchange Rate",
     xlab = "Date",
     ylab = "FIX",
     col = "#0B3C5D",
     lwd = 2)

#Convert to time series 
fix_ts <- ts(fix_db$fix)

#Plot the time series
plot(fix_ts, main = "FIX Exchange Rate Time Series", ylab = "FIX", col = "#1B5886")

#Check stationarity with ADF
adf_original <- adf.test(fix_ts)
adf_original
## 
##  Augmented Dickey-Fuller Test
## 
## data:  fix_ts
## Dickey-Fuller = -2.0711, Lag order = 4, p-value = 0.5462
## alternative hypothesis: stationary

#p-value was > 0.05 thus differencing needs to be applied

fix_diff <- diff(fix_ts)
#Check for stationary again

#With the ADF Test
adf.test(fix_diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  fix_diff
## Dickey-Fuller = -2.3241, Lag order = 4, p-value = 0.4436
## alternative hypothesis: stationary
fix_diff2<-diff(fix_diff)
adf.test(fix_diff2)
## Warning in adf.test(fix_diff2): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  fix_diff2
## Dickey-Fuller = -7.1446, Lag order = 3, p-value = 0.01
## alternative hypothesis: stationary
# Plot differenced data
autoplot(fix_diff2) +
  ggtitle("Differenced Series") +
  xlab("Time") + ylab("Differenced Value")

# 2) Analyze ACF and PACF to identify potential model structures and appropiate lag values

# ACF and PACF
par(mfrow = c(1,2))
acf(fix_diff2, main = "ACF of Differenced Series")
pacf(fix_diff2, main = "PACF of Differenced Series")

par(mfrow = c(1,1))
#Fit candidate models
model1 = arima(fix_ts, order = c(0,2,1))
model2 = arima(fix_ts, order = c(1,2,0))
model3 = arima(fix_ts, order = c(1,2,1))
model4 = arima(fix_ts, order = c(2,2,0))
model5 = arima(fix_ts, order = c(2,2,1))
model6 = arima(fix_ts, order = c(3,2,0))
model7 = arima(fix_ts, order = c(3,2,1))


#Models
model1
## 
## Call:
## arima(x = fix_ts, order = c(0, 2, 1))
## 
## Coefficients:
##           ma1
##       -1.0000
## s.e.   0.1782
## 
## sigma^2 estimated as 0.01388:  log likelihood = 44.7,  aic = -85.4
model2
## 
## Call:
## arima(x = fix_ts, order = c(1, 2, 0))
## 
## Coefficients:
##           ar1
##       -0.4155
## s.e.   0.1151
## 
## sigma^2 estimated as 0.02287:  log likelihood = 30.46,  aic = -56.92
model3
## 
## Call:
## arima(x = fix_ts, order = c(1, 2, 1))
## 
## Coefficients:
##          ar1     ma1
##       0.0164  -1.000
## s.e.  0.1251   0.139
## 
## sigma^2 estimated as 0.01388:  log likelihood = 44.71,  aic = -83.41
model4
## 
## Call:
## arima(x = fix_ts, order = c(2, 2, 0))
## 
## Coefficients:
##           ar1      ar2
##       -0.6062  -0.4981
## s.e.   0.1093   0.1103
## 
## sigma^2 estimated as 0.01736:  log likelihood = 39.14,  aic = -72.27
model5
## 
## Call:
## arima(x = fix_ts, order = c(2, 2, 1))
## 
## Coefficients:
##           ar1      ar2      ma1
##       -0.1103  -0.3170  -0.8285
## s.e.   0.1497   0.1393   0.1240
## 
## sigma^2 estimated as 0.01342:  log likelihood = 46.91,  aic = -85.82
model6
## 
## Call:
## arima(x = fix_ts, order = c(3, 2, 0))
## 
## Coefficients:
##           ar1      ar2      ar3
##       -0.7998  -0.7381  -0.4045
## s.e.   0.1143   0.1214   0.1153
## 
## sigma^2 estimated as 0.01453:  log likelihood = 44.67,  aic = -81.33
model7
## 
## Call:
## arima(x = fix_ts, order = c(3, 2, 1))
## 
## Coefficients:
##           ar1      ar2      ar3      ma1
##       -0.1383  -0.3343  -0.0339  -0.8046
## s.e.   0.2234   0.1726   0.1880   0.1955
## 
## sigma^2 estimated as 0.01342:  log likelihood = 46.93,  aic = -83.85
# Create table of AIC values
model_comparison <- data.frame(
  Model = c("ARIMA(0,2,1)", "ARIMA(1,2,0)", "ARIMA(1,2,1)",
            "ARIMA(2,2,0)", "ARIMA(2,2,1)", "ARIMA(3,2,0)", "ARIMA(3,2,1)"),
  AIC = c(
    AIC(model1),
    AIC(model2),
    AIC(model3),
    AIC(model4),
    AIC(model5),
    AIC(model6),
    AIC(model7)
  )
)
model_comparison
##          Model       AIC
## 1 ARIMA(0,2,1) -85.39553
## 2 ARIMA(1,2,0) -56.91814
## 3 ARIMA(1,2,1) -83.41262
## 4 ARIMA(2,2,0) -72.27435
## 5 ARIMA(2,2,1) -85.81802
## 6 ARIMA(3,2,0) -81.33161
## 7 ARIMA(3,2,1) -83.85167
# Order by AIC (lowest is better)
model_comparison <- model_comparison[order(model_comparison$AIC), ]

print(model_comparison)
##          Model       AIC
## 5 ARIMA(2,2,1) -85.81802
## 1 ARIMA(0,2,1) -85.39553
## 7 ARIMA(3,2,1) -83.85167
## 3 ARIMA(1,2,1) -83.41262
## 6 ARIMA(3,2,0) -81.33161
## 4 ARIMA(2,2,0) -72.27435
## 2 ARIMA(1,2,0) -56.91814
#Do residual diagnosis with Ljung-Box for the best model 
checkresiduals(model5)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(2,2,1)
## Q* = 7.1986, df = 7, p-value = 0.4085
## 
## Model df: 3.   Total lags used: 10
Box.test(model5$residuals, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  model5$residuals
## X-squared = 0.011259, df = 1, p-value = 0.9155
# Forecastinggg
fix_forecast <- forecast(model5, h = 10)
fix_forecast
##    Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
## 68       17.39045 17.24196 17.53893 17.16336 17.61753
## 69       17.32131 17.10479 17.53782 16.99018 17.65244
## 70       17.23547 16.98033 17.49061 16.84527 17.62568
## 71       17.18327 16.88208 17.48446 16.72264 17.64390
## 72       17.13265 16.77658 17.48872 16.58809 17.67722
## 73       17.07120 16.66075 17.48164 16.44347 17.69892
## 74       17.01044 16.54541 17.47546 16.29925 17.72163
## 75       16.95303 16.43066 17.47540 16.15414 17.75193
## 76       16.89504 16.31300 17.47708 16.00489 17.78519
## 77       16.83605 16.19275 17.47935 15.85221 17.81989
plot(fix_forecast, main = "10-Step Forecast for FIX Exchange Rate")