← Retour aux articles
March 30, 2026
5 min de lecture

Modèles de copules pour la modélisation conjointe du risque dans les portefeuilles crypto

Modèles de copules pour la modélisation conjointe du risque dans les portefeuilles crypto
#risk
#copula
#portfolio
#tail-dependence
#VaR
📊
Part 4 of 5 · Collection
Portfolio Construction & Risk

Modèles de copules — distribution conjointe du risque

La corrélation est le premier outil auquel recourent la plupart des gestionnaires de portefeuille pour évaluer la diversification. Mais sur les marchés crypto, la corrélation est dangereusement trompeuse. Deux tokens peuvent afficher une corrélation de Pearson de 0,3 en période calme, puis grimper à 0,95 lors d'un krach. La corrélation linéaire suppose des distributions elliptiques — une hypothèse qui s'effondre face aux queues épaisses et aux structures de dépendance asymétriques propres aux rendements des cryptomonnaies.

Les modèles de copules résolvent ce problème en séparant le comportement marginal (comment chaque actif se comporte individuellement) de la structure de dépendance (comment les actifs évoluent ensemble). Cette séparation, ancrée dans le théorème de Sklar, nous offre un cadre flexible pour modéliser la distribution conjointe complète des rendements du portefeuille — y compris les queues, là où réside réellement le risque.

Pourquoi la corrélation linéaire échoue pour la crypto

Considérons un portefeuille composé de BTC, ETH, SOL et AVAX. Lors de l'effondrement de Terra/Luna en mai 2022, les corrélations entre ces actifs ont convergé vers 1,0, précisément au moment où la diversification était la plus nécessaire. Un optimiseur moyenne-variance supposant des corrélations stables aurait considérablement sous-estimé le risque du portefeuille.

Les problèmes fondamentaux de la corrélation de Pearson pour la crypto :

  1. Distributions non elliptiques. Les rendements crypto présentent une asymétrie et un kurtosis significatifs. Les rendements journaliers du BTC affichent régulièrement des valeurs de kurtosis supérieures à 10 (distribution normale : 3).
  2. Dépendance asymétrique. Les actifs ont tendance à être plus corrélés lors des baisses que lors des hausses. Ce phénomène de « rupture de corrélation » est bien documenté sur les marchés actions et est encore plus prononcé en crypto.
  3. Dépendance de queue. La probabilité que deux actifs subissent simultanément des pertes extrêmes n'est pas capturée par la corrélation linéaire. Deux actifs peuvent avoir une corrélation identique mais une dépendance de queue radicalement différente.

Le théorème de Sklar : le fondement

Le théorème de Sklar (1959) énonce que toute distribution conjointe multivariée F(x1,x2,,xd)F(x_1, x_2, \ldots, x_d) peut être décomposée en :

F(x1,x2,,xd)=C(F1(x1),F2(x2),,Fd(xd))F(x_1, x_2, \ldots, x_d) = C\bigl(F_1(x_1), F_2(x_2), \ldots, F_d(x_d)\bigr)

où les FiF_i sont les fonctions de distribution marginales et C:[0,1]d[0,1]C: [0,1]^d \to [0,1] est la copule — une fonction qui encode toute la structure de dépendance entre les variables.

Réciproquement, si les marginales sont continues, la copule CC est unique.

Cette décomposition est puissante car elle permet de :

  • Modéliser la distribution marginale de chaque actif séparément (via GARCH, EVT, ou toute distribution appropriée)
  • Modéliser la structure de dépendance indépendamment via la copule
  • Combiner les deux pour obtenir la distribution conjointe complète

La densité de la distribution conjointe se factorise ainsi :

f(x1,,xd)=c(F1(x1),,Fd(xd))i=1dfi(xi)f(x_1, \ldots, x_d) = c\bigl(F_1(x_1), \ldots, F_d(x_d)\bigr) \cdot \prod_{i=1}^{d} f_i(x_i)

cc est la densité de la copule et fif_i les densités marginales.

Familles de copules et leurs propriétés

Comparaison de la dépendance de queue entre familles de copules

Copule gaussienne

La copule gaussienne est paramétrée par une matrice de corrélation Σ\Sigma :

CΣGauss(u1,,ud)=ΦΣ(Φ1(u1),,Φ1(ud))C_{\Sigma}^{\text{Gauss}}(u_1, \ldots, u_d) = \Phi_{\Sigma}\bigl(\Phi^{-1}(u_1), \ldots, \Phi^{-1}(u_d)\bigr)

ΦΣ\Phi_{\Sigma} est la CDF normale multivariée et Φ1\Phi^{-1} la fonction quantile normale univariée.

Dépendance de queue : λL=λU=0\lambda_L = \lambda_U = 0 (pour ρ<1\rho < 1).

La copule gaussienne présente une dépendance de queue nulle — elle sous-estime systématiquement la probabilité d'événements extrêmes conjoints. Ce fut un facteur clé de la mauvaise évaluation des CDO avant 2008, et c'est tout aussi dangereux pour la modélisation du risque crypto.

Copule t de Student

La copule t introduit une dépendance de queue symétrique via un paramètre de degrés de liberté ν\nu :

Cν,Σt(u1,,ud)=tν,Σ(tν1(u1),,tν1(ud))C_{\nu, \Sigma}^{t}(u_1, \ldots, u_d) = t_{\nu, \Sigma}\bigl(t_{\nu}^{-1}(u_1), \ldots, t_{\nu}^{-1}(u_d)\bigr)

Dépendance de queue :

λL=λU=2tν+1((ν+1)(1ρ)1+ρ)\lambda_L = \lambda_U = 2 \cdot t_{\nu+1}\left(-\sqrt{\frac{(\nu+1)(1-\rho)}{1+\rho}}\right)

Pour ν=4\nu = 4 et ρ=0,5\rho = 0,5, cela donne λ0,18\lambda \approx 0,18 — une probabilité de 18 % que les deux actifs se trouvent simultanément dans leur pire quantile. Un ν\nu plus faible (queues plus épaisses) augmente cette probabilité. Les marchés crypto, avec leurs rendements à queue épaisse, nécessitent généralement un ν\nu situé entre 3 et 8.

La copule t constitue une amélioration significative par rapport à la gaussienne, mais elle impose une dépendance de queue symétrique (λL=λU\lambda_L = \lambda_U). En pratique, les actifs crypto présentent souvent une dépendance de queue inférieure plus forte (chute conjointe) que de queue supérieure (hausse conjointe).

Copule de Clayton

La copule de Clayton capture la dépendance de queue inférieure — exactement le type de comportement asymétrique de regroupement en cas de krach observé en crypto :

CθClayton(u1,u2)=(u1θ+u2θ1)1/θ,θ>0C_{\theta}^{\text{Clayton}}(u_1, u_2) = \left(u_1^{-\theta} + u_2^{-\theta} - 1\right)^{-1/\theta}, \quad \theta > 0

Dépendance de queue : λL=21/θ\lambda_L = 2^{-1/\theta}, λU=0\lambda_U = 0.

Lorsque θ\theta augmente, la dépendance de queue inférieure se renforce. Pour θ=2\theta = 2, λL0,71\lambda_L \approx 0,71 — une probabilité très élevée de pertes extrêmes conjointes.

Copule de Gumbel

La copule de Gumbel en est l'image miroir — elle capture la dépendance de queue supérieure :

CθGumbel(u1,u2)=exp([(lnu1)θ+(lnu2)θ]1/θ),θ1C_{\theta}^{\text{Gumbel}}(u_1, u_2) = \exp\left(-\left[(-\ln u_1)^{\theta} + (-\ln u_2)^{\theta}\right]^{1/\theta}\right), \quad \theta \geq 1

Dépendance de queue : λL=0\lambda_L = 0, λU=221/θ\lambda_U = 2 - 2^{1/\theta}.

Copule de Frank

La copule de Frank présente une dépendance de queue nulle dans les deux queues (λL=λU=0\lambda_L = \lambda_U = 0), ce qui la rend adaptée pour modéliser la dépendance dans le corps de la distribution sans effets de queue :

CθFrank(u1,u2)=1θln(1+(eθu11)(eθu21)eθ1)C_{\theta}^{\text{Frank}}(u_1, u_2) = -\frac{1}{\theta}\ln\left(1 + \frac{(e^{-\theta u_1}-1)(e^{-\theta u_2}-1)}{e^{-\theta}-1}\right)

Choisir la bonne copule pour la crypto

Pour les portefeuilles crypto, les preuves empiriques suggèrent :

  • Clayton ou Gumbel inversée (survival Gumbel) pour la dépendance de queue inférieure — capturant la contagion des krachs
  • La copule t comme choix robuste et polyvalent lorsque la dépendance de queue symétrique est acceptable
  • La copule de Joe pour capturer une forte dépendance de queue supérieure lors des phases haussières

Une étude de Bruhn et Jeleskovic (2024) a montré que les modèles GARCH-copule, en particulier ceux utilisant des marginales t de Student combinées à des copules t, surpassaient systématiquement les approches moyenne-variance et CVaR historique sur les périodes de baisse (2022), de reprise (2023) et de stabilité (2024) en crypto.

La malédiction de la dimensionnalité : les copules vigne entrent en jeu

Structure arborescente d'une copule vigne pour un portefeuille crypto

Les copules multivariées standard (gaussienne, t) s'adaptent aux dimensions élevées mais imposent des hypothèses restrictives. Les copules archimédiennes (Clayton, Gumbel, Frank) sont naturellement bivariées — les étendre à des dimensions d>2d > 2 exige que toutes les paires partagent le même paramètre de dépendance, ce qui n'est pas réaliste.

Les copules vigne résolvent ce problème en décomposant une copule à dd dimensions en une cascade de copules bivariées organisées selon une structure arborescente. Chaque paire de variables (conditionnellement aux autres) obtient sa propre famille de copule bivariée et son propre paramètre.

La construction par paires de copules

Pour une densité à dd dimensions, la factorisation de la copule vigne s'écrit :

f(x1,,xd)=i=1dfi(xi)j=1d1i=1djci,i+ji+1,,i+j1f(x_1, \ldots, x_d) = \prod_{i=1}^{d} f_i(x_i) \cdot \prod_{j=1}^{d-1}\prod_{i=1}^{d-j} c_{i,i+j|i+1,\ldots,i+j-1}

ci,jSc_{i,j|S} est une densité de copule bivariée pour les variables ii et jj conditionnées à l'ensemble SS.

Une copule vigne à dd dimensions nécessite (d2)=d(d1)/2\binom{d}{2} = d(d-1)/2 copules bivariées. Pour un portefeuille crypto de 10 actifs, cela représente 45 copules de paires — chacune potentiellement issue d'une famille différente.

Structures vigne : C-vine, D-vine, R-vine

C-vine (vigne canonique) : Chaque arbre possède un unique nœud racine relié à tous les autres nœuds. Optimal lorsqu'une variable domine — par exemple, le BTC comme moteur du marché.

Tree 1:    BTC --- ETH
           BTC --- SOL
           BTC --- AVAX
           BTC --- DOT

Tree 2:    ETH|BTC --- SOL|BTC
           ETH|BTC --- AVAX|BTC
           ETH|BTC --- DOT|BTC

D-vine (vigne dessinable) : Une structure de chemin séquentiel. Optimale lorsque les variables ont un ordre naturel (par exemple, par capitalisation boursière ou secteur).

R-vine (vigne régulière) : La structure la plus générale — toute séquence d'arbres valide. Les R-vines englobent à la fois les C-vines et les D-vines.

Les recherches sur les portefeuilles de cryptomonnaies suggèrent que les structures D-vine produisent souvent des prévisions de VaR supérieures à celles des C-vine et R-vine pour les actifs crypto, bien que cela dépende de la composition spécifique du portefeuille.

Pourquoi les copules vigne comptent pour la crypto

Un portefeuille de 8 actifs crypto modélisé avec une unique copule de Clayton force les 28 paires à partager le même θ\theta. Mais BTC-ETH pourrait avoir θClayton=3,5\theta_{\text{Clayton}} = 3,5 (forte dépendance en cas de krach) tandis que SOL-AVAX pourrait avoir θ=1,2\theta = 1,2 (modérée). Les copules vigne permettent à chaque paire d'exprimer sa propre structure de dépendance :

  • BTC-ETH : copule t (ν=4\nu=4, ρ=0,72\rho=0,72)
  • BTC-SOL : Clayton (θ=2,1\theta=2,1)
  • ETH-AVAX : Frank (θ=5,3\theta=5,3)
  • SOL-DOT | BTC : Gumbel (θ=1,8\theta=1,8)

Cette flexibilité est essentielle pour une estimation précise du risque de portefeuille.

Modélisation des marginales : GARCH-EVT

Avant d'ajuster la copule, il faut transformer la série de rendements de chaque actif en variables uniformes [0,1][0,1] (la « transformée intégrale de probabilité »). Le pipeline standard :

  1. Ajuster un modèle GARCH à la série de rendements de chaque actif pour capturer la volatilité variant dans le temps
  2. Extraire les résidus standardisés zt=(rtμt)/σtz_t = (r_t - \mu_t) / \sigma_t
  3. Ajuster les queues à l'aide de la théorie des valeurs extrêmes (EVT) — plus précisément, la distribution de Pareto généralisée (GPD) pour les queues supérieure et inférieure au-delà d'un seuil (typiquement les 5e et 95e centiles)
  4. Utiliser la CDF empirique pour le corps de la distribution
  5. Appliquer la transformée intégrale de probabilité pour obtenir des observations pseudo-uniformes ui,t=F^i(zi,t)u_{i,t} = \hat{F}_i(z_{i,t})

Cette approche GARCH-EVT est souvent appelée méthode « semi-paramétrique ». Elle capture correctement :

  • Le regroupement de la volatilité (GARCH)
  • Les queues épaisses (GPD issue de l'EVT)
  • La forme globale de la distribution (CDF empirique pour le corps)

Pour les actifs crypto, un modèle EGARCH(1,1) ou GJR-GARCH(1,1) avec innovations t de Student fonctionne généralement bien, car il capture la réponse de volatilité asymétrique (les mauvaises nouvelles augmentent davantage la volatilité que les bonnes).

VaR et CVaR de portefeuille avec les copules

Value-at-Risk (VaR)

La VaR du portefeuille au niveau de confiance α\alpha est :

VaRα=inf{l:P(Ll)α}\text{VaR}_\alpha = \inf\{ l : P(L \leq l) \geq \alpha \}

LL est la perte du portefeuille. Avec les copules, on estime la VaR par Monte Carlo :

  1. Simuler NN échantillons à partir de la copule vigne ajustée (dans l'espace uniforme)
  2. Retransformer vers l'espace des rendements à l'aide des CDF marginales inverses
  3. Calculer les rendements du portefeuille : rp=iwirir_p = \sum_i w_i \cdot r_i
  4. La VaR est le quantile α\alpha de la distribution simulée des pertes du portefeuille

Conditional Value-at-Risk (CVaR / Expected Shortfall)

La CVaR est la perte attendue sachant que la perte dépasse la VaR :

CVaRα=E[LLVaRα]=11αα1VaRudu\text{CVaR}_\alpha = E[L \mid L \geq \text{VaR}_\alpha] = \frac{1}{1-\alpha}\int_{\alpha}^{1}\text{VaR}_u\, du

La CVaR est cohérente (elle satisfait la sous-additivité), ce qui la rend supérieure à la VaR pour l'optimisation de portefeuille. L'estimation par Monte Carlo est directe — il suffit de moyenner les pertes qui dépassent la VaR.

Pourquoi le risque fondé sur les copules surpasse le risque fondé sur la corrélation

Considérons deux portefeuilles avec des corrélations par paires identiques de 0,5 :

  • Portefeuille A : dépendance de copule gaussienne (aucune dépendance de queue)
  • Portefeuille B : dépendance de copule de Clayton (θ=2\theta = 2, λL=0,71\lambda_L = 0,71)

Au niveau de confiance de 99 %, le portefeuille B affichera une VaR et une CVaR significativement plus élevées, car la copule de Clayton modélise correctement la tendance des actifs à chuter ensemble. La copule gaussienne sous-estime ce risque en supposant que les co-mouvements extrêmes sont d'une rareté insignifiante.

Dans les études empiriques sur les portefeuilles crypto, la différence de CVaR à 99 % entre les modèles gaussien et copule vigne peut dépasser 30 à 40 %, ce qui signifie que les modèles fondés sur la corrélation peuvent sous-estimer le risque de queue d'un tiers ou plus.

Mise en œuvre : Python avec pyvinecopulib

Voici un pipeline complet pour ajuster une copule vigne aux rendements crypto et estimer la VaR/CVaR du portefeuille.

Étape 1 : Préparation des données et ajustement des marginales

import numpy as np
import pandas as pd
from arch import arch_model
from scipy import stats
import pyvinecopulib as pv

def fetch_crypto_returns(symbols, start="2023-01-01", end="2025-12-31"):
    """
    Fetch daily returns for a list of crypto symbols.
    Replace with your data source (ccxt, yfinance, etc.)
    """
    import yfinance as yf
    prices = yf.download(
        [f"{s}-USD" for s in symbols],
        start=start, end=end
    )["Close"]
    prices.columns = symbols
    returns = np.log(prices / prices.shift(1)).dropna()
    return returns

symbols = ["BTC", "ETH", "SOL", "AVAX", "DOT", "LINK", "MATIC", "ATOM"]
returns = fetch_crypto_returns(symbols)

def fit_garch_marginal(series, dist="t"):
    """
    Fit GJR-GARCH(1,1) with Student-t innovations.
    Returns standardized residuals and the fitted model.
    """
    model = arch_model(
        series * 100,  # scale for numerical stability
        vol="GARCH",
        p=1, o=1, q=1,  # GJR-GARCH
        dist=dist,
        mean="AR",
        lags=1
    )
    result = model.fit(disp="off")
    std_resid = result.std_resid.dropna()
    return std_resid, result

residuals = {}
garch_models = {}
for sym in symbols:
    std_resid, model = fit_garch_marginal(returns[sym])
    residuals[sym] = std_resid
    garch_models[sym] = model

residuals_df = pd.DataFrame(residuals).dropna()

Étape 2 : Transformée intégrale de probabilité

def semi_parametric_pit(residuals, tail_threshold=0.05):
    """
    Semi-parametric probability integral transform:
    - GPD for tails beyond threshold
    - Empirical CDF for the body
    Returns pseudo-uniform observations in [0, 1].
    """
    n = len(residuals)
    u = np.zeros(n)
    sorted_resid = np.sort(residuals)

    lower_thresh = np.quantile(residuals, tail_threshold)
    upper_thresh = np.quantile(residuals, 1 - tail_threshold)

    for i, x in enumerate(residuals):
        if x <= lower_thresh:
            lower_exceedances = -(residuals[residuals <= lower_thresh] - lower_thresh)
            shape, _, scale = stats.genpareto.fit(lower_exceedances, floc=0)
            u[i] = tail_threshold * (
                1 - stats.genpareto.cdf(-(x - lower_thresh), shape, scale=scale)
            )
        elif x >= upper_thresh:
            upper_exceedances = residuals[residuals >= upper_thresh] - upper_thresh
            shape, _, scale = stats.genpareto.fit(upper_exceedances, floc=0)
            u[i] = 1 - tail_threshold * (
                1 - stats.genpareto.cdf(x - upper_thresh, shape, scale=scale)
            )
        else:
            u[i] = np.mean(residuals <= x)

    u = np.clip(u, 1e-6, 1 - 1e-6)
    return u

U = np.column_stack([
    semi_parametric_pit(residuals_df[sym].values)
    for sym in symbols
])

Étape 3 : Ajuster la copule vigne

controls = pv.FitControlsVinecop(
    family_set=[
        pv.BicopFamily.student,
        pv.BicopFamily.clayton,
        pv.BicopFamily.gumbel,
        pv.BicopFamily.frank,
        pv.BicopFamily.joe,
        pv.BicopFamily.bb1,       # Clayton-Gumbel mixture
        pv.BicopFamily.bb7,       # Joe-Clayton mixture
        pv.BicopFamily.gaussian,
    ],
    selection_criterion="bic",    # BIC for model selection
    tree_criterion="tau",          # Kendall's tau for tree structure
    nonparametric_method="constant",
    trunc_lvl=5,                   # Truncate after 5 trees
)

vine = pv.Vinecop(U, controls=controls)

print(f"Log-likelihood: {vine.loglik(U):.2f}")
print(f"AIC: {vine.aic(U):.2f}")
print(f"BIC: {vine.bic(U):.2f}")

for i in range(vine.order.shape[0] - 1):
    pair = vine.get_pair_copula(0, i)
    print(f"Tree 1, Edge {i}: {pair.family} "
          f"(params: {pair.parameters})")

Étape 4 : VaR et CVaR par Monte Carlo

def estimate_var_cvar(vine, garch_models, symbols, weights,
                       n_sim=50_000, alpha=0.99, seed=42):
    """
    Estimate portfolio VaR and CVaR using Monte Carlo simulation
    from the fitted vine copula.
    """
    U_sim = vine.simulate(n=n_sim, seeds=[seed])

    returns_sim = np.zeros((n_sim, len(symbols)))
    for j, sym in enumerate(symbols):
        model = garch_models[sym]
        forecasts = model.forecast(horizon=1)
        mu = forecasts.mean.iloc[-1, 0] / 100  # unscale
        sigma = np.sqrt(forecasts.variance.iloc[-1, 0]) / 100

        nu = model.params.get("nu", 5)
        z_sim = stats.t.ppf(U_sim[:, j], df=nu)
        returns_sim[:, j] = mu + sigma * z_sim

    weights = np.array(weights)
    portfolio_returns = returns_sim @ weights

    losses = -portfolio_returns

    var = np.quantile(losses, alpha)

    cvar = np.mean(losses[losses >= var])

    return var, cvar, portfolio_returns

weights = [1.0 / len(symbols)] * len(symbols)

var_99, cvar_99, sim_returns = estimate_var_cvar(
    vine, garch_models, symbols, weights,
    n_sim=100_000, alpha=0.99
)

print(f"1-day 99% VaR:  {var_99*100:.2f}%")
print(f"1-day 99% CVaR: {cvar_99*100:.2f}%")

from scipy.stats import norm
mu_p = sim_returns.mean()
sigma_p = sim_returns.std()
var_gauss = -(mu_p + sigma_p * norm.ppf(0.01))
print(f"\nGaussian VaR:   {var_gauss*100:.2f}%")
print(f"Copula/Gaussian ratio: {var_99/var_gauss:.2f}x")

Étape 5 : Analyse de la dépendance de queue

def compute_tail_dependence(vine, symbols):
    """
    Extract lower and upper tail dependence coefficients
    from the first tree of the vine copula.
    """
    results = []
    order = vine.order
    n_edges = order.shape[0] - 1

    for i in range(n_edges):
        pair = vine.get_pair_copula(0, i)
        u_pair = pair.simulate(n=100_000, seeds=[42])
        q = 0.01  # 1st percentile

        mask_lower = (u_pair[:, 0] <= q)
        lambda_L = np.mean(u_pair[mask_lower, 1] <= q) if mask_lower.sum() > 0 else 0

        mask_upper = (u_pair[:, 0] >= 1 - q)
        lambda_U = np.mean(u_pair[mask_upper, 1] >= 1 - q) if mask_upper.sum() > 0 else 0

        i_idx = order[0]
        j_idx = order[i + 1]
        results.append({
            "pair": f"{symbols[i_idx]}-{symbols[j_idx]}",
            "family": str(pair.family),
            "lambda_L": round(lambda_L, 4),
            "lambda_U": round(lambda_U, 4),
        })

    return pd.DataFrame(results)

tail_dep = compute_tail_dependence(vine, symbols)
print(tail_dep.to_string(index=False))

Un résultat typique pour un portefeuille crypto pourrait ressembler à :

Pair Family λL\lambda_L λU\lambda_U
BTC-ETH student 0.22 0.22
BTC-SOL clayton 0.35 0.00
BTC-AVAX bb7 0.28 0.12
BTC-DOT student 0.18 0.18
BTC-LINK clayton 0.31 0.00
BTC-MATIC frank 0.00 0.00
BTC-ATOM gumbel 0.00 0.15

Remarquez comment chaque paire peut avoir une structure de dépendance totalement différente. BTC-SOL présente une forte dépendance de queue inférieure (Clayton) avec une dépendance de queue supérieure nulle — ils chutent ensemble mais ne montent pas nécessairement ensemble. BTC-MATIC ne présente aucune dépendance de queue (Frank), ce qui suggère un certain bénéfice de diversification même dans les extrêmes.

Backtesting du modèle de VaR par copule

Un modèle de VaR n'est utile que s'il est bien calibré. Le backtest standard calcule les violations de VaR — les jours où la perte réelle a dépassé la VaR prédite — et teste si le taux de violation correspond au taux attendu.

def backtest_var(returns, symbols, weights, window=500,
                 alpha=0.99, n_sim=20_000):
    """
    Rolling-window VaR backtest using vine copula.
    """
    violations = []
    var_series = []
    T = len(returns)

    for t in range(window, T):
        window_returns = returns.iloc[t-window:t]

        U_window = np.zeros((window, len(symbols)))
        models_t = {}
        for j, sym in enumerate(symbols):
            std_resid, model = fit_garch_marginal(window_returns[sym])
            models_t[sym] = model
            u = pv.to_pseudo_obs(std_resid.values.reshape(-1, 1))
            U_window[:len(u), j] = u.ravel()

        U_clean = U_window[~np.any(U_window == 0, axis=1)]
        vine_t = pv.Vinecop(U_clean, controls=controls)

        var_t, _, _ = estimate_var_cvar(
            vine_t, models_t, symbols, weights,
            n_sim=n_sim, alpha=alpha
        )
        var_series.append(var_t)

        actual_return = (returns.iloc[t][symbols].values
                         * np.array(weights)).sum()
        violations.append(-actual_return > var_t)

    violation_rate = np.mean(violations)
    expected_rate = 1 - alpha
    print(f"Expected violation rate: {expected_rate:.4f}")
    print(f"Actual violation rate:   {violation_rate:.4f}")
    print(f"Number of violations:    {sum(violations)} / {len(violations)}")

    return violations, var_series

Un modèle de VaR à 99 % bien calibré devrait avoir un taux de violation proche de 1 %. Si le taux est significativement plus élevé, le modèle sous-estime le risque. S'il est significativement plus faible, il est trop conservateur.

Considérations pratiques

Coût computationnel

L'ajustement d'une copule vigne est de complexité O(d2n)O(d^2 \cdot n) par niveau d'arbre. Pour un portefeuille de 10 actifs avec des fenêtres glissantes de 500 jours, un backtest complet avec 50 000 simulations de Monte Carlo par étape peut prendre des heures. Stratégies de gestion :

  • Vignes tronquées : définir trunc_lvl=3 ou trunc_lvl=4 — les arbres supérieurs capturent des dépendances conditionnelles plus faibles qui contribuent moins au risque
  • Réduction du nombre de simulations : 10 000 à 20 000 simulations suffisent souvent pour une VaR à 99 %
  • Calcul parallèle : les ajustements GARCH de chaque actif sont indépendants et peuvent être parallélisés
  • Mise en cache des modèles : réajuster la copule chaque semaine plutôt que chaque jour, en ne mettant à jour que les prévisions GARCH

Sensibilité au régime

Les marchés crypto présentent des régimes distincts (haussier, baissier, latéral, événements de forte volatilité). Une copule vigne unique ajustée sur l'ensemble de l'échantillon peut ne pas capturer la dépendance liée au régime. Envisager :

  • Des fenêtres glissantes de 250 à 500 jours
  • Des copules à changement de régime, où les paramètres de la copule dépendent d'un état de Markov caché
  • Des observations pondérées exponentiellement, accordant plus de poids aux données récentes

Pièges courants

  1. Oublier le PIT. Injecter directement les rendements bruts dans la copule au lieu des observations pseudo-uniformes produit des résultats dénués de sens. Toujours transformer d'abord en marginales uniformes.
  2. Surapprentissage avec trop de familles. Inclure toutes les familles bivariées possibles dans l'ensemble de sélection peut conduire à un surapprentissage, surtout avec des échantillons courts. Utiliser le BIC pour la sélection du modèle et envisager de se limiter à 4-5 familles.
  3. Ignorer la dépendance sérielle. Les copules modélisent la dépendance transversale à un instant donné. Si l'on saute l'étape GARCH et que l'on injecte des rendements autocorrélés dans la copule, la dépendance estimée sera contaminée par des effets sériels.
  4. Copules statiques dans des marchés dynamiques. Une copule ajustée sur les données du marché haussier de 2021 sera mal calibrée pour un krach de 2022. Toujours utiliser des fenêtres glissantes ou extensibles.

Conclusion

Les modèles de copules — en particulier les copules vigne — offrent un cadre mathématiquement rigoureux pour modéliser le risque conjoint des portefeuilles crypto, allant bien au-delà de ce que la corrélation linéaire peut capturer. Les avantages clés :

  • Modélisation séparée des marginales et de la dépendance via le théorème de Sklar
  • Dépendance de queue flexible grâce à un choix approprié de la famille de copule (Clayton pour la contagion des krachs, Gumbel pour le co-mouvement haussier, copule t pour les queues symétriques)
  • Scalabilité en haute dimension grâce à la décomposition en copule vigne, où chaque paire d'actifs obtient sa propre copule bivariée
  • Estimation précise de la VaR/CVaR tenant compte de la dépendance non linéaire et asymétrique — essentielle pour la gestion des risques sur un marché où « tout s'effondre ensemble » est la norme, non l'exception

Le pipeline GARCH-EVT-Copule est désormais l'approche standard dans les fonds spéculatifs quantitatifs et les bureaux de risque spécialisés en crypto. Grâce à des bibliothèques comme pyvinecopulib, la barrière à l'implémentation est suffisamment basse pour que tout trader systématique puisse intégrer la modélisation du risque par copules dans son flux de gestion de portefeuille.

Le code présenté dans cet article constitue un point de départ fonctionnel. Pour une utilisation en production, on ajouterait une validation croisée appropriée pour la sélection de l'ordre GARCH, des modèles marginaux plus sophistiqués (par exemple, EGARCH avec effets de levier, ou des mesures de volatilité réalisée à partir de données intrajournalières), ainsi que des tests de résistance sous des paramètres de copule hypothétiques calibrés sur des épisodes de crise historiques.


Références

  • Sklar, A. (1959). Fonctions de repartition a n dimensions et leurs marges. Publications de l'Institut de Statistique de l'Universite de Paris, 8, 229-231.
  • Joe, H. (2014). Dependence Modeling with Copulas. Chapman and Hall/CRC.
  • Aas, K., Czado, C., Frigessi, A., & Bakken, H. (2009). Pair-copula constructions of multiple dependence. Insurance: Mathematics and Economics, 44(2), 182-198.
  • Jeleskovic, V. & Bruhn, L. (2024). Cryptocurrency portfolio optimization: Utilizing a GARCH-Copula model within the Markowitz framework. Journal of Corporate Accounting & Finance.
  • Nagler, T. & Vatter, T. (2023). pyvinecopulib: A Python library for vine copula models. GitHub.
  • Tiwari, A. K., et al. (2020). Modeling risk dependence and portfolio VaR forecast through vine copula for cryptocurrencies. PLOS ONE, 15(1), e0242102.
blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Gardez une longueur d'avance sur le marché

Abonnez-vous à notre newsletter pour des insights exclusifs sur le trading IA, des analyses de marché et des mises à jour de la plateforme.

Nous respectons votre vie privée. Désabonnement possible à tout moment.