library(tidyverse) # Data manipulation and visualization
library(tidyfinance) # Financial data tools
library(tsibble) # Time series data manipulation
library(feasts) # Time series analysis tools
library(tseries) # Time series analysis
library(broom) # Tidying statistical outputs
library(PortfolioAnalytics) # Portfolio optimization
library(rugarch) # GARCH models
Day 2 Part 1: Simulating Volatility Processes
Zero to Hero Bootcamp - Time Series Econometrics in R
Introduction
In this session, we will simulate various volatility processes using different GARCH models. By specifying and simulating data from these models, we aim to understand how they capture the dynamics of financial time series, particularly the behavior of volatility over time.
Loading Required Libraries
First, we load the necessary R packages that will be used throughout this analysis.
Setting Simulation Parameters
We set the number of observations for our simulations.
<- 1000 # Number of time periods to simulate n_sim
Specifying GARCH Models
We will specify four different GARCH models:
- Standard GARCH (sGARCH)
- GJR-GARCH (gjrGARCH)
- Exponential GARCH (eGARCH)
- Asymmetric Power ARCH (apARCH)
1. Standard GARCH Model
The standard GARCH model, as proposed by Bollerslev (1986), can be mathematically represented as follows:
\sigma_t^2 = \omega + \sum_{j=1}^q \alpha_j \epsilon_{t-j}^2 + \sum_{j=1}^p \beta_j \sigma_{t-j}^2
Where:
- \sigma_t^2: Conditional variance at time t
- \omega: Intercept term
- \alpha_j: Coefficients for lagged error terms (ARCH terms)
- \beta_j: Coefficients for lagged variance terms (GARCH terms)
This model captures volatility clustering, a characteristic often observed in financial time series, where periods of high volatility tend to be followed by more high volatility. We specify a standard GARCH(1,1) model using the ugarchspec
function from the rugarch
package. This model includes an AR(1) term in the mean equation and GARCH(1,1) terms in the variance equation.
<-
s_garch ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(1, 0)),
fixed.pars =
c(
mu = 0.1, # Intercept of the mean equation
ar1 = 0.9, # AR(1) coefficient
omega = 0.1, # Intercept of the variance equation
alpha1 = 0.7, # ARCH coefficient
beta1 = 0.1 # GARCH coefficient
),distribution.model = "norm"
) s_garch
*---------------------------------*
* GARCH Model Spec *
*---------------------------------*
Conditional Variance Dynamics
------------------------------------
GARCH Model : sGARCH(1,1)
Variance Targeting : FALSE
Conditional Mean Dynamics
------------------------------------
Mean Model : ARFIMA(1,0,0)
Include Mean : TRUE
GARCH-in-Mean : FALSE
Conditional Distribution
------------------------------------
Distribution : norm
Includes Skew : FALSE
Includes Shape : FALSE
Includes Lambda : FALSE
2. GJR-GARCH Model
The GJR-GARCH model, introduced by Glosten, Jagannathan, and Runkle (1993), extends the standard GARCH model by allowing for asymmetry in the volatility response to positive and negative shocks. The model is represented by:
\sigma_t^2 = \omega + \sum_{j=1}^q \left( \alpha_j \epsilon_{t-j}^2 + \gamma_j I(\epsilon_{t-j} < 0) \epsilon_{t-j}^2 \right) + \sum_{j=1}^p \beta_j \sigma_{t-j}^2
Where:
- \gamma_j: Represents the leverage effect, capturing the impact of negative shocks
- I(\epsilon_{t-j} < 0): Indicator function that equals 1 if the lagged error term is negative, otherwise 0
This model allows volatility to react differently to positive and negative shocks, which is often observed in financial markets (e.g., bad news tends to increase volatility more than good news). We specify the GJR-GARCH model as follows:
<-
gjr_garch ugarchspec(
variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(1, 0)),
fixed.pars =
c(
mu = 0.1, # Intercept of the mean equation
ar1 = 0.9, # AR(1) coefficient
omega = 0.1, # Intercept of the variance equation
alpha1 = 0.5, # ARCH(1) coefficient
beta1 = 0.1, # GARCH(1) coefficient
gamma1 = 0.1 # Asymmetry term
),distribution.model = "norm"
) gjr_garch
*---------------------------------*
* GARCH Model Spec *
*---------------------------------*
Conditional Variance Dynamics
------------------------------------
GARCH Model : gjrGARCH(1,1)
Variance Targeting : FALSE
Conditional Mean Dynamics
------------------------------------
Mean Model : ARFIMA(1,0,0)
Include Mean : TRUE
GARCH-in-Mean : FALSE
Conditional Distribution
------------------------------------
Distribution : norm
Includes Skew : FALSE
Includes Shape : FALSE
Includes Lambda : FALSE
3. Exponential GARCH Model
The Exponential GARCH (eGARCH) model, proposed by Nelson (1991), captures leverage effects by modeling the logarithm of the conditional variance:
\log(\sigma_t^2) = \omega + \sum_{j=1}^q \left( \alpha_j z_{t-j} + \gamma_j (|z_{t-j}| - E|z_{t-j}|) \right) + \sum_{j=1}^p \beta_j \log(\sigma_{t-j}^2)
Where:
- z_t: Standardized residuals
- \alpha_j: Captures the sign effect (impact of positive/negative shocks)
- \gamma_j: Captures the size effect (impact of the magnitude of shocks)
This model naturally ensures positive variance without requiring parameter restrictions and effectively models asymmetric volatility. We specify the eGARCH model as follows:
<-
e_garch ugarchspec(
variance.model = list(model = "eGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(1, 0)),
fixed.pars =
c(
mu = 0.1, # Intercept of the mean equation
ar1 = 0.9, # AR(1) coefficient
omega = 0.1, # Intercept of the variance equation
alpha1 = 0.5, # ARCH(1) coefficient
beta1 = 0.4, # GARCH(1) coefficient
gamma1 = 0.1 # Leverage term
),distribution.model = "norm"
) e_garch
*---------------------------------*
* GARCH Model Spec *
*---------------------------------*
Conditional Variance Dynamics
------------------------------------
GARCH Model : eGARCH(1,1)
Variance Targeting : FALSE
Conditional Mean Dynamics
------------------------------------
Mean Model : ARFIMA(1,0,0)
Include Mean : TRUE
GARCH-in-Mean : FALSE
Conditional Distribution
------------------------------------
Distribution : norm
Includes Skew : FALSE
Includes Shape : FALSE
Includes Lambda : FALSE
4. Asymmetric Power ARCH Model
The Asymmetric Power ARCH (apARCH) model, introduced by Ding, Granger, and Engle (1993), allows for both leverage and power effects in the volatility equation:
\sigma_t^\delta = \omega + \sum_{j=1}^q \alpha_j (|\epsilon_{t-j}| - \gamma_j \epsilon_{t-j})^\delta + \sum_{j=1}^p \beta_j \sigma_{t-j}^\delta
Where:
- \delta: Power parameter, allowing for flexibility in modeling the distribution of volatility
- \gamma_j: Leverage term, similar to the GJR-GARCH model
This model captures the observed behavior where volatility can respond asymmetrically to past shocks and allows for different power transformations of volatility. We specify the apARCH model as follows:
<-
ap_arch ugarchspec(
variance.model = list(model = "apARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(1, 0)),
fixed.pars =
c(
mu = 0.1, # Intercept of the mean equation
ar1 = 0.9, # AR(1) coefficient
omega = 0.1, # Intercept of the variance equation
alpha1 = 0.5, # ARCH(1) coefficient
beta1 = 0.4, # GARCH(1) coefficient
gamma1 = 0.1, # Asymmetry term
delta = 1 # Power parameter
),distribution.model = "norm"
) ap_arch
*---------------------------------*
* GARCH Model Spec *
*---------------------------------*
Conditional Variance Dynamics
------------------------------------
GARCH Model : apARCH(1,1)
Variance Targeting : FALSE
Conditional Mean Dynamics
------------------------------------
Mean Model : ARFIMA(1,0,0)
Include Mean : TRUE
GARCH-in-Mean : FALSE
Conditional Distribution
------------------------------------
Distribution : norm
Includes Skew : FALSE
Includes Shape : FALSE
Includes Lambda : FALSE
Compiling the Model Specifications
We compile all the model specifications into a list for easy reference and manipulation.
<-
volatility_specs list(
s_garch = s_garch,
gjr_garch = gjr_garch,
e_garch = e_garch,
ap_arch = ap_arch
)
Simulating Data from the GARCH Models
We simulate time series data from each of the specified GARCH models and combine the results into a single data frame.
<-
sim_data map(
names(volatility_specs),
function(model_name) {
<- volatility_specs[[model_name]]
spec <- ugarchpath(spec = spec, n.sim = n_sim)
simulation tibble(
time = 1:n_sim,
series = as.numeric(simulation@path$seriesSim),
sigma = as.numeric(simulation@path$sigmaSim),
model = model_name
)
}%>%
) list_rbind()
sim_data
# A tibble: 4,000 × 4
time series sigma model
<int> <dbl> <dbl> <chr>
1 1 0.0549 0.387 s_garch
2 2 0.144 0.341 s_garch
3 3 -0.319 0.341 s_garch
4 4 -1.08 0.509 s_garch
5 5 -1.74 0.760 s_garch
6 6 -0.459 0.765 s_garch
7 7 -0.120 1.00 s_garch
8 8 0.651 0.507 s_garch
9 9 0.363 0.720 s_garch
10 10 -0.197 0.436 s_garch
# ℹ 3,990 more rows
Visualizing the Simulated Data
We visualize the simulated series and their corresponding volatilities for each model.
%>%
sim_data pivot_longer(c(series, sigma)) %>%
ggplot(aes(time, value, color = model)) +
geom_line() +
facet_wrap(~name, scales = "free", ncol=2) +
theme(legend.position = "bottom")
Figure: Simulated time series and volatility from different GARCH models.
Analyzing the Volatility Processes
To further understand the volatility processes generated by each model, we will examine the time series properties of the volatility series.
Defining a Plotting Function
We define a function plot_tsdisplay
that creates time series plots along with the autocorrelation function (ACF) and partial autocorrelation function (PACF) for the volatility series.
<-
plot_tsdisplay function(model_name) {
%>%
sim_data filter(model == model_name) %>%
as_tsibble(index = time) %>%
gg_tsdisplay(sigma, plot_type = "partial")
}
Analyzing Each Model
Standard GARCH Model
plot_tsdisplay("s_garch")
GJR-GARCH Model
plot_tsdisplay("gjr_garch")
Exponential GARCH Model
plot_tsdisplay("e_garch")
Asymmetric Power ARCH Model
plot_tsdisplay("ap_arch")
Figures: Time series, ACF, and PACF plots of the volatility series for each GARCH model.
Conclusion
In this exercise, we simulated and analyzed different GARCH models to understand how they capture volatility in time series data. By comparing the simulated series and their volatility processes, we observed the characteristics and differences among the models. This hands-on approach enhances our understanding of volatility modeling in financial econometrics.