← Zurück zu den Artikeln
July 12, 2026
5 min read

DCC-GARCH: Dynamische Korrelationen für Paare und Portfoliorisiko

#volatility
#GARCH
#DCC
#correlation
#portfolio
#pairs-trading
#crypto

Fragen Sie die meisten Krypto-Desks nach der Korrelation zwischen BTC und ETH, und Sie erhalten eine einzelne Zahl — 0,8, vielleicht 0,75 — berechnet über irgendein Fenster, an dessen Wahl sich niemand erinnert. Diese Zahl ist eine Lüge, oder zumindest eine gefährliche Vereinfachung. Die Stichprobenkorrelation ist ein Durchschnitt über einen Zeitraum, in dem sich die wahre Abhängigkeitsstruktur ständig bewegt hat. In ruhigen Märkten driften BTC und ETH weit genug auseinander, um ein marktneutrales Paar attraktiv erscheinen zu lassen. In einer Liquidationskaskade koppeln sie sich aneinander und an alles andere, und die Diversifikation, für die Sie bezahlt haben, verdampft genau in dem Moment, in dem Sie sie brauchen.

Das ist kein subtiler Effekt. Nehmen Sie einen beliebigen Drawdown aus 2022 — den LUNA-Kollaps im Mai, die 3AC-Abwicklung im Juni, die FTX-Implosion im November — und Sie werden sehen, wie die durchschnittliche paarweise Korrelation über die Top-20-Token innerhalb von Tagen vom Bereich 0,4-0,6 in Richtung 0,9+ marschiert. Korrelation ist keine Konstante, die gelegentlich schlecht geschätzt wird; sie ist eine Zeitreihe mit eigener Dynamik, eigenem Clustering und eigenen Regimen. Sie als Skalar zu behandeln, ist das multivariate Äquivalent zur Annahme konstanter Volatilität — ein Fehler, den wir bereits in Teil 1 dieser Serie für einen einzelnen Vermögenswert auseinandergenommen haben.

Dieser Artikel ist Teil 3 einer vierteiligen Volatilitätsserie. Teil 1 baute univariates GARCH(1,1) mit der arch-Bibliothek auf und zeigte, wie Volatilität clustert und zum Mittelwert zurückkehrt. Teil 2 fügte Asymmetrie (GJR-GARCH, EGARCH) und Student-t-Innovationen hinzu, um den Leverage-Effekt und Fat Tails zu erfassen. Hier werden wir multivariat: Wir modellieren die gesamte bedingte Kovarianzmatrix HtH_t in ihrer Entwicklung, unter Verwendung von Engles Dynamic-Conditional-Correlation-Modell (DCC). Das liefert uns zwei Dinge, die eine skalare Korrelation niemals kann — eine dynamische Hedge-Ratio für Pairs-Trading und eine ehrliche, zeitvariable Portfoliovarianz für risikobasierte Allokation. Teil 4 schließt die Serie mit einem volatilitätsgezielten Backtest ab, der die univariaten und multivariaten Prognosen in eine Positionsgrößen-Regel überführt.

Wir setzen voraus, dass Sie Teil 1 und 2 gelesen haben, daher werden wir univariates GARCH nicht erneut herleiten. Wenn Sie das gemeinsame Tail-Verhalten wissen möchten — die Wahrscheinlichkeit, dass zwei Vermögenswerte gemeinsam ihr 1%-Quantil durchbrechen — dann ist das eine Copula-Frage, und wir behandeln sie in Copula-Modelle für gemeinsames Risiko. DCC und Copulas sind komplementär: Die Copula liefert Ihnen eine statische, aber flexible Tail-Abhängigkeitsstruktur, während DCC Ihnen eine handhabbare Zeitreihe der gesamten Korrelationsmatrix liefert. In diesem Artikel geht es um Letzteres.

Warum statische Korrelation in Krypto versagt

Bevor wir zur Maschinerie kommen, sollten wir präzise sagen, was versagt. Eine einzelne Stichprobenkorrelation ρ^\hat{\rho} über ein Fenster [tw,t][t-w, t] schätzt

ρ^ij=s(ri,srˉi)(rj,srˉj)s(ri,srˉi)2s(rj,srˉj)2\hat{\rho}_{ij} = \frac{\sum_{s} (r_{i,s} - \bar{r}_i)(r_{j,s} - \bar{r}_j)}{\sqrt{\sum_s (r_{i,s}-\bar{r}_i)^2}\sqrt{\sum_s (r_{j,s}-\bar{r}_j)^2}}

Dies trägt drei implizite Annahmen in sich, die für Krypto allesamt falsch sind:

  1. Stationarität der Abhängigkeit. Das Fenster hat ein wahres ρ\rho. In Wirklichkeit hat die Abhängigkeit Regime — ein Ruhemarkt-Regime nahe 0,5 und ein Stress-Regime nahe 0,95 — und ρ^\hat{\rho} vermischt sie zu einer bedeutungslosen Mitte.
  2. Konstante marginale Volatilität. Die Pearson-Korrelation ist eine normalisierte Kovarianz. Wenn sich σi,t\sigma_{i,t} und σj,t\sigma_{j,t} selbst bewegen (sie tun es — das ist die gesamte Prämisse von Teil 1 und 2), dann erzeugt selbst eine konstante Kovarianz eine zeitvariable Korrelation und umgekehrt. Sie können die beiden nicht trennen, ohne ein Volatilitätsmodell darunter.
  3. Symmetrie über die Marktrichtung. Die Korrelation steigt in Drawdowns stärker als in Rallyes. Dies ist der multivariate Vetter des Leverage-Effekts. Ein rollierendes Fenster kann ihn nicht ausdrücken, ohne so kurz zu werden, dass es reines Rauschen ist.

Der Rolling-Window-Fix — ρ^\hat{\rho} über die letzten 30 oder 60 Tage neu zu berechnen — tauscht ein Problem gegen ein anderes. Kurze Fenster sind reaktionsschnell, aber verrauscht und hinken dem tatsächlichen Bruch hinterher; lange Fenster sind stabil, aber veraltet. Schlimmer noch: Eine rollierende Korrelationsmatrix über dd Vermögenswerte bleibt nicht garantiert positiv semidefinit, sobald Sie mit Schrumpfung oder Patching beginnen, was jeden nachgelagerten Optimierer bricht. Wir wollen ein Modell, das (a) von einem echten Volatilitätsprozess pro Vermögenswert getrieben wird, (b) per Konstruktion in jedem Schritt eine gültige Korrelationsmatrix erzeugt und (c) Parameter hat, die wir per Maximum-Likelihood schätzen können, statt eine Fensterlänge aus dem Hut zu ziehen. Dieses Modell ist DCC-GARCH.

Das multivariate Problem: Die bedingte Kovarianzmatrix

Sei rtRdr_t \in \mathbb{R}^d der Vektor der Renditen für dd Vermögenswerte zum Zeitpunkt tt, mit bedingtem Mittelwert μt\mu_t (oft nur eine Konstante oder ein kleiner AR-Term) und Residuum ϵt=rtμt\epsilon_t = r_t - \mu_t. Wir nehmen an

ϵtFt1D(0,Ht)\epsilon_t \mid \mathcal{F}_{t-1} \sim \mathcal{D}(0, H_t)

wobei HtH_t die d×dd \times d bedingte Kovarianzmatrix gegeben die Informationsmenge Ft1\mathcal{F}_{t-1} ist und D\mathcal{D} eine bedingte Verteilung ist (Gauß oder, besser für Krypto, multivariate Student-t). Alles in der multivariaten Volatilitätsmodellierung ist eine andere Antwort auf eine Frage: Wie parametrisiert man die Dynamik von HtH_t, sodass es in jedem Schritt symmetrisch positiv definit bleibt, ohne eine Explosion von Parametern?

Zwei klassische Antworten zeigen, warum das Problem schwer ist.

VECH

Das VECH-Modell (Bollerslev, Engle, Wooldridge 1988) schreibt die Halb-Vektorisierung von HtH_t als lineare Funktion vergangener quadrierter Residuen und vergangener Kovarianzen:

vech(Ht)=c+Avech(ϵt1ϵt1)+Bvech(Ht1)\mathrm{vech}(H_t) = c + A\,\mathrm{vech}(\epsilon_{t-1}\epsilon_{t-1}') + B\,\mathrm{vech}(H_{t-1})

wobei vech()\mathrm{vech}(\cdot) das untere Dreieck einer symmetrischen Matrix in einen Vektor der Länge d(d+1)/2d(d+1)/2 stapelt. Dies ist maximal allgemein — jede Varianz und Kovarianz hängt von jeder vergangenen Varianz und Kovarianz ab — und jenseits von d=3d=3 maximal nutzlos. Für dd Vermögenswerte sind AA und BB jeweils d(d+1)2×d(d+1)2\frac{d(d+1)}{2} \times \frac{d(d+1)}{2}. Bei d=5d=5 sind das zwei 15×1515\times 15-Matrizen, ungefähr 450 Parameter, plus Positive-Definitheits-Beschränkungen, die schon auszudrücken schmerzhaft sind. Die Likelihood-Oberfläche ist ein Sumpf.

BEKK

Das BEKK-Modell (Engle & Kroner 1995) garantiert positive Definitheit per Konstruktion mittels einer quadratischen Form:

Ht=CC+Aϵt1ϵt1A+BHt1BH_t = C'C + A'\,\epsilon_{t-1}\epsilon_{t-1}'\,A + B'\,H_{t-1}\,B

mit CC oberer Dreiecksmatrix. Da jeder Term eine quadratische Form ist, gilt Ht0H_t \succ 0 automatisch, solange CC0C'C \succ 0. BEKK ist sparsamer als VECH, skaliert aber immer noch mit O(d2)O(d^2) Parametern — die AA- und BB-Matrizen sind jeweils d×dd \times d. Für d=10d=10 schätzen Sie in der Größenordnung von 200+ Parametern gemeinsam per MLE, auf verrauschten täglichen Krypto-Daten, ohne Garantie, dass der Optimierer zu etwas Sinnvollem konvergiert. In der Praxis ist volles BEKK auf d4d \le 4 beschränkt, und selbst dann verwendet man die diagonalen oder skalaren Restriktionen, die den Großteil der Kreuzdynamik verwerfen.

Dies ist der Fluch der Dimensionalität für multivariates GARCH: Die Anzahl der Parameter wächst quadratisch, aber die Menge an Information in den Daten nicht. Ihnen gehen die Freiheitsgrade lange aus, bevor Ihnen die Vermögenswerte ausgehen, die Sie interessieren. Jedes Krypto-Portfolio mit 10-30 Token ist für VECH oder BEKK völlig unerreichbar.

Der Ausweg, der auf Engle zurückgeht, besteht darin, nicht mehr zu versuchen, HtH_t direkt zu modellieren, sondern es stattdessen zu faktorisieren in Teile, die wir bereits kostengünstig schätzen können.

Engles DCC (2002): Die zweistufige Zerlegung

Bollerslevs Constant-Conditional-Correlation-Modell (CCC) (1990) war die erste sparsame Faktorisierung. Es schreibt

Ht=DtRDtH_t = D_t\, R\, D_t

wobei Dt=diag(σ1,t,,σd,t)D_t = \mathrm{diag}(\sigma_{1,t}, \ldots, \sigma_{d,t}) die Diagonalmatrix der bedingten Standardabweichungen ist — ein univariates GARCH pro Vermögenswert — und RR eine konstante Korrelationsmatrix ist. Dies ist eine enorme Vereinfachung: Sie passen dd unabhängige univariate GARCH-Modelle an und schätzen dann eine einzelne Stichprobenkorrelationsmatrix der standardisierten Residuen. Positive Definitheit ist automatisch, solange RR eine gültige Korrelationsmatrix ist und alle σi,t>0\sigma_{i,t} > 0 sind.

Das Problem von CCC steckt schon im Namen — die Korrelation ist konstant, was genau die Annahme ist, die wir am Anfang dieses Artikels abgelehnt haben. Engles Dynamic Conditional Correlation (2002) behält CCCs schöne Faktorisierung bei, lässt die Korrelationsmatrix aber atmen:

Ht=DtRtDtH_t = D_t\, R_t\, D_t

Nun ist RtR_t zeitvariabel. Der Geniestreich ist, dass die Volatilitäten und die Korrelationen in zwei getrennten Schritten geschätzt werden, sodass wir niemals mit der vollen O(d2)O(d^2)-Gemeinschaftsoptimierung konfrontiert sind.

Schritt 1: Univariates GARCH pro Vermögenswert

Für jeden Vermögenswert ii passen Sie ein univariates GARCH-Modell an, genau wie in Teil 1 und 2 — GARCH(1,1), GJR-GARCH oder EGARCH mit Student-t-Innovationen, was auch immer für diese Reihe am besten passte. Dies liefert bedingte Varianzen σi,t2\sigma_{i,t}^2 und somit Dt=diag(σ1,t,,σd,t)D_t = \mathrm{diag}(\sigma_{1,t}, \ldots, \sigma_{d,t}).

Aus den angepassten Modellen extrahieren wir die standardisierten Residuen:

zi,t=ϵi,tσi,tz_{i,t} = \frac{\epsilon_{i,t}}{\sigma_{i,t}}

Per Konstruktion hat jedes zi,tz_{i,t} (näherungsweise) eine bedingte Einheitsvarianz. Stapeln Sie sie in einen Vektor zt=(z1,t,,zd,t)z_t = (z_{1,t}, \ldots, z_{d,t})'. Diese standardisierten Residuen sind das Rohmaterial für den Korrelationsschritt — ihre individuelle Volatilitätsdynamik wurde herausgerechnet, sodass jede verbleibende Mitbewegung reine Abhängigkeit ist und kein Volatilitätsartefakt. (Dies ist dieselbe PIT-artige Logik, die der Copula-Artikel vor dem Anpassen der Ränder verwendet; hier hören wir bei der Standardisierung auf, statt den ganzen Weg bis zu Gleichverteilungen zu gehen.)

Schritt 2: Die DCC-Korrelationsrekursion

Wir modellieren einen Hilfsprozess QtQ_t, eine d×dd \times d symmetrische positiv definite Matrix, mit einer GARCH-artigen Rekursion, die durch die äußeren Produkte der standardisierten Residuen getrieben wird:

Qt=(1ab)Qˉ+azt1zt1+bQt1Q_t = (1 - a - b)\,\bar{Q} + a\, z_{t-1} z_{t-1}' + b\, Q_{t-1}

wobei:

  • Qˉ=1Tt=1Tztzt\bar{Q} = \frac{1}{T}\sum_{t=1}^{T} z_t z_t' die unbedingte Korrelationsmatrix der standardisierten Residuen ist (dies ist Korrelations-Targeting — mehr dazu unten),
  • a0a \ge 0 steuert, wie stark der heutige Schock zt1zt1z_{t-1}z_{t-1}' die Korrelation zieht,
  • b0b \ge 0 steuert die Persistenz — wie viel vom gestrigen Qt1Q_{t-1} übertragen wird,
  • und die Mean-Reversion-Beschränkung ist a+b<1a + b < 1 (mit a,b>0a, b > 0), direkt analog zu α+β<1\alpha + \beta < 1 im univariaten GARCH.

Beachten Sie, dass die Struktur identisch mit einer skalaren GARCH(1,1)-Rekursion ist, aber auf Matrizen: ein langfristiger Anker Qˉ\bar{Q}, ein Schockterm und ein Persistenzterm. Da es eine Konvexkombination positiv semidefiniter Matrizen ist (Qˉ\bar{Q}, das Rang-1-äußere-Produkt und das vorherige Qt1Q_{t-1}), bleibt QtQ_t positiv definit, solange Qˉ0\bar{Q} \succ 0 und die Gewichte nicht negativ sind. Das ist es, was uns garantiert gültige Kovarianzmatrizen kostenlos beschert.

QtQ_t ist fast eine Korrelationsmatrix, aber nicht ganz — seine Diagonale ist nicht exakt 1. Daher normalisieren wir es:

Rt=(diag(Qt))1/2Qt(diag(Qt))1/2R_t = \left(\mathrm{diag}(Q_t)\right)^{-1/2}\, Q_t\, \left(\mathrm{diag}(Q_t)\right)^{-1/2}

Elementweise ist die bedingte Korrelation zwischen den Vermögenswerten ii und jj

ρij,t=qij,tqii,tqjj,t\rho_{ij,t} = \frac{q_{ij,t}}{\sqrt{q_{ii,t}\, q_{jj,t}}}

Dieses RtR_t ist eine echte Korrelationsmatrix — Einheitsdiagonale, Nebendiagonalen in [1,1][-1,1], positiv definit — in jedem einzelnen Zeitschritt, per Konstruktion. Setzen Sie die volle bedingte Kovarianz wieder zusammen:

Ht=DtRtDt,hij,t=ρij,tσi,tσj,tH_t = D_t\, R_t\, D_t, \qquad h_{ij,t} = \rho_{ij,t}\,\sigma_{i,t}\,\sigma_{j,t}

Diese letzte elementweise Form ist diejenige, die Sie ständig verwenden werden: Die bedingte Kovarianz zweier Vermögenswerte ist ihre dynamische Korrelation multipliziert mit jeder ihrer dynamischen Volatilitäten. Jede Zutat auf der rechten Seite ist zeitvariabel und stammt aus einem Modell, das Sie schätzen können.

Das gesamte Modell hat nur zwei Korrelationsparameter, aa und bb, unabhängig davon, ob d=2d = 2 oder d=50d = 50. Die Volatilitätsseite skaliert linear (ein univariates GARCH pro Vermögenswert, jeweils mit ~4-5 Parametern, alle unabhängig und peinlich parallel angepasst). Deshalb skaliert DCC dort, wo BEKK und VECH es nicht können: Der Dimensionalitätsfluch ist auf Qˉ\bar{Q} beschränkt, das getargetet (als Stichprobenschätzung eingesetzt) statt optimiert wird.

Die skalare Restriktion und ihr Preis

Die a,ba, b-Skalare bedeuten, dass jedes Vermögenswertpaar dieselbe Korrelationsdynamik teilt — dieselbe Anpassungsgeschwindigkeit und dieselbe Persistenz. Die BTC-ETH-Korrelation und die DOGE-SHIB-Korrelation bewegen sich im selben Rhythmus, obwohl sich ihre Ökonomie unterscheidet. Dies ist der Preis der Handhabbarkeit, und es ist normalerweise ein akzeptabler Preis. Verallgemeinerungen (Generalized DCC mit Matrizen A,BA, B; das asymmetrische DCC von Cappiello-Engle-Sheppard) lockern es auf Kosten von Parametern und Schätzstabilität. Wir erwähnen aDCC weiter unten.

Die DCC-Quasi-Log-Likelihood

Um aa und bb zu schätzen, benötigen wir die Likelihood. Engles Schlüsselergebnis ist, dass sich die Gauß-Log-Likelihood in einen Volatilitätsteil und einen Korrelationsteil auftrennt, was den zweistufigen Schätzer rechtfertigt. Unter der Annahme ϵtFt1N(0,Ht)\epsilon_t \mid \mathcal{F}_{t-1} \sim \mathcal{N}(0, H_t) ist der Log-Likelihood-Beitrag zum Zeitpunkt tt

t=12(dlog(2π)+logHt+ϵtHt1ϵt)\ell_t = -\frac{1}{2}\left( d\log(2\pi) + \log|H_t| + \epsilon_t' H_t^{-1} \epsilon_t \right)

Setzen Sie Ht=DtRtDtH_t = D_t R_t D_t ein. Dann gilt Ht=Dt2Rt|H_t| = |D_t|^2 |R_t| und Ht1=Dt1Rt1Dt1H_t^{-1} = D_t^{-1} R_t^{-1} D_t^{-1}, und mit zt=Dt1ϵtz_t = D_t^{-1}\epsilon_t:

t=12(dlog(2π)+2logDt+logRt+ztRt1zt)\ell_t = -\frac{1}{2}\left( d\log(2\pi) + 2\log|D_t| + \log|R_t| + z_t' R_t^{-1} z_t \right)

Nun teilen wir es auf, indem wir ztztz_t'z_t addieren und subtrahieren:

t=12(dlog(2π)+2logDt+ϵtDt2ϵt)Volatilita¨tsteil   tV  12(logRt+ztRt1ztztzt)Korrelationsteil   tC\ell_t = \underbrace{-\frac{1}{2}\left( d\log(2\pi) + 2\log|D_t| + \epsilon_t' D_t^{-2}\epsilon_t \right)}_{\text{Volatilitätsteil }\;\ell_t^{V}} \;\underbrace{-\frac{1}{2}\left( \log|R_t| + z_t' R_t^{-1} z_t - z_t' z_t \right)}_{\text{Korrelationsteil }\;\ell_t^{C}}

Der Volatilitätsteil tV\ell_t^V hängt nur von den univariaten GARCH-Parametern ab (über DtD_t) — ihn zu maximieren ist genau das Anpassen von dd unabhängigen univariaten GARCH-Modellen, was wir in Schritt 1 getan haben. Der Korrelationsteil tC\ell_t^C hängt von aa und bb ab (über RtR_t), gegeben die standardisierten Residuen aus Schritt 1. In Schritt 2 maximieren wir also nur

LC(a,b)=12t=1T(logRt+ztRt1zt)\mathcal{L}^C(a, b) = -\frac{1}{2}\sum_{t=1}^{T}\left( \log|R_t| + z_t' R_t^{-1} z_t \right)

(der Term ztztz_t'z_t hängt nicht von a,ba, b ab, daher lassen wir ihn weg). Dies ist eine zweiparametrige Optimierung, egal wie viele Vermögenswerte — das ist der ganze Sinn. Sie wird Quasi-Likelihood genannt, weil der zweistufige Schätzer konsistent, aber nicht vollständig effizient ist; die Standardfehler benötigen eine Korrektur (Engle & Sheppard 2001), aber für die Signalgenerierung sind die Punktschätzungen das, worauf es ankommt.

Für Krypto unterschätzen Gauß-Innovationen das Tail-Risiko. Der Ersatz durch die multivariate Student-t-Likelihood ist eine Drop-in-Änderung an t\ell_t (ersetzen Sie den Gauß-Kern durch die multivariate tt-Dichte und fügen Sie einen Freiheitsgrad-Parameter ν\nu hinzu). Wir behalten die Gauß-Quasi-Likelihood im Schätzer unten der Klarheit halber bei und weisen darauf hin, wo ν\nu eintritt — die Standardisierung aus Teil 1-2 verwendete bereits t-Innovationen auf den Rändern, was den größten Teil des Tail-Vorteils erfasst.

Python-Implementierung

Eine unverblümte, aber wichtige Tatsache: die arch-Bibliothek macht kein multivariates GARCH oder DCC. arch ist eine hervorragende univariate Engine (wir stützen uns genau dafür darauf), aber es gibt kein dcc_model darin. Ihre praktischen Optionen sind:

  1. Rollen Sie Ihr eigenes DCC auf arch — passen Sie univariate Modelle mit arch an, extrahieren Sie standardisierte Residuen, implementieren Sie die QQ-Rekursion und die Korrelations-Quasi-Likelihood in NumPy/SciPy und optimieren Sie die zwei Skalare. Das ist es, was wir unten tun. Es sind etwa 60 Zeilen und vollkommen transparent.
  2. Das mgarch-PyPI-Paket — eine leichtgewichtige reine-Python-DCC-GARCH-Implementierung. Bequem für eine schnelle Anpassung, weniger flexibel, wenn Sie GJR-Ränder oder t-Innovationen präzise verdrahten möchten.
  3. Rs rmgarch (Alexios Galanos) — die Referenzimplementierung. dccspec / dccfit unterstützen DCC, aDCC, GARCH-Copula, Student-t und korrekte Standardfehler. Wenn Sie ernsthafte multivariate Volatilitätsforschung betreiben, ist rmgarch (bei Bedarf aus Python über rpy2 aufgerufen) der Goldstandard.

Wir bauen Option 1, weil sie jedes bewegliche Teil explizit macht und die univariaten Fähigkeiten aus Teil 1-2 wiederverwendet.

Schritt 1: Univariate GARCH-Ränder mit arch anpassen

import numpy as np
import pandas as pd
from arch import arch_model
from scipy.optimize import minimize

def fetch_returns(symbols, start="2022-01-01", end="2025-12-31"):
    """
    Daily log returns for a list of crypto symbols.
    Replace with your data source (ccxt for 24/7 exchange data,
    yfinance for a quick sketch).
    """
    import yfinance as yf
    px = yf.download([f"{s}-USD" for s in symbols],
                     start=start, end=end)["Close"]
    px.columns = symbols
    rets = np.log(px / px.shift(1)).dropna()
    return rets

symbols = ["BTC", "ETH", "SOL", "BNB"]
returns = fetch_returns(symbols)

def fit_univariate(series, dist="t"):
    """
    Fit GJR-GARCH(1,1) with Student-t innovations (Part 2 model).
    Returns the fitted result and the *scaled* series it was fit on.
    We scale returns by 100 for the optimizer's numerical health,
    exactly as in Parts 1 and 2.
    """
    scaled = series * 100.0
    model = arch_model(scaled, mean="Constant",
                       vol="GARCH", p=1, o=1, q=1, dist=dist)
    res = model.fit(disp="off")
    return res

fits = {s: fit_univariate(returns[s]) for s in symbols}

Z = pd.DataFrame({s: fits[s].std_resid for s in symbols}).dropna()

Sigma = pd.DataFrame({s: fits[s].conditional_volatility
                      for s in symbols}).loc[Z.index]

print(Z.describe())

Eine schnelle Plausibilitätsprüfung der standardisierten Residuen ist wichtig. Wenn eine Spalte eine Standardabweichung weit von 1 hat oder starke verbleibende Autokorrelation in ihrem Quadrat (Ljung-Box auf zi,t2z_{i,t}^2), ist der univariate Rand fehlspezifiziert, und der DCC-Schritt wird diesen Fehler erben. Korrigieren Sie zuerst den Rand — genau dafür war Teil 2 da.

Schritt 2: Die DCC-Rekursion und Quasi-Log-Likelihood

def dcc_negloglik(params, Z):
    """
    Negative DCC quasi-log-likelihood (Gaussian) in (a, b).
    Z : (T, d) array of standardized residuals from Step 1.

    Implements:
        Q_t = (1-a-b) Qbar + a z_{t-1} z_{t-1}' + b Q_{t-1}
        R_t = diag(Q_t)^{-1/2} Q_t diag(Q_t)^{-1/2}
        LL  = -1/2 sum_t ( log|R_t| + z_t' R_t^{-1} z_t )
    with correlation targeting: Qbar = sample corr of Z.
    """
    a, b = params
    if a <= 0 or b <= 0 or a + b >= 1.0:
        return 1e10

    Z = np.asarray(Z)
    T, d = Z.shape
    Qbar = np.cov(Z, rowvar=False, bias=True)   # unconditional (targeted)
    dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
    Qbar = dinv @ Qbar @ dinv

    Q = Qbar.copy()          # initialize Q_1 at the target
    ll = 0.0
    for t in range(T):
        q_diag = np.sqrt(np.diag(Q))
        R = Q / np.outer(q_diag, q_diag)
        sign, logdet = np.linalg.slogdet(R)
        if sign <= 0:
            return 1e10
        z = Z[t]
        Rinv_z = np.linalg.solve(R, z)
        ll += -0.5 * (logdet + z @ Rinv_z)
        Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
    return -ll

def fit_dcc(Z):
    """Estimate (a, b) by maximizing the DCC quasi-log-likelihood."""
    res = minimize(
        dcc_negloglik, x0=[0.03, 0.94], args=(np.asarray(Z),),
        method="L-BFGS-B",
        bounds=[(1e-6, 0.5), (1e-6, 0.999)],
    )
    a, b = res.x
    print(f"DCC estimates: a = {a:.4f}, b = {b:.4f}, a+b = {a+b:.4f}")
    print(f"log-likelihood: {-res.fun:.2f}")
    return a, b

a_hat, b_hat = fit_dcc(Z)

Wenn Sie dies auf einem BTC/ETH/SOL/BNB-Portfolio über einige Jahre täglicher Daten ausführen, entsteht eine Ausgabe in folgender Form (die Zahlen unten sind illustrativ, nicht aus einem konkreten datierten Experiment — führen Sie es mit Ihren eigenen Daten aus):

DCC estimates: a = 0.0287, b = 0.9401, a+b = 0.9688
log-likelihood: -3812.44

So liest man es:

  • a=0.029a = 0.029 ist klein — die Korrelationsmatrix ruckt nicht bei einem einzigen Tagesschock. Jeder Tag schiebt RtR_t nur um ~3% in Richtung des äußeren Produkts zt1zt1z_{t-1}z_{t-1}'.
  • b=0.940b = 0.940 ist groß — Korrelationen sind hochgradig persistent. Sobald sich das Portfolio in einem Stressereignis koppelt, bleibt es eine Weile gekoppelt und klingt nur langsam zu Qˉ\bar{Q} ab. Das entspricht der gelebten Erfahrung von Krypto-Drawdowns: Korrelationen springen nicht in dem Moment zurück, in dem sich der Preis stabilisiert.
  • a+b=0.969<1a + b = 0.969 < 1 bestätigt Mean Reversion. Der Korrelationsprozess hat ein stationäres langfristiges Niveau (Qˉ\bar{Q}), zu dem er zurückkehrt, mit einer Halbwertszeit von ungefähr log(0.5)/log(a+b)22\log(0.5)/\log(a+b) \approx 22 Tagen. Wenn Sie jemals a+ba + b im Wesentlichen gleich 1 schätzen, ist der Korrelationsprozess integriert — er hat keinen langfristigen Anker, meist ein Symptom eines Strukturbruchs innerhalb Ihrer Stichprobe, den das Modell als unendliche Persistenz absorbiert.

Die nahe-Einheits-Persistenz und die winzige Schockladung sind der kanonische DCC-Fingerabdruck über Anlageklassen hinweg, und Krypto ist keine Ausnahme. Es ist auch der Grund, warum eine 30-Tage-Rolling-Korrelation ein so schlechter Ersatz ist: Ein rollierendes Fenster nimmt implizit aa und bb an, die überhaupt nicht zu dieser Abklingstruktur passen.

Ein paar Implementierungshinweise, die echte Debugging-Zeit sparen:

  • Initialisierung. Der Start bei [0.03, 0.94] spiegelt die typische Krypto-Schätzung wider: kleines aa (Korrelationen reagieren auf Schocks, aber nicht heftig), großes bb (Korrelationen sind persistent). Wenn Ihr Optimierer zu a+b1a+b \to 1 wandert, ist der Korrelationsprozess integriert — meist ein Zeichen für einen Strukturbruch in der Stichprobe (ein Regimewechsel, den das Modell mit Mühe als Persistenz anzupassen versucht).
  • Timing-Konvention. Innerhalb der Schleife bewerten wir RtR_t gegen ztz_t und aktualisieren dann QQ mit ztztz_t z_t' für den nächsten Schritt. Dies hält RtR_t als eine Funktion der Information nur bis t1t-1 — kein Look-Ahead. Diesen Off-by-One-Fehler falsch zu machen, ist der mit Abstand häufigste DCC-Bug, und er bläht den In-Sample-Fit stillschweigend auf.
  • Korrelations-Targeting. Wir setzen Qˉ\bar{Q} als die Stichprobenkorrelation ein, statt es zu schätzen. Das ist es, was die Optimierung zweidimensional macht. Der Preis ist, dass Qˉ\bar{Q} die volle Stichprobe verwendet, sodass Sie es in einem strikten Walk-Forward nur auf dem Trainingsfenster neu schätzen müssen (siehe unten).

Schritt 3: Die Korrelations- und Kovarianzpfade rekonstruieren

Sobald a,ba, b fixiert sind, führen Sie die Rekursion noch einmal aus, diesmal unter Speicherung des vollen RtR_t- (und HtH_t-)Pfads, damit nachgelagerte Strategien ihn verwenden können.

def dcc_filter(Z, Sigma, a, b):
    """
    Run the DCC recursion with fixed (a,b) and return the full paths:
      R_path : (T, d, d) conditional correlation matrices
      H_path : (T, d, d) conditional covariance matrices (scaled units)
    Sigma : (T, d) conditional volatilities aligned with Z.
    """
    Z = np.asarray(Z); Sig = np.asarray(Sigma)
    T, d = Z.shape
    Qbar = np.cov(Z, rowvar=False, bias=True)
    dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
    Qbar = dinv @ Qbar @ dinv

    Q = Qbar.copy()
    R_path = np.empty((T, d, d))
    H_path = np.empty((T, d, d))
    for t in range(T):
        q_diag = np.sqrt(np.diag(Q))
        R = Q / np.outer(q_diag, q_diag)
        R_path[t] = R
        Dt = np.diag(Sig[t])          # D_t = diag(sigma_i,t)
        H_path[t] = Dt @ R @ Dt       # H_t = D_t R_t D_t
        z = Z[t]
        Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
    return R_path, H_path

R_path, H_path = dcc_filter(Z, Sigma, a_hat, b_hat)

i, j = symbols.index("BTC"), symbols.index("ETH")
rho_btc_eth = pd.Series(R_path[:, i, j], index=Z.index, name="rho_BTC_ETH")
print(rho_btc_eth.describe())
print("min/max correlation:", rho_btc_eth.min().round(3),
      rho_btc_eth.max().round(3))

Die rho_btc_eth-Reihe ist der Ertrag der gesamten Übung: Statt einer Zahl haben Sie nun eine tägliche Korrelation, die Sie plotten, mit Schwellen versehen oder in eine Strategie einspeisen können. Auf echten Krypto-Daten werden Sie typischerweise sehen, dass sie von etwa 0,5 in ruhigen Phasen bis über 0,9 während Stress reicht — genau die Spanne, die eine einzelne Stichprobenkorrelation wegmittelt.

Ein-Schritt-voraus-Prognose

Für den Live-Handel benötigen Sie das nächste Ht+1H_{t+1} aus jetzt verfügbaren Informationen. Die Volatilitätsseite kommt aus der Ein-Schritt-Prognose jedes arch-Modells; die Korrelationsseite ist eine weitere Runde der Rekursion:

def dcc_forecast_next(Z, a, b, fits, symbols):
    """One-step-ahead H_{t+1} using info through the last observation."""
    Z = np.asarray(Z); T, d = Z.shape
    Qbar = np.cov(Z, rowvar=False, bias=True)
    dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
    Qbar = dinv @ Qbar @ dinv

    Q = Qbar.copy()
    for t in range(T):
        z = Z[t]
        Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
    q_diag = np.sqrt(np.diag(Q))
    R_next = Q / np.outer(q_diag, q_diag)

    sig_next = np.array([
        np.sqrt(fits[s].forecast(horizon=1, reindex=False)
                .variance.iloc[-1, 0])
        for s in symbols
    ])
    Dt = np.diag(sig_next)
    H_next = Dt @ R_next @ Dt
    return R_next, H_next, sig_next

R_next, H_next, sig_next = dcc_forecast_next(Z, a_hat, b_hat, fits, symbols)

Denken Sie daran, dass alles in skalierten (×100) Einheiten ist, weil wir arch auf series * 100 angepasst haben. Teilen Sie die Volatilitäten durch 100 (und die Kovarianzen durch 1002=10,000100^2 = 10{,}000), um zu Roh-Rendite-Einheiten zurückzukehren, bevor Sie eine Strategie speisen. Die Skalierung im Griff zu behalten, ist mühsam, aber eine häufige Quelle stiller Bugs.

Anwendung 1: Eine dynamische Hedge-Ratio für Pairs-Trading

Das klassische marktneutrale Paar — long ein Vermögenswert, short ein beta-gewichteter Betrag eines anderen — steht und fällt mit der Hedge-Ratio β\beta. Schätzen Sie sie per statischer OLS über ein Trainingsfenster, und Sie erben genau das Problem der veralteten Korrelation, um das es in diesem gesamten Artikel geht: Der Hedge, der letztes Quartal das Marktexposure neutralisiert hat, ist dieses Quartal falsch.

DCC liefert Ihnen die Hedge-Ratio als Zeitreihe. Der minimum-varianz-Hedge des ETH-Exposures mittels BTC ist der bedingte Regressionskoeffizient

βt=Covt(rETH,rBTC)Vart(rBTC)=hETH,BTC,tσBTC,t2=ρETH,BTC,tσETH,tσBTC,t\beta_t = \frac{\mathrm{Cov}_t(r_{\text{ETH}}, r_{\text{BTC}})}{\mathrm{Var}_t(r_{\text{BTC}})} = \frac{h_{\text{ETH,BTC},t}}{\sigma_{\text{BTC},t}^2} = \rho_{\text{ETH,BTC},t}\,\frac{\sigma_{\text{ETH},t}}{\sigma_{\text{BTC},t}}

Jeder Term auf der rechten Seite ist eine DCC-Ausgabe. Die Hedge-Ratio bewegt sich aus zwei verschiedenen Gründen, und DCC trennt sie sauber: Die Korrelation ρt\rho_t ändert sich (die Vermögenswerte koppeln oder entkoppeln sich), und das Volatilitätsverhältnis σETH,t/σBTC,t\sigma_{\text{ETH},t}/\sigma_{\text{BTC},t} ändert sich (ein Vermögenswert wird relativ volatiler). Ein Rolling-OLS-Beta verschmiert beide Effekte mit einer Verzögerung zusammen; DCC schreibt sie zu.

def dynamic_hedge_ratio(R_path, Sigma, base="BTC", target="ETH",
                        symbols=symbols, index=Z.index):
    """
    beta_t to hedge `target` exposure with `base`:
        beta_t = rho_t * sigma_target,t / sigma_base,t
    (Scaling cancels in the ratio, so scaled units are fine here.)
    """
    i = symbols.index(target)
    j = symbols.index(base)
    rho = R_path[:, i, j]
    sig = np.asarray(Sigma)
    beta = rho * sig[:, i] / sig[:, j]
    return pd.Series(beta, index=index, name=f"beta_{target}_{base}")

beta_t = dynamic_hedge_ratio(R_path, Sigma)
print(beta_t.describe())

spread = (returns["ETH"] - beta_t.shift(1) * returns["BTC"]).dropna()

Speisen Sie spread in welche Pairs-Engine auch immer Sie betreiben. Der dynamische Hedge erzeugt für sich allein keinen Edge — er macht den Spread, den Sie handeln, über die Zeit hinweg wirklich marktneutral, sodass Ihr Mean-Reversion-Signal nicht durch driftendes gerichtetes Exposure kontaminiert wird. Wenn Sie Pairs-Strategien bauen, fügt sich dies direkt in die Frameworks in Statistische Arbitrage & Pairs-Trading in Krypto und den Distanz-Ansatz für Paare ein und ersetzt deren feste Hedge-Ratio. Die Korrelationsreihe selbst ist auch ein saubererer Input für ein korrelationsbasiertes Paar-Signal als jedes rollierende Fenster — Sie erhalten ein geglättetes, modellkonsistentes ρt\rho_t statt einer verrauschten gefensterten Schätzung.

Zwei Vorsichtsmaßnahmen speziell für den Live-Einsatz von βt\beta_t. Erstens: lag es — handeln Sie auf βt1\beta_{t-1}, niemals auf dem zeitgleichen βt\beta_t, sonst spähen Sie. Zweitens: Eine Hedge-Ratio, die jeden Tag herumpeitscht, erzeugt Umschlag und Gebühren; in Kryptos 24/7-Markt mit Funding-Kosten auf dem Short-Bein kann ein überreaktiver Hedge mehr ausbluten als die Drift, die er korrigiert. Glätten Sie βt\beta_t (ein EWMA, oder balancieren Sie den Hedge nur neu, wenn er über ein Band hinaus wandert) und dimensionieren Sie das Ganze vernünftig — die Positionsdimensionierung auf Basis eines verrauschten Signals ist eine eigene Disziplin, behandelt in Kelly-Kriterium-Dimensionierung.

Anwendung 2: Zeitvariable Portfoliovarianz

Für ein Portfolio mit Gewichtsvektor ww ist die bedingte Varianz

σp,t2=wHtw=ijwiwjρij,tσi,tσj,t\sigma_{p,t}^2 = w'\, H_t\, w = \sum_{i}\sum_{j} w_i w_j\, \rho_{ij,t}\,\sigma_{i,t}\,\sigma_{j,t}

Mit einer statischen Kovarianzmatrix — dem Markowitz-Standard — ist diese Zahl eine Konstante, die Sie einmal berechnet haben und so tun, als wäre sie immer noch wahr. Ist sie nicht. Das Portfoliorisiko atmet mit dem Markt, und es atmet genau dann am heftigsten, wenn Korrelationen hochschnellen, denn in einem Drawdown steigen sowohl die σi,t\sigma_{i,t}-Terme als auch die ρij,t\rho_{ij,t}-Terme gemeinsam an und multiplizieren sich. Ein Portfolio, das in ruhigen Märkten wie 40% annualisierte Volatilität aussah, kann in einer Stresswoche 80%+ laufen, und eine statische Kovarianzmatrix wird Ihnen sagen, dass sich nichts geändert hat.

def portfolio_vol_path(H_path, weights, index=Z.index, unscale=1e4):
    """
    Conditional portfolio volatility sigma_{p,t} = sqrt(w' H_t w).
    H_path is in scaled (x100) units, so covariances carry a 100^2
    factor: divide by unscale=1e4 to return to raw-return variance.
    """
    w = np.asarray(weights)
    var_t = np.einsum("i,tij,j->t", w, H_path, w) / unscale
    return pd.Series(np.sqrt(var_t), index=index, name="port_vol")

w = np.array([0.4, 0.3, 0.2, 0.1])   # BTC, ETH, SOL, BNB
pv = portfolio_vol_path(H_path, w)
pv_annual = pv * np.sqrt(365)
print(pv_annual.describe())

Dieses zeitvariable σp,t\sigma_{p,t} ist der ehrliche Input, den die risikobasierte Allokation braucht. Die Mean-Varianz-Optimierung (Markowitz für Krypto) mit einer statischen Stichproben-Kovarianz optimiert gegen eine Fiktion; sie mit HtH_t (oder dessen kurzfristiger Prognose) zu speisen, macht die Effizienzgrenze selbst zeitvariabel und zwingt den Optimierer, in Regime steigender Korrelation hinein zu de-riskieren, statt erst danach. Risk-Parity- und hierarchische Ansätze — die HRP + CVaR-Pipeline — sind noch empfindlicher gegenüber dem Kovarianz-Input, da die gesamte Allokation eine Funktion der Risikomatrix ist. Und wenn Sie Allokatoren direkt vergleichen, wie in Portfolio-Optimierungsalgorithmen im Vergleich, ist es oft ein größerer Treiber des realisierten Risikos, ob sie statische oder dynamische Kovarianz konsumieren, als die Wahl des Algorithmus.

Die direkte Anwendung ist Volatilitäts-Targeting des gesamten Portfolios: Wählen Sie eine annualisierte Zielvolatilität σ\sigma^{*} und skalieren Sie das Brutto-Exposure jede Periode um σ/σp,t\sigma^{*} / \sigma_{p,t}, sodass das realisierte Risiko grob konstant bleibt, statt in Krisen aufzublähen. Das schließt den Kreis mit Teil 4, der genau diese Regel baut und backtestet.

Anwendung 3: Korrelation als Regime-Signal

Über Hedging und Dimensionierung hinaus trägt die Korrelationsmatrix ein Makro-Signal. Der einzelne nützlichste Skalar, den Sie extrahieren können, ist die durchschnittliche paarweise Korrelation:

ρˉt=2d(d1)i<jρij,t\bar{\rho}_t = \frac{2}{d(d-1)}\sum_{i < j} \rho_{ij,t}

Wenn ρˉt\bar{\rho}_t über das Portfolio steigt, tritt der Markt in ein Risk-off-Regime ein — idiosynkratische Geschichten hören auf zu zählen und alles handelt als ein Makro-Beta. Dies ist der quantitative Fingerabdruck von "Korrelationen gehen in einer Krise gegen 1". Es tendiert dazu, Drawdowns voranzugehen oder mit ihnen zusammenzufallen, was es zu einem verwertbaren Regime-Indikator macht statt zu einer hinterherhinkenden Nachbetrachtung.

def avg_pairwise_corr(R_path, index=Z.index):
    T, d, _ = R_path.shape
    iu = np.triu_indices(d, k=1)          # upper-triangle off-diagonals
    avg = R_path[:, iu[0], iu[1]].mean(axis=1)
    return pd.Series(avg, index=index, name="avg_corr")

avg_corr = avg_pairwise_corr(R_path)

roll_q = avg_corr.rolling(365, min_periods=90).quantile(0.80)
risk_off = (avg_corr > roll_q)

Sie können risk_off als eigenständige Drossel verwenden (Brutto-Exposure kürzen, Stops verbreitern, Mean-Reversion-Strategien einstellen, die überfahren werden, wenn alles gemeinsam trendet) oder als Feature in einem formelleren Regime-Modell. Es passt natürlich zum Hidden-Markov-Ansatz in Regime-Erkennung mit HMMs: Die durchschnittliche DCC-Korrelation ist eine der informativeren Beobachtungsvariablen, die Sie einem HMM übergeben können, weil sie in einer Weise vorausschauend auf systemischen Stress ist, wie es hinterherhinkende Renditen nicht sind. Die ehrliche Einschränkung: Steigende Korrelation sagt Ihnen, dass die Diversifikation versagt, nicht in welche Richtung der Markt geht. Es ist ein Risikosignal, kein Alpha-Signal, und sollte als solches dimensioniert werden — siehe die Asymmetrie von Verlusten und Gewinnen dafür, warum es schlecht endet, ein Risikoregime als gerichtete Wette zu behandeln.

Praktische Überlegungen

Schätzstabilität und Anzahl der Vermögenswerte

DCC skaliert weit besser als BEKK, aber "skaliert" ist nicht "gratis". Die Korrelations-Targeting-Matrix Qˉ\bar{Q} ist eine d×dd \times d-Stichprobenkorrelation, und Stichprobenkorrelationsmatrizen werden schlecht konditioniert, wenn dd sich der Anzahl der Beobachtungen nähert. Mit 4 Vermögenswerten und 1000 Tagen sind Sie fein. Mit 60 Vermögenswerten und 400 Tagen ist Qˉ\bar{Q} nahezu singulär, ihre Inverse in der Likelihood explodiert, und RtR_t kann durch numerisches Rauschen non-PD wandern. Abmilderungen, grob in der Reihenfolge, wie oft Sie sie brauchen werden:

  • Schrumpfen Sie Qˉ\bar{Q} in Richtung eines strukturierten Ziels (Ledoit-Wolf, oder in Richtung der Identität / einer Konstant-Korrelations-Matrix), bevor Sie die Rekursion ausführen. Dies ist der wirkungsvollste Einzelfix für große Portfolios.
  • Gruppieren Sie Vermögenswerte in eine Handvoll Sektoren (Majors, L1s, DeFi, Memes), modellieren Sie innerhalb und über die Sektorebene hinweg, oder führen Sie DCC auf Hauptkomponenten-Faktoren statt auf rohen Vermögenswerten aus.
  • Bevorzugen Sie mehr Daten gegenüber mehr Vermögenswerten. DCC hat einen unstillbaren Appetit auf eine lange, saubere, zeitgleiche Historie — genau das, was junge Token nicht haben.

Realistisch halten Sie direktes DCC auf höchstens ein paar Dutzend Vermögenswerte. Für ein großes Universum ist DCC auf Faktorrenditen plus idiosynkratischen Residuen der Standard-Workaround.

Korrelations-Targeting ist eine Abkürzung mit einem Preis

Das Targeting von Qˉ\bar{Q} macht die Schätzung handhabbar, backt aber die Voll-Stichproben-unbedingte Korrelation in jedes RtR_t ein. In einem strikten Backtest ist dies ein Look-Ahead-Leck: Ihre Korrelationsmatrix am Tag tt "kennt" die durchschnittliche Korrelation der gesamten Stichprobe, einschließlich der Zukunft. Für eine ehrliche Evaluation müssen Sie Qˉ\bar{Q} nur auf dem Trainingsfenster neu schätzen und es out-of-sample fixieren, oder es vorwärts rollen. Dies ist dieselbe Disziplin, die das gesamte Walk-Forward-Optimierungs-Framework durchsetzt, und sie ist leicht versehentlich zu verletzen mit einem bequemen np.cov(Z) über das volle Array — wie es unser Lehrcode oben tut. Korrigieren Sie es, bevor Sie einer einzigen P&L-Zahl trauen.

Neuanpassungs-Kadenz und Look-Ahead-Disziplin

Sie müssen a,ba, b nicht jeden Tag neu optimieren — sie sind stabile Parameter. Eine sinnvolle Produktionskadenz:

  • Schätzen Sie a,ba, b und die univariaten GARCH-Parameter neu wöchentlich oder monatlich.
  • Führen Sie den Filter aus (aktualisieren Sie QtQ_t, σi,t\sigma_{i,t}) jede Periode mit den eingefrorenen Parametern, um frische RtR_t und HtH_t zu erhalten. Filtern ist billig; Anpassen ist es nicht.
  • Prognostizieren Sie immer, glätten Sie nie. Verwenden Sie das aus Information bis t1t-1 gebaute RtR_t, um bei tt zu handeln. Die zweistufige Struktur (Anpassen auf einem Fenster, dann Vorwärtsfiltern) ist das, was Sie ehrlich hält.

Die Lücke zwischen einem DCC-Backtest und Live-Performance ist fast immer ein Look-Ahead-Leck — Voll-Stichproben-Qˉ\bar{Q}, zeitgleiches βt\beta_t oder Neuanpassen auf Daten, die den Trade enthalten, den Sie evaluieren. Die Disziplin, den Backtest an die Live-Bedingungen anzupassen, ist ein eigenes Thema in Backtest-Live-Parität, und DCC ist ein Modell, das Schlampigkeit hier mehr bestraft als die meisten. Wenn nach sauberer Walk-Forward-Evaluation die dynamische Korrelation für Ihre Strategie nichts über eine einfache rollierende Schätzung hinaus beiträgt, ist das ein reales und publizierbares negatives Ergebnis — die Denkweise in ehrliche negative Ergebnisse gilt direkt.

Asymmetrisches DCC (aDCC)

So wie der univariate Leverage-Effekt (Teil 2) bedeutet, dass schlechte Nachrichten die Volatilität stärker anheben als gute Nachrichten, steigen Korrelationen stärker nach gemeinsamen negativen Schocks als nach gemeinsamen positiven. Cappiello, Engle & Sheppard (2006) erfassen dies mit asymmetrischem DCC, indem sie einen Term hinzufügen, der durch das äußere Produkt der Negativteil-standardisierten Residuen zt=min(zt,0)z_t^- = \min(z_t, 0) getrieben wird:

Qt=(QˉaQˉbQˉgNˉ)+azt1zt1+gzt1zt1+bQt1Q_t = (\bar{Q} - a\bar{Q} - b\bar{Q} - g\bar{N}) + a\, z_{t-1} z_{t-1}' + g\, z_{t-1}^- z_{t-1}^{-\prime} + b\, Q_{t-1}

wobei Nˉ=1Ttztzt\bar{N} = \frac{1}{T}\sum_t z_t^- z_t^{-\prime} und g0g \ge 0 den zusätzlichen Korrelationsschub aus gemeinsamen Abwärtsbewegungen misst. Für Krypto, wo Crash-Korrelation das dominante Risiko ist, ist der Asymmetrieterm meist signifikant und den einen zusätzlichen Parameter wert. rmgarch passt aDCC direkt an (model="aDCC"); den ztz_t^--Term zu unserem NumPy-Schätzer hinzuzufügen ist eine unkomplizierte Übung.

Vergleich: DCC gegen die Alternativen

Wo steht DCC unter den Möglichkeiten, wie Sie eine Kovarianzmatrix für ein Krypto-Portfolio erhalten könnten? Die ehrliche Zusammenfassung:

Ansatz Params Skaliert bis Zeitvariables ρ\rho? PD garantiert? Tail-Abhängigkeit?
Stichproben-/rollierende Kovarianz 0 (Fensterlänge) beliebiges dd grob (verzögert, verrauscht) nein (braucht Patching) nein
EWMA (RiskMetrics) 1 (λ\lambda) beliebiges dd ja (einzelner Zerfall) ja nein
CCC-GARCH dd Ränder + Qˉ\bar{Q} Dutzende nein (konstantes RR) ja nein
DCC-GARCH dd Ränder + 2 Dutzende ja ja nein
aDCC-GARCH dd Ränder + 3 Dutzende ja, asymmetrisch ja partiell
BEKK O(d2)O(d^2) 4\le 4 ja (reich) ja nein
VECH O(d4)O(d^4) 3\le 3 ja (am reichsten) schmerzhaft nein
GARCH-Copula dd Ränder + Copula Dutzende (Vines) statische Copula ja ja

Ein paar Lesarten dieser Tabelle:

  • EWMA ist die günstige Baseline, die jeder schlagen sollte, bevor er behauptet, DCC helfe. Es ist im Geiste ein Ein-Parameter-Spezialfall — ein einzelner exponentieller Zerfall, direkt auf die Kovarianz angewandt — und für viele Portfolios ist es verblüffend schwer, es out-of-sample zu übertreffen. Wenn DCC EWMA nicht im sauberen Walk-Forward schlägt, verwenden Sie EWMA.
  • CCC vs DCC ist der ganze Sinn dieses Artikels: dieselbe Faktorisierung, aber CCC friert RR ein und DCC lässt es sich bewegen. Die zwei zusätzlichen Parameter (a,ba, b) sind der gesamte Unterschied, und in Krypto verdienen sie sich ihren Lebensunterhalt.
  • BEKK/VECH erkaufen reichere Dynamik — jede Kovarianz kann auf jeden vergangenen Schock reagieren — aber die Parameterkosten beschränken sie auf winzige Portfolios. Für alles jenseits von 4 Vermögenswerten sind sie keine echte Option.
  • GARCH-Copula ist die einzige Zeile mit einem "ja" unter Tail-Abhängigkeit. Das ist wieder die Komplementarität: DCC modelliert das dynamische Zentrum der gemeinsamen Verteilung, Copulas modellieren ihre statischen Tails. Wenn Ihre Risikofrage lautet "was passiert, wenn alles auf einmal bricht", greifen Sie zur Copula-Pipeline; wenn sie lautet "was ist gerade jetzt meine Hedge-Ratio / Portfoliovarianz", greifen Sie zu DCC.

Der praktische Standard für ein systematisches Krypto-Desk: DCC (oder aDCC) für Hedge-Ratios und dynamische Kovarianz im Zentrum, ein Copula-Overlay für Tail-Risiko und CVaR und EWMA als Plausibilitäts-Baseline, die Sie ehrlich darüber hält, ob sich die zusätzliche Maschinerie auszahlt.

Grenzen

  • Skalare Dynamik. Ein aa und ein bb für alle Paare ist eine starke Restriktion. BTC-ETH und zwei obskure Altcoins teilen dieselbe Anpassungsgeschwindigkeit. Generalized DCC lockert dies, führt aber die Parameterexplosion wieder ein, die DCC vermeiden sollte.
  • Effizienzverlust durch zwei Schritte. Der Quasi-Likelihood-Schätzer ist konsistent, aber nicht vollständig effizient, und naive Standardfehler sind falsch. Verwenden Sie die Engle-Sheppard-Korrektur, wenn Ihnen Inferenz wichtig ist; für die Signalgenerierung genügen die Punktschätzungen.
  • Gauß-Tails standardmäßig. Die einfache Gauß-Quasi-Likelihood unterschätzt das gemeinsame Tail-Risiko. Student-t-Innovationen helfen; für echte Tail-Abhängigkeit (die Wahrscheinlichkeit gleichzeitiger extremer Bewegungen) ist DCC das falsche Werkzeug und ein Copula-Modell das richtige. DCC liefert Ihnen den dynamischen Körper der Korrelation; Copulas liefern den statischen Tail. Ernsthafte Desks verwenden beides.
  • Korrelation ist keine Kausalität und keine Richtung. Steigendes ρˉt\bar{\rho}_t warnt, dass die Diversifikation versagt; es sagt nichts über die Marktrichtung. Überladen Sie ein Risikosignal nicht mit gerichteten Erwartungen.
  • Datenhunger. Alles oben setzt lange, saubere, synchronisierte Historien voraus. Kryptos neueste und interessanteste Token verletzen alle drei.

Zusammenfassung

  • Statische Korrelation ist eine Lüge in Krypto. Korrelationen clustern, persistieren und schießen in Drawdowns gegen 1 — genau dann, wenn die Diversifikation helfen soll. Ein einzelnes Stichproben-ρ^\hat{\rho} mittelt einen Regime-wechselnden Prozess zu einer bedeutungslosen Mitte.
  • Volles multivariates GARCH (VECH, BEKK) skaliert nicht. Die Parameteranzahl wächst mit O(d2)O(d^2); beide sind in der Praxis auf eine Handvoll Vermögenswerte beschränkt.
  • DCC (Engle 2002) faktorisiert das Problem: Ht=DtRtDtH_t = D_t R_t D_t, mit DtD_t aus unabhängigen univariaten GARCH-Anpassungen (Wiederverwendung von Teil 1-2) und RtR_t aus einer Zwei-Parameter-Rekursion. Es skaliert auf Dutzende von Vermögenswerten, weil nur a,ba, b optimiert werden.
  • Die Rekursion Qt=(1ab)Qˉ+azt1zt1+bQt1Q_t = (1-a-b)\bar{Q} + a\,z_{t-1}z_{t-1}' + b\,Q_{t-1}, normalisiert zu RtR_t, erzeugt in jedem Schritt eine gültige positiv definite Korrelationsmatrix, mit a,b>0a,b>0, a+b<1a+b<1.
  • arch macht kein DCC. Passen Sie die Ränder mit arch an, implementieren Sie dann den ~60-Zeilen-NumPy/SciPy-Schätzer hier, oder verwenden Sie mgarch (Python) oder rmgarch (R, die Referenz).
  • Drei konkrete Erträge: eine dynamische Hedge-Ratio βt=ρtσETH,t/σBTC,t\beta_t = \rho_t\,\sigma_{\text{ETH},t}/\sigma_{\text{BTC},t} für Pairs-Trading; eine ehrliche zeitvariable Portfoliovarianz wHtww'H_t w für risikobasierte Allokation; und die durchschnittliche paarweise Korrelation als Risk-off-Regime-Signal.
  • Disziplin ist alles. Das Korrelations-Targeting leckt den Voll-Stichproben-Durchschnitt, also schätzen Sie Qˉ\bar{Q} nur auf Trainingsdaten neu; laggen Sie jede Hedge-Ratio; filtern Sie vorwärts, glätten Sie nie. Walk-Forward-Evaluation ist nicht verhandelbar.
  • aDCC fügt einen Abwärts-Asymmetrieterm hinzu und ist in Krypto meist lohnenswert, wo Crash-Korrelation dominiert.
  • Teil 4 verwendet diese Prognosen, um eine volatilitätsgezielte Strategie zu bauen und zu backtesten.

Referenzen:

  • Engle, R. (2002). Dynamic Conditional Correlation: A Simple Class of Multivariate Generalized Autoregressive Conditional Heteroskedasticity Models. Journal of Business & Economic Statistics, 20(3), 339-350. DOI
  • Engle, R. & Sheppard, K. (2001). Theoretical and Empirical Properties of Dynamic Conditional Correlation Multivariate GARCH. NBER Working Paper 8554. DOI
  • 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. DOI
  • Cappiello, L., Engle, R., & Sheppard, K. (2006). Asymmetric Dynamics in the Correlations of Global Equity and Bond Returns. Journal of Financial Econometrics, 4(4), 537-572. DOI
  • Engle, R. & Kroner, K. (1995). Multivariate Simultaneous Generalized ARCH. Econometric Theory, 11(1), 122-150. DOI
  • Bollerslev, T., Engle, R., & Wooldridge, J. (1988). A Capital Asset Pricing Model with Time-Varying Covariances. Journal of Political Economy, 96(1), 116-131. DOI
  • Galanos, A. (2022). rmgarch: Multivariate GARCH Models. R package. CRAN.
blog.disclaimer

MarketMaker.cc Team

Quantitative Research & Strategy

Discuss in Telegram
Newsletter

Dem Markt einen Schritt voraus

Abonniere unseren Newsletter für exklusive KI-Trading-Einblicke, Marktanalysen und Plattform-Updates.

Wir respektieren deine Privatsphäre. Jederzeit abbestellbar.