GARCH-Constant Conditional Correlation (CCC)
This post details a multivariate GARCH Constant Conditional Correlation (CCC) model (Engle 1982). It was somewhat surprising that I didn’t find a good Python implementation of GARCH-CCC, so I wrote my own, see documentation on frds.io. It performs very well, often generates (marginally) better estimates than in Stata based on log-likelihood.
Multivariate GARCH-CCC
The Multivariate GARCH model generalizes the univariate GARCH framework to multiple time series, capturing not only the conditional variances but also the conditional covariances between the series. One common form is the Constant Conditional Correlation (CCC) model proposed by Bollerslev (1990).
Return equation
The return equation for a
Here,
Shock equation
The shock term is modelled as:
Here,
Conditional covariance matrix
In the CCC-GARCH(1,1) model, the conditional covariance matrix
where
In a bivariate GARCH(1,1) setting, we have two univariate GARCH(1,1) processes, one for each return series. Specifically, the GARCH(1,1) equations for the conditional variances
where
and are past shock terms from their respective time series.- The parameters
are to be estimated.
With these individual variances, the conditional covariance matrix
Here,
Log-likelihood function
The log-likelihood function for the
where
In the bivariate case, the log-likelihood function can be specifically written as a function of all parameters.
The log-likelihood function
Here,
Further,
So the log-determinant of
The log-determinant of
The inverse of
Lastly,
Inserting all of these into
Estimation techniques
frds.algorithms.GARCHModel_CCC
is my implementation. Specifically, I estimate all the GARCH-DCC parameters simultaneously via maximizing the log-likelihood.
General steps are:
- Use
frds.algorithms.GARCHModel
to estimate the GARCH model for each of the returns. - Use the standardized residuals from the estimated GARCH models to compute the correlation coefficient.
- Use as starting values the estimated parameters from above in optimizing the log-likelihood function.
Example code
Let’s import the dataset.
>>> import pandas as pd
>>> data_url = "https://www.stata-press.com/data/r18/stocks.dta"
>>> df = pd.read_stata(data_url, convert_dates=["date"])
Scale returns to percentage returns for better optimization results
>>> returns1 = df["toyota"].to_numpy() * 100
>>> returns2 = df["nissan"].to_numpy() * 100
Use frds.algorithms.GARCHModel_CCC
to estimate a GARCH(1,1)-CCC.
>>> from frds.algorithms import GARCHModel_CCC
>>> model_ccc = GARCHModel_CCC(returns1, returns2)
>>> res = model_ccc.fit()
>>> from pprint import pprint
>>> pprint(res)
=0.02745814255283541,
Parameters(mu1=0.03401400758840226,
omega1=0.06593379740524756,
alpha1=0.9219575443861723,
beta1=0.009390068254041505,
mu2=0.058694325049554734,
omega2=0.0830561828957614,
alpha2=0.9040961791372522,
beta2=0.6506770477876749,
rho=-7281.321453218112) loglikelihood
These results are comparable to the ones obtained in Stata, and even marginally better based on log-likelihood. In Stata, we can estimate the same model as below:
webuse stocks, clear
replace toyota = toyota * 100
replace nissan = nissan * 100
arch(1) garch(1) mgarch ccc (toyota nissan = ),
The Stata results are:
Constant conditional correlation MGARCH model
Sample: 1 thru 2015 Number of obs = 2,015
Distribution: Gaussian Wald chi2(.) = .
Log likelihood = -7282.961 Prob > chi2 = .
-------------------------------------------------------------------------------------
| Coefficient Std. err. z P>|z| [95% conf. interval]
--------------------+----------------------------------------------------------------
toyota |
_cons | .0277462 .0302805 0.92 0.360 -.0316024 .0870948
--------------------+----------------------------------------------------------------
ARCH_toyota |
arch |
L1. | .0666384 .0101597 6.56 0.000 .0467257 .0865511
|
garch |
L1. | .9210688 .0119214 77.26 0.000 .8977032 .9444343
|
_cons | .0344153 .0109208 3.15 0.002 .013011 .0558197
--------------------+----------------------------------------------------------------
nissan |
_cons | .0079682 .0349351 0.23 0.820 -.0605034 .0764398
--------------------+----------------------------------------------------------------
ARCH_nissan |
arch |
L1. | .0851778 .0132656 6.42 0.000 .0591778 .1111779
|
garch |
L1. | .9016613 .0150494 59.91 0.000 .8721649 .9311577
|
_cons | .0603765 .0178318 3.39 0.001 .0254269 .0953262
--------------------+----------------------------------------------------------------
corr(toyota,nissan) | .6512249 .0128548 50.66 0.000 .62603 .6764199
-------------------------------------------------------------------------------------