GARCH(1,1) - CCC#


The Multivariate GARCH(1,1) model generalizes the univariate GARCH(1,1) 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).


Check Examples section for code guide and comparison to Stata.

Return equation#

The return equation for a \(N\)-dimensional time series is:

(1)#\[\mathbf{r}_t = \boldsymbol{\mu} + \boldsymbol{\epsilon}_t\]

Here, \(\mathbf{r}_t\) is a \(N \times 1\) vector of returns, and \(\boldsymbol{\mu}\) is a \(N \times 1\) vector of mean returns. \(\boldsymbol{\epsilon}_t\) is the \(N \times 1\) vector of shock terms.

Shock equation#

The shock term is modelled as:

(2)#\[\boldsymbol{\epsilon}_t = \mathbf{H}_t^{1/2} \mathbf{z}_t\]

Here, \(\mathbf{H}_t\) is a \(N \times N\) conditional covariance matrix, \(\mathbf{H}_t^{1/2}\) is a \(N \times N\) positive definite matrix, and \(\mathbf{z}_t\) is a \(N \times 1\) vector of standard normal innovations.

Conditional covariance matrix#

In the CCC-GARCH(1,1) model, the conditional covariance matrix \(\mathbf{H}_t\) is constructed as:

(3)#\[\mathbf{H}_t = \mathbf{D}_t\mathbf{R}\mathbf{D}_t\]

where \(\mathbf{D}_t=\text{diag}(\mathbf{h}_t)^{1/2}\), and \(\mathbf{h}_t\) is a \(N \times 1\) vector whose elements are univariate GARCH(1,1) variances for each time series. \(\mathbf{R}\) is a positive definite constant conditional correlation matrix.

A bivarite example

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 \(h_{1t}\) and \(h_{2t}\) can be written as:

(4)#\[h_{1t} = \omega_1 + \alpha_1 \epsilon_{1,t-1}^2 + \beta_1 h_{1,t-1}\]
(5)#\[h_{2t} = \omega_2 + \alpha_2 \epsilon_{2,t-1}^2 + \beta_2 h_{2,t-1}\]


  • \(\epsilon_{1,t-1}\) and \(\epsilon_{2,t-1}\) are past shock terms from their respective time series.

  • The parameters \(\omega_1, \alpha_1, \beta_1, \omega_2, \alpha_2, \beta_2\) are to be estimated.

With these individual variances, the conditional covariance matrix \(\mathbf{H}_t\) is:

(6)#\[\begin{split}\mathbf{H}_t = \begin{pmatrix} h_{1t} & \rho\sqrt{h_{1t} h_{2t}} \\\\ \rho\sqrt{h_{1t} h_{2t}} & h_{2t} \end{pmatrix}\end{split}\]

Here, \(\rho\) is the correlation between the two time series. It is assumed to be constant over time in the CCC-GARCH framework.

The constant correlation matrix \(\mathbf{R}\) simplifies to a \(2 \times 2\) matrix:

(7)#\[\begin{split}\mathbf{R} = \begin{pmatrix} 1 & \rho \\\\ \rho & 1 \end{pmatrix}\end{split}\]

Log-likelihood function#

The log-likelihood function for the \(N\)-dimensional multivariate GARCH CCC model is:

(8)#\[\begin{split}\begin{align} \ell &= -\frac{1}{2} \sum_{t=1}^T \left[ N\ln(2\pi) + \ln(|\mathbf{H}_t|) + \mathbf{\epsilon}_t' \mathbf{H}_t^{-1} \mathbf{\epsilon}_t \right] \\\\ &= -\frac{1}{2} \sum_{t=1}^T \left[ N\ln(2\pi) + \ln(|\mathbf{D}_t\mathbf{R}\mathbf{D}_t|) + \mathbf{\epsilon}_t' \mathbf{D}_t^{-1}\mathbf{R}^{-1}\mathbf{D}_t^{-1} \mathbf{\epsilon}_t \right] \\\\ &= -\frac{1}{2} \sum_{t=1}^T \left[ N\ln(2\pi) + 2 \ln(|\mathbf{D}_t|) + \ln(|\mathbf{R}|)+ \mathbf{z}_t' \mathbf{R}^{-1} \mathbf{z}_t \right] \end{align}\end{split}\]

where \(\mathbf{z}_t=\mathbf{D}_t^{-1}\mathbf{\epsilon}_t\) is the vector of standardized residuals.

This function is maximized to estimate the model parameters.

A bivariate example

In the bivariate case, the log-likelihood function can be specifically written as a function of all parameters.

The log-likelihood function \(\ell\) for the bivariate case with all parameters \(\Theta = (\mu_1, \omega_1, \alpha_1, \beta_1, \mu_2, \omega_2, \alpha_2, \beta_2, \rho)\) is:

(9)#\[\ell(\Theta) = -\frac{1}{2} \sum_{t=1}^T \left[ 2\ln(2\pi) + 2 \ln(|\mathbf{D}_t|) + \ln(|\mathbf{R}|)+ \mathbf{z}_t' \mathbf{R}^{-1} \mathbf{z}_t \right]\]

Here, \(\mathbf{z}_t'\) is the transpose of the vector of standardized residuals \(\mathbf{z}_t\),

\[\begin{split}\mathbf{z}_t = \begin{pmatrix} z_{1,t} \\ z_{2,t} \end{pmatrix}\end{split}\]


\[\begin{split}\mathbf{D}_t = \begin{pmatrix} \sqrt{h_{1t}} & 0 \\\\ 0 & \sqrt{h_{2t}} \end{pmatrix}\end{split}\]

so the log-determinant of \(\mathbf{D}_t\) is

\[\ln(|\mathbf{D}_t|) = \frac{1}{2} \ln(h_{1t} h_{2t})\]

The log-determinant of \(\mathbf{R}\) is

\[\ln(|\mathbf{R}|) = \ln(1 - \rho^2)\]

Inverse of \(\mathbf{R}\) is

\[\begin{split}\mathbf{R}^{-1} = \frac{1}{1 - \rho^2} \begin{pmatrix} 1 & -\rho \\ -\rho & 1 \end{pmatrix}\end{split}\]

Lastly, \(\mathbf{z}_t' \mathbf{R}^{-1} \mathbf{z}_t\) is

\[\mathbf{z}_t' \mathbf{R}^{-1} \mathbf{z}_t = \frac{1}{1 - \rho^2} \left[ z_{1t}^2 - 2\rho z_{1t} z_{2t} + z_{2t}^2 \right]\]

Inserting all of these into \(\ell(\Theta)\) in equation (9):

(10)#\[\ell(\Theta) = -\frac{1}{2} \sum_{t=1}^T \left[ 2\ln(2\pi) + \ln(h_{1t} h_{2t} (1 - \rho^2)) + \frac{1}{1 - \rho^2} \left( z_{1t}^2 - 2\rho z_{1t} z_{2t} + z_{2t}^2 \right) \right]\]

Estimation techniques#

My implementation of frds.algorithms.GARCHModel_CCC fits the GARCH-CCC model by simultaneously estimating all parameters via maxmimizing the log-likelihood (5).

General steps are:

  1. Use frds.algorithms.GARCHModel to estimate the GARCH(1,1) model for each of the returns.

  2. Use the standardized residuals from the estimated GARCH models to compute correlation coefficient.

  3. Use as starting vaues the estimated parameters from above in optimizing the loglikelihood function.


  • Engle, R. F. (1982), “Autoregressive Conditional Heteroskedasticity with Estimates of the Variance of United Kingdom Inflation.” Econometrica, 50(4), 987-1007.

  • Bollerslev, T. (1990), “Modelling the Coherence in Short-Run Nominal Exchange Rates: A Multivariate Generalized ARCH Model.” Review of Economics and Statistics, 72(3), 498-505.


class frds.algorithms.GARCHModel_CCC(returns1: ndarray, returns2: ndarray)[source]#

GARCH(1,1) - CCC model with the following specification:

  • Bivariate

  • Constant mean

  • Normal noise

It estimates the model parameters only. No standard errors calculated.

__init__(returns1: ndarray, returns2: ndarray) None[source]#
  • returns1 (np.ndarray) – (T,) array of T returns of first asset

  • returns2 (np.ndarray) – (T,) array of T returns of second asset


returns is best to be percentage returns for optimization

fit() Parameters[source]#

Estimates the Multivariate GARCH(1,1)-CCC parameters via MLE



Return type:


loglikelihood_model(params: ndarray, backcast1: float, backcast2: float, var_bounds1: ndarray, var_bounds2: ndarray) float[source]#

Calculates the negative log-likelihood based on the current params.

  • params (np.ndarray) – [mu1, omega1, alpha1, beta1, mu2, omega2, alpha2, beta2, rho]

  • backcast1 (float) – Backcast value for initializing the first return series variance.

  • backcast2 (float) – Backcast value for initializing the second return series variance.

  • var_bounds1 (np.ndarray) – Array of variance bounds for the first return series.

  • var_bounds2 (np.ndarray) – Array of variance bounds for the second return series.


negative log-likelihood

Return type:


loglikelihood(resids1: ndarray, sigma2_1: ndarray, resids2: ndarray, sigma2_2: ndarray, rho: float) float[source]#

Computes the log-likelihood for a bivariate GARCH(1,1) model with constant correlation.

  • resids1 (np.ndarray) – Residuals for the first return series.

  • sigma2_1 (np.ndarray) – Array of conditional variances for the first return series.

  • resids2 (np.ndarray) – Residuals for the second return series.

  • sigma2_2 (np.ndarray) – Array of conditional variances for the second return series.

  • rho (float) – Constant correlation.


The log-likelihood value for the bivariate model.

Return type:


class frds.algorithms.GARCHModel_CCC.Parameters(mu1: float = nan, omega1: float = nan, alpha1: float = nan, beta1: float = nan, mu2: float = nan, omega2: float = nan, alpha2: float = nan, beta2: float = nan, rho: float = nan, loglikelihood: float = nan)#


Let’s import the dataset.

>>> import pandas as pd
>>> data_url = ""
>>> 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 =
>>> from pprint import pprint
>>> pprint(res)

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
mgarch ccc (toyota nissan = ), arch(1) garch(1)

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

See Stata’s reference manual for its estimation techniques.