In this vignette, we demonstrate the copula GARCH approach (in
general). Note that a special case (with normal or student t residuals) is also available in
the rmgarch
package (thanks to Alexios Ghalanos for
pointing this out).
First, we simulate the innovation distribution. Note that, for demonstration purposes, we choose a small sample size. Ideally, the sample size should be larger to capture GARCH effects.
## Simulate innovations
n <- 200 # sample size
d <- 2 # dimension
nu <- 3 # degrees of freedom for t
tau <- 0.5 # Kendall's tau
th <- iTau(ellipCopula("t", df = nu), tau) # corresponding parameter
cop <- ellipCopula("t", param = th, dim = d, df = nu) # define copula object
set.seed(271) # reproducibility
U <- rCopula(n, cop) # sample the copula
nu. <- 3.5 # degrees of freedom for the t margins
Z <- sqrt((nu.-2)/nu.) * qt(U, df = nu.) # margins must have mean 0 and variance 1 for ugarchpath()!
Now we simulate two ARMA(1,1)-GARCH(1,1) processes with these copula-dependent innovations. To this end, recall that an ARMA(p1,q1)-GARCH(p2,q2) model is given by
## Fix parameters for the marginal models
fixed.p <- list(mu = 1,
ar1 = 0.5,
ma1 = 0.3,
omega = 2, # alpha_0 (conditional variance intercept)
alpha1 = 0.4,
beta1 = 0.2)
meanModel <- list(armaOrder = c(1,1))
varModel <- list(model = "sGARCH", garchOrder = c(1,1)) # standard GARCH
uspec <- ugarchspec(varModel, mean.model = meanModel,
fixed.pars = fixed.p) # conditional innovation density (or use, e.g., "std")
## Simulate ARMA-GARCH models using the dependent innovations
## Note: ugarchpath(): simulate from a spec; ugarchsim(): simulate from a fitted object
X <- ugarchpath(uspec,
n.sim = n, # simulated path length
m.sim = d, # number of paths to simulate
custom.dist = list(name = "sample", distfit = Z)) # passing (n, d)-matrix of *standardized* innovations
## Extract the resulting series
X. <- fitted(X) # X_t = mu_t + eps_t (simulated process)
sig.X <- sigma(X) # sigma_t (conditional standard deviations)
eps.X <- X@path$residSim # epsilon_t = sigma_t * Z_t (residuals)
## Basic sanity checks :
stopifnot(all.equal(X., X@path$seriesSim, check.attributes = FALSE),
all.equal(sig.X, X@path$sigmaSim, check.attributes = FALSE),
all.equal(eps.X, sig.X * Z, check.attributes = FALSE))
## Plot (X_t) for each margin
matplot(X., type = "l", xlab = "t", ylab = expression(X[t]~"for each margin"))
We now show how to fit an ARMA(1,1)-GARCH(1,1) process to
X
(we remove the argument fixed.pars
from the
above specification for estimating these parameters):
uspec <- ugarchspec(varModel, mean.model = meanModel, distribution.model = "std")
fit <- apply(X., 2, function(x) ugarchfit(uspec, data = x))
Check the (standardized) Z
, i.e., the
pseudo-observations of the residuals Z
:
Z. <- sapply(fit, residuals, standardize = TRUE)
U. <- pobs(Z.)
par(pty = "s")
plot(U., xlab = expression(hat(U)[1]), ylab = expression(hat(U)[2]))
Fit a t copula to the
standardized residuals Z
. For the marginals, we also assume
t distributions but with
different degrees of freedom; for simplicity, the estimation is omitted
here.
## Warning in var.mpl(copula, u): the covariance matrix of the parameter estimates
## is computed as if 'df.fixed = TRUE' with df = 2.31167999431284
nu. <- rep(nu., d) # marginal degrees of freedom; for simplicity using the known ones here
est <- cbind(fitted = c(fitcop@estimate, nu.), true = c(th, nu, nu.)) # fitted vs true
rownames(est) <- c("theta", "nu (copula)", paste0("nu (margin ",1:2,")"))
est
## fitted true
## theta 0.6724203 0.7071068
## nu (copula) 2.3116800 3.0000000
## nu (margin 1) 3.5000000 3.5000000
## nu (margin 2) 3.5000000 3.5000000
Simulate from the fitted copula model.
set.seed(271) # reproducibility
U.. <- rCopula(n, fitcop@copula)
Z.. <- sapply(1:d, function(j) sqrt((nu.[j]-2)/nu.[j]) * qt(U..[,j], df = nu.[j]))
## => Innovations have to be standardized for ugarchsim()
sim <- lapply(1:d, function(j)
ugarchsim(fit[[j]], n.sim = n, m.sim = 1,
custom.dist = list(name = "sample",
distfit = Z..[,j, drop = FALSE])))
and plot the resulting series (Xt) for each margin