4.1 MGARCH modelling in R

TABLE 4.1: Commands for DCC – multivariate GARCH modelling within package rmgarch
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 df of multivariate t–distribution
rskew() obtains skewnees of multivariate t–distribution
Example 12. text here
Solution Copy the code lines below to the clipboard, paste them into an R Script file, and run them.
# 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"


# Task: Estimate a DCC(1,1) model between Tesla returns and the S&P 500 index
# to study the time-varying beta coefficient.

# Compute Tesla and S&P 500 daily log returns and removing missig values (if any)
tesla_returns <- na.omit(dailyReturn(Cl(TSLA), type = "log"))
sp500_returns <- na.omit(dailyReturn(Cl(GSPC), type = "log"))

# Merge returns into a single dataframe with renamed columns
# Keep only the dates that exist in both returns
returns_data <- merge(tesla_returns, sp500_returns, join = "inner") 
colnames(returns_data) <- c("Tesla", "SP500")

# Univariate GARCH(1,1) should be specified in the first step prior do DCC specification
univariate <- ugarchspec(
  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 of innovations
)

# Multivariate DCC-GARCH specification in the secon step
multivariate <- dccspec(
  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
dcc_fit <- dccfit(multivariate, data = as.matrix(returns_data))
print(dcc_fit) # Display estimation results

# Extracting dynamic correlations
dcc_rho <- rcor(dcc_fit)            # 1004 correlation matrices 2x2
rho_t <- dcc_rho[1, 2, ]            # extracting off-diagonal elements 
rho_t <- xts(rho_t, order.by = index(returns_data))
colnames(rho_t) <- c("rho")
rho_t[1:10]                        # preview first 10 correlations

# Plotting dynamic correlations
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 <- sigma(dcc_fit)
index(sigma) <- as.Date(index(sigma))
sigma_tesla <- sigma[, "Tesla"]    # Tesla volatility
sigma_sp500 <- sigma[, "SP500"]  # S&P500 volatility
beta_t <- rho_t * (sigma_tesla / sigma_sp500)

# 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 betas of Tesla", x = "Days", y = "Beta cofficient") +
  theme_minimal()

# Finding the dates when beta was less or equal to 1
beta_t[beta_t <= 1]

# Summarizing beta coefficients
quantile(beta_t) #  five-number summary

\(~~~\)

Example 13. text here
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)
sp500_returns <- na.omit(dailyReturn(Cl(GSPC), type = "log"))
bitcoin_returns <- na.omit(dailyReturn(Cl(`BTC-USD`), type = "log")) # use backticks `` when there is dash (-) in objects name


# Merge returns into a single dataframe with renamed columns
# Keep only the dates that exist in both returns
returns_data <- merge(sp500_returns, bitcoin_returns, join = "inner") 
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
univariate <- ugarchspec(
  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 of innovations
)

# Multivariate DCC-GARCH specification in the second step
multivariate1 <- dccspec(
  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
dcc_fit1 <- dccfit(multivariate1, data = as.matrix(returns_data))
print(dcc_fit1) # Display estimation results

# Extracting dynamic correlations
dcc_rho <- rcor(dcc_fit1)            # 1257 correlation matrices 2x2
rho_t <- dcc_rho[1, 2, ]            # extracting off-diagonal elements 
rho_t <- xts(rho_t, order.by = index(returns_data))
colnames(rho_t) <- c("rho")
rho_t[1:10]                        # preview first 10 correlations

# 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
rho_t[rho_t <= 0]
sum(rho_t <= 0)/length(rho_t)*100

# Two functions are defined that return two data frames: tidy and glance
# This is required as modelsummary() command does not support MGARCH model
tidy.DCCfit<- function(x, ...) {
  s <- x@mfit$matcoef
  ret <- data.frame(
    term      = row.names(s),
    estimate  = s[, " Estimate"],
    std.error = s[, " Std. Error"],
    statistic = s[, " t value"],
    p.value =  s[,"Pr(>|t|)"])
  ret
}

glance.DCCfit <- function(x, ...) {
  s <- x@mfit
  ret <- data.frame(
    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
univariate2 <- ugarchspec(
  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
multivariate2 <- dccspec(uspec = multispec(replicate(2, univariate2)),
                         dccOrder = c(1, 1),              # DCC(1,1) order
                         model="DCC", # asymmetric DCC model 
                         distribution = "mvt")          # multivariate t-distribution

dcc_fit2 <- dccfit(multivariate2, data = as.matrix(returns_data))
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)

\(~~~\)