R code: Estimation and Forecasting of GARCH Volatility model

This post uses rugarch R package for estimating GARCH model to obtain conditional volatility estimates. This R package also provides various extended versions of GARCH model such as EGARCH, GJR-GARCH, to name a few.

James Webb Space Telescope captures a spooky view of the Pillars of Creation


Generalised Autoregressive Conditional Heteroskedasticity model



Bollerslev (1986) proposed the GARCH model which estimates the conditional volatility of time series. Many textbook on time series analysis or econometrics deal with this important model at the neighborhood of Chapter 6 (in the middle part of that book).


GARCH model


The standard GARCH model (Bollerslev, 1986) formulates the conditional variance (\(\sigma_t^2\)) of a stochastic error term (\(\epsilon_t\)) as follows.

\[\begin{align} \epsilon_t &= \sigma_t Z_t \\ \sigma_t^2 &= \text{Var}[\epsilon_t| \mathcal{F}_{t-1}] \\ &= \omega + \sum_{i=1}^{q} \alpha_i \epsilon_{t-i}^2 + \sum_{i=1}^{p} \beta_i \sigma_{t-i}^2 \\ &= \text{GARCH}(p,q) \end{align}\]
where \(E[\epsilon_t| \mathcal{F}_{t-1}] = 0\) and \({F}_{t-1}\) means all the information available at time \(t\). \(Z_t\) is a white noise with mean zero and variance 1.

The conditional distribution of \(\epsilon_t| \mathcal{F}_{t-1}\) is assumed to be normal. Of course, other distributions can be applied.

The standard GARCH model is about an error term and this means a mean constant zero. However, the conditional mean is appropriate in many cases. For this purpose, ARMA-GARCH model is used.

\[\begin{align} &y_t - c - \sum_{i=1}^{r} \phi_i y_{t-i} - \sum_{i=1}^{m} \theta_i \epsilon_{t-i} = \epsilon_t \\ & \epsilon_t = \sigma_t Z_t \\ &\sigma_t^2 = \text{GARCH}(p,q) \end{align}\]

Beautiful Graphs from output of ugarchfit()


rugarch R package provides so nice looking figures when we plot just the results of the ugarchfit() fitting function. There are 12 figures, and we can select one by its number or all by "all" option.


Plot Selection by Number

  • 1: Series with 2 Conditional SD Superimposed
  • 2 Series with 1% VaR Limits
  • 3: Conditional SD (vs |returns|)
  • 4: ACF of Observations
  • 5: ACF of Squared Observations
  • 6: ACF of Absolute Observations
  • 7: Cross Correlation
  • 8: Empirical Density of Standardized Residuals
  • 9: QQ-Plot of Standardized Residuals
  • 10: ACF of Standardized Residuals
  • 11: ACF of Squared Standardized Residuals
  • 12: News-Impact Curve
  • "all": All Plots


Data


Data is the S&P 500 index return (S&P 500 ETF Trust) as follows.
R code: Estimation and Forecasting of GARCH Volatility model

R code


The following R code uses rugarch R package to estimate ARMA(1,1)-GARCH(1,1)-Normal model using ugarchfit() function and performs return and conditional volatility forecasts using ugarchforecast() function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#========================================================#
# Quantitative Financial Econometrics & Derivatives 
# Machine/Deep Learing, R, Python, Tensorflow 
# by Sang-Heon Lee 
#
# https://shleeai.blogspot.com
#--------------------------------------------------------#
# GARCH model
#========================================================#
 
graphics.off(); rm(list = ls())
 
library(quantmod)
library(rugarch)
 
#===========================================
# Data
#===========================================
 
# S&P 500 index
getSymbols("SPY",from="2007/01/01")
df <- data.frame(
    as.Date(index(SPY)), 
    SPY$SPY.Adjusted, 
    diff(log(SPY$SPY.Adjusted)))
rownames(df) <- NULL
colnames(df) <- c("dt""pr""rt")
head(df)
      
# zoo type
zf <- read.zoo(df)
 
# draw data             
x11(); plot(zf, xlab = "date", main = "S&P 500"
            ylab = c("Index""Return"), col=c(4,3))
 
 
#===========================================
# ARMA(1,1)-GARCH(1,1)-Normal distribution
#===========================================
 
# default specification : ARMA(1,1)-GARCH(1,1)-N
# mod_spec = ugarchspec()
 
# same specification : ARMA(1,1)-GARCH(1,1)-N
mod_spec = ugarchspec(
    variance.model=list(model="sGARCH",garchOrder=c(1,1)),
    mean.model=list(armaOrder=c(1,1), include.mean=TRUE),
    distribution.model="norm"
)
 
# GARCH Estimation
mod_fit = ugarchfit(spec = mod_spec, data = zf$rt[-1])
mod_fit
 
# draw all the estimated results
x11(width = 9, height=7); plot(mod_fit, which = "all")
 
# draw conditional variance
x11(width = 7, height=5); plot(mod_fit, which = 3)
 
# Extract estimated coefficients
mod_fit@fit$coef
 
# estimated conditional variances
convar <- mod_fit@fit$var
 
# estimated squared residuals 
res2 <- (mod_fit@fit$residuals)^2
 
#plot squared residuals and conditional variance
x11(); plot(res2, type = "l",col="darkgray",
    xlab="Index", ylab ="Residuals & Variance", lwd=2
lines(convar, col = "blue", lwd=1)
 
 
#===========================================
# Forecast conditional volatility
#===========================================
 
# run forecasting
mod_fcst <- ugarchforecast(mod_fit, n.ahead = 500)
 
# read return forecast
mod_fcst_ret <- as.vector(mod_fcst@forecast$seriesFor)
 
temp <- data.frame(
    fcst_cvol = as.vector(merge(tail(zf$rt,100), 
                head(mod_fcst_ret,100)))
)
temp$fit_cvol = temp$fcst_cvol
temp$fit_cvol[102:nrow(temp)] <- NA
 
# draw return forecast with data
x11(width = 7, height=5
matplot(temp, type = "l", lty = 1, lwd = 3
        ylab="Return", col = c(4,2),
        main = paste0("ARMA(1,1)-GARCH(1,1)-Normal : "
                      "Conditional Mean Forecast"))
 
# read sigma forecast
mod_fcst_cvol <- as.vector(mod_fcst@forecast$sigmaFor)
 
# read sigma fitted
mod_fit_cvol <- as.vector(mod_fit@fit$sigma)
 
temp <- data.frame(
    fcst_cvol = c(mod_fit_cvol, mod_fcst_cvol),
    fit_cvol  = c(mod_fit_cvol, mod_fcst_cvol[1], 
                  mod_fcst_cvol[-1]*NA))
 
# draw conditional volatility forecast with fitted values
x11(width = 7, height=5)
matplot(temp, type = "l", lty = 1, lwd = 3,
        ylab="Volatility", col = c(4,2),
        main = paste0("ARMA(1,1)-GARCH(1,1)-Normal : "
                      "Conditional Volatility Forecast"))
 
cs


After running the above R code, we can draw summary plots of GARCH estimation with which = "all" option. It's very nice.

R code: Estimation and Forecasting of GARCH Volatility model

we can also draw a plot of the estimated conditional volatility with which = 3 option.
R code: Estimation and Forecasting of GARCH Volatility model

Estimation results of GARCH model consist of parameter estimates, its statistical significances, and some test statistics including Ljung-Box, ARCH-LM test, and so on. These test statistics are academic so that you can learn how to interpret these statistics with the help of some famous financial time series textbooks such as Applied Econometric Time Series - Walter Enders.

R code: Estimation and Forecasting of GARCH Volatility model


Forecast


By using ugarchforecast() function, we can obtain two forecasting results of mean and conditional volatility. First, due to the small forecasted range of s, the return forecasts with recent period are shown as follows.
R code: Estimation and Forecasting of GARCH Volatility model

Second, as volatility range is not so small, we don't have to magnify some part of sample period. The conditional volatility forecasts with the whole sample are shown as follows.
R code: Estimation and Forecasting of GARCH Volatility model


Concluding Remarks


This post introduces rugarch R package to estimate the famous GARCH model. This package also provides a variety of extended GARCH models, and you can find them in the rugarch manual. \(\blacksquare\)


No comments:

Post a Comment