×

Last Update : 19 Oct 2025

Next Update : 29 Oct 2025


DCC - Dynamic Conditional Correlation

GARCH -  Generalized Autoregressive Conditional Heteroskedasticity


DCC GARCH is a popular statistical model to analyze financial markets and their correlations. We analyze forex major pair's price with this model but in a particular way, that we are gonna talk about.

There are few pre-requirements for data before fitting into this model.


We implemented full DCC-GARCH,  summarize entire workflow — from selecting 3 forex pairs to the final DCC correlation plot.

Below is the step-by-step logical and technical process we’ve been following :


🧩 1️⃣ Select correlated forex triplets


You begin by grouping related currency pairs — for example:

group = ['AUDCAD=X', 'NZDCAD=X', 'AUDUSD=X']

These are chosen manually or algorithmically because they share common currencies (AUD, NZD, CAD), which creates potential correlation and co-movement.

Purpose → find groups that show regional or fundamental linkage (commodity currencies, majors, etc.).


📈 2️⃣ Download data


You use Yahoo Finance (yfinance):

import yfinance as yf
data = yf.download(group, start="2010-01-01", end="2025-10-01")['Close']

You end up with a clean dataframe containing closing prices for each of the 3 symbols.


🔁 3️⃣ Compute log returns


Convert price levels to returns:

returns = np.log(data / data.shift(1)).dropna()

These returns are what DCC and GARCH models use.


⚙️ 4️⃣ Fit univariate GARCH(1,1) models


For each pair’s returns:

  • You estimate a GARCH(1,1) model (using arch library).

  • You extract standardized residuals and conditional variances.

Example:

from arch import arch_model

std_resid = {}
for col in returns.columns:
    am = arch_model(returns[col], mean='Zero', vol='GARCH', p=1, q=1)
    res = am.fit(disp='off')
    std_resid[col] = res.resid / res.conditional_volatility

This gives you whitened residuals — the input to DCC.


🔗 5️⃣ Combine standardized residuals


You now have a standardized residual matrix:

standardized_residuals = pd.DataFrame(std_resid)

Each column corresponds to one pair (e.g., AUDCAD, NZDCAD, AUDUSD).


🧮 6️⃣ Fit the DCC model (Dynamic Conditional Correlation)


We use a manual implementation or a library-based approach (like mgarch or custom loops).

The manual method uses Engle’s 2002 recursion:

                 


🎨 7️⃣ Plot dynamic correlations


You compute pairwise correlations from ( R_t ):

Example (for 3 pairs):

corrs = pd.DataFrame({
    f"{group[0]} vs {group[1]}": Rt[:,0,1],
    f"{group[0]} vs {group[2]}": Rt[:,0,2],
    f"{group[1]} vs {group[2]}": Rt[:,1,2]
}, index=returns.index)

Then you z-standardize, smooth, and optionally normalize (0–1) for visual comparison:

corrs_z = (corrs - corrs.mean()) / corrs.std()
corrs_smoothed = corrs_z.rolling(10).mean().dropna()

Finally, plot with chosen colors:

colors = ['black', 'blue', 'orange']
corrs_smoothed.plot(color=colors)
plt.title(f"DCC Dynamic Correlations - Group: {group}")
plt.ylabel("Correlation (-1 to 1)")
plt.grid(True)
plt.show()

🔍 8️⃣ Interpretation


  • The lines show time-varying correlation between each pair.

  • Correlations fluctuating around 0.5–0.9 → strong comovement.

  • Negative or diverging → decoupling phases (e.g., crisis, different interest rate regimes).

  • By overlapping all 3, you visually recognize patterns or synchronized movements — perfect for pattern recognition or clustering.


Summary of Your Pipeline


Step Description Output
1                                                   Select 3 related forex pairs                                                 group list
2 Download historical prices data
3 Compute log returns returns
4 Fit univariate GARCH(1,1) standardized residuals
5 Stack residuals standardized_residuals DataFrame
6 Apply DCC recursion time-varying correlation matrices Rt
7 Extract pairwise correlations DataFrame of correlations
8 Z-score + smooth + plot dynamic overlapping lines