4.2 MGARCH modelling in R
Command | Description |
---|---|
DCCtest() |
testing for non-constant correlations |
dccspec() |
creating a DCC specification object prior to fitting |
dccfit() |
estimating (fitting) specified DCC model |
show() |
displays the results of estimated DCC model (mGARCHfit object) |
fitted() |
produces fitted conditional means |
sigma() |
produces fitted conditional standard deviations |
residuals() |
extracts fitted conditional mean residuals |
dccforecast() |
forecasts the future variances and covariances for h-steps ahead |
infocriteria() |
exctrcts information criteria, such as AIC, BIC,… |
coef() |
displays coefficient vector |
likelihood() |
extracts the joint maximum likelihhod |
plot() |
displys 4 possible plots by selecting numbers from 1 do 4 |
nisurface() |
plots news impact surface |
rcor() |
extracts fitted dynamic conditional correlations |
rcov() |
extracts fitted dynamic conditional covariances |
rshape() |
obtains degrees of freedom from multivariate t–distribution |
rskew() |
obtains skewnees of multivariate t–distribution |
Example 14. Estimate Engle’s DCC(1,1) model to study the time–varying beta coefficient between Tesla’s returns and the S&P500 index. Install and load
In this example estimate parameters μ, ω, α1 and γ1 are interpreted in the same way as in univariate GARCH’s, whereas a1 and b1 are not interpretable but can serve to test the null hypothesis about constant correlations, which is not rejected in this example (p−value=0.40094). This indicates that CCC model is more appropriate despite to significance of parameter b1 and non-significance of parameter a1. However, plot exhibits time–varying correlations which are all positive in the range from 0.21487 to 0.70336. Beta coefficients also varied from 0.86669 to 3.38423, while in the first week of October 2022 recorded values below 1.
rmgarch
package in R for the first time. Download daily prices for both assets, covering the period from “2021-01-01”
to “2024-12-31”
, and compute objects tesla.returns
and sp500.returns
(ensuring that any missing values are removed). Specify univariate GARCH(1,1) models for both Tesla and S&P500 returns, which is necessary before specifying the multivariate DCC–GARCH model (assume univariate as well as multivariate normal distributions). Once the DCC(1,1)–GARCH model is fitted, extract and plot the dynamic conditional correlations. Test the joint null hypothesis H0: a1=b1=0 using DCCtest()
command. Finally, calculate the time–varying beta coefficients by multiplying the dynamic conditional correlation by the ratio of the Tesla and the S&P500 variances. After plotting time–varying beta’s, identify the dates when the beta coefficient was less than or equal to 1, and summarize the beta coefficients using a five–number summary.
Solution
Copy the code lines below to the clipboard, paste them into an R Script file, and run them.In this example estimate parameters μ, ω, α1 and γ1 are interpreted in the same way as in univariate GARCH’s, whereas a1 and b1 are not interpretable but can serve to test the null hypothesis about constant correlations, which is not rejected in this example (p−value=0.40094). This indicates that CCC model is more appropriate despite to significance of parameter b1 and non-significance of parameter a1. However, plot exhibits time–varying correlations which are all positive in the range from 0.21487 to 0.70336. Beta coefficients also varied from 0.86669 to 3.38423, while in the first week of October 2022 recorded values below 1.
# Installing and loading new package "rmgarch"
install.packages("rmgarch")
library(rmgarch) # also requires "rugarch" for univariate GARCH
# Downloading the data for Tesla and S&P500 index
getSymbols(c("TSLA","^GSPC"), # tickers for both equities
src="yahoo", # specifying the source of the data
from = as.Date("2021-01-01"), # starting date in the format "yyyy-mm-dd"
to = as.Date("2024-12-31")) # ending date in the format "yyyy-mm-dd"
# Compute Tesla and S&P500 daily log returns and remove missig values (if any)
<- na.omit(dailyReturn(Cl(TSLA), type = "log"))
tesla.returns <- na.omit(dailyReturn(Cl(GSPC), type = "log"))
sp500.returns
# Merge returns into a single data frame with renamed columns
# Keep only the dates that exist in both returns
<- merge(tesla.returns, sp500.returns, join = "inner")
returns_data colnames(returns_data) <- c("Tesla", "SP500")
# Univariate GARCH(1,1) should be specified in the first step prior to DCC specification
<- ugarchspec(
univariate variance.model = list(model = "sGARCH", garchOrder = c(1, 1)), # standard GARCH(1,1)
mean.model = list(armaOrder = c(0, 0), include.mean = TRUE), # constant mean
distribution.model = "norm") # normal distribution
# Multivariate DCC-GARCH specification in the second step
<- dccspec(
multivariate uspec = multispec(replicate(2, univariate)), # same univariate GARCH for both assets
dccOrder = c(1, 1), # DCC(1,1) order
distribution = "mvnorm") # multivariate normal innovations
# Fitting the DCC(1,1)-GARCH model
<- dccfit(multivariate, data = as.matrix(returns_data))
dcc_fit print(dcc_fit) # display estimation results
# Performing DCC test to check for constant or dynamic correlation
DCCtest(as.matrix(returns_data))
# Extracting dynamic correlations
<- rcor(dcc_fit) # 1004 correlation matrices 2x2
dcc_rho <- dcc_rho[1, 2, ] # extracting off-diagonal elements
rho_t <- xts(rho_t, order.by = index(returns_data))
rho_t colnames(rho_t) <- c("rho")
1:10] # preview first 10 correlations
rho_t[
# Plotting dynamic correlations
library(ggplot2)
ggplot(rho_t, aes(x = Index, y = rho)) +
geom_line(color = "orchid") +
labs(title = "Dynamic correlations between Tesla and S&P500", x = "Days", y = "Correlation") +
theme_minimal()
# Calculating time-varying beta: beta_t = rho_t * (sigma_TSLA / sigma_sp500)
<- sigma(dcc_fit)
sigma index(sigma) <- as.Date(index(sigma))
<- sigma[, "Tesla"] # Tesla volatility
sigma_tesla <- sigma[, "SP500"] # S&P500 volatility
sigma_sp500 <- rho_t * (sigma_tesla / sigma_sp500)
beta_t
# Plotting time-varying betas
colnames(beta_t) <- c("beta")
ggplot(beta_t, aes(x = Index, y = beta)) +
geom_line(color = "orchid") +
labs(title = "Time-varying beta of Tesla", x = "Days", y = "Beta coefficient") +
theme_minimal()
# Finding the dates when beta was less or equal to 1
<= 1]
beta_t[beta_t
# Summarizing beta coefficients
quantile(beta_t) # five-number summary
Example 15. Estimate both a standard (symmetric) and an asymmetric DCC(1,1) model to analyze the dynamic correlation between BitCoin and the S&P500 index. Specify a univariate GJR–GARCH(1,1) models with t–distribution of innovations (with fixed degrees of freedom 5) and use it to specify DCC(1,1) models as objects
multivariate1
and multivariate2
. Estimate two models as dcc_fit1
and dcc_fit2
objects. Extract and plot the time–varying correlations between BitCoin and the S&P500 index based on dcc_fit1
and identify periods where the correlation was zero or negative. Finally, summarize and compare both models using custom–defined tidy.DCCfit
and glance.DCCfit
functions, and present the results using the modelsummary()
command. Plot news impact surface from object dcc_fit2
.
Solution
Copy the code lines below to the clipboard, paste them into an R Script file, and run them.# Downloading the data for BitCoin and S&P500 index starting from January 2020
getSymbols(c("^GSPC","BTC-USD"), # tickers for equity and cryptocurrency
src="yahoo", # specifying the source of the data
from = as.Date("2020-01-01"), # also covers the pandemic period
to = as.Date("2024-12-31"))
# Compute S&P500 and BitCoin daily log returns and removing missing values (if any)
<- na.omit(dailyReturn(Cl(GSPC), type = "log"))
sp500_returns <- na.omit(dailyReturn(Cl(`BTC-USD`), type = "log")) # use backticks `` when there is dash (-) in objects name
bitcoin_returns
# Merge returns into a single data frame with renamed columns
# Keep only the dates that exist in both returns
<- merge(sp500_returns, bitcoin_returns, join = "inner")
returns_data colnames(returns_data) <- c("SP500","BitCoin")
# Estimating one correlation for entire period
cor(returns_data)
# Univariate GARCH(1,1) should be specified in the first step prior do DCC specification
<- ugarchspec(
univariate variance.model = list(model = "sGARCH", garchOrder = c(1, 1)), # standard GARCH(1,1)
mean.model = list(armaOrder = c(0, 0), include.mean = TRUE), # constant mean
distribution.model = "std") # normal distribution of innovations
# Multivariate DCC-GARCH specification in the second step
<- dccspec(
multivariate1 uspec = multispec(replicate(2, univariate)), # same univariate GARCH for both assets
dccOrder = c(1, 1), # DCC(1,1) order
model="DCC", # standard DCC model
distribution = "mvt") # multivariate normal innovations
# Fitting the DCC(1,1)-GARCH model
<- dccfit(multivariate1, data = as.matrix(returns_data))
dcc_fit1 print(dcc_fit1) # Display estimation results
# Extracting dynamic correlations
<- rcor(dcc_fit1) # 1257 correlation matrices 2x2
dcc_rho <- dcc_rho[1, 2, ] # extracting off-diagonal elements
rho_t <- xts(rho_t, order.by = index(returns_data))
rho_t colnames(rho_t) <- c("rho")
1:10] # preview first 10 correlations
rho_t[
# Plotting dynamic correlations
ggplot(rho_t, aes(x = Index, y = rho)) +
geom_line(color = "orchid") +
labs(title = "Dynamic correlations between S&P500 and BitCoin", x = "Days", y = "Correlation") +
theme_minimal()
# Alternative to dynamic correlation plot
plot(dcc_fit1,which=4)
# Covariance can be also plotted
plot(dcc_fit1,which=3)
# Finding the dates when correlation was less or equal to 0
<= 0]
rho_t[rho_t
# Two functions are defined that return two data frames: tidy and glance
# This is required as modelsummary() command does not support MGARCH model
<- function(x, ...) {
tidy.DCCfit<- x@mfit$matcoef
s <- data.frame(
ret term = row.names(s),
estimate = s[, " Estimate"],
std.error = s[, " Std. Error"],
statistic = s[, " t value"],
p.value = s[,"Pr(>|t|)"])
ret
}
<- function(x, ...) {
glance.DCCfit <- x@mfit
s <- data.frame(
ret Likelihood = round(s$llh, digits=2),
Akaike=round(infocriteria(x)[1], digits=4),
Bayes=round(infocriteria(x)[2], digits=4))
ret
}
# Fitting an asymmetric DCC(1,1) model by incorporating univariate GJR-GARCH models
<- ugarchspec(
univariate2 variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)), # asymmetric GARCH(1,1)
mean.model = list(armaOrder = c(0, 0), include.mean = TRUE), # constant mean
distribution.model = "std", # t- distribution of innovations
fixed.pars=list(shape=5))
# Same univariate GARCH for both assets
<- dccspec(uspec = multispec(replicate(2, univariate2)),
multivariate2 dccOrder = c(1, 1), # DCC(1,1) order
model="DCC", # asymmetric DCC model
distribution = "mvt") # multivariate t-distribution
<- dccfit(multivariate2, data = as.matrix(returns_data))
dcc_fit2
modelsummary(list("DCC(1,1) model"=dcc_fit1,"Asymmetric DCC(1,1)"=dcc_fit2),
stars = c('*' = 0.1, '**' = 0.05, '***' = 0.01), # customizing significance levels
fmt=4)
# Plotting news impact surface from object dcc_fit2
nisurface(dcc_fit2)