Vine Copulas

C-vine and D-vine decompositions for multi-market tail risk

Vine copulas extend bivariate copula modeling to three or more markets. Instead of fitting one giant multivariate copula (which forces a single dependence shape on all pairs), vines decompose the joint distribution into a tree of bivariate copulas, each of which can be a different family. This lets you capture the fact that markets A and B crash together (Clayton) while B and C rally together (Gumbel).

API

Fit a vine

python
import numpy as np

# Returns matrix: rows = observations, columns = markets
returns = np.column_stack([returns_a, returns_b, returns_c, returns_d])

vine = hz.fit_vine(returns, vine_type="c-vine")

vine.tree_structure   # list of tree levels with pair assignments
vine.pair_copulas     # dict mapping (i, j) -> {family, param, tau}
vine.log_lik          # total log-likelihood
vine.aic              # model AIC

Vine types

  • C-vine (canonical vine): one central node per tree level. Use when one market dominates the dependence structure (e.g., SPY drives everything).
  • D-vine (drawable vine): sequential chain. Use when markets have a natural ordering (e.g., along a yield curve or a supply chain).
python
# C-vine: SPY as the center
vine_c = hz.fit_vine(returns, vine_type="c-vine")

# D-vine: sequential pairing
vine_d = hz.fit_vine(returns, vine_type="d-vine")

Risk monitoring

python
monitor = hz.vine_risk_monitor()

# Configure with a fitted vine
monitor.set_vine(vine)

# On new data, compute joint tail probability
joint_tail = monitor.joint_tail_prob(
    quantiles=[0.05, 0.05, 0.05, 0.05]  # all four markets in 5th percentile
)

# Conditional dependence
cond = monitor.conditional_dependence(
    target=0,         # market index
    given={1: 0.02},  # conditioning: market 1 at 2nd percentile
)

Tree structure example

For four markets (A, B, C, D) in a C-vine with A as center:

Tree 1:  A-B    A-C    A-D        (3 bivariate copulas)
Tree 2:  B-C|A  B-D|A             (2 conditional copulas)
Tree 3:  C-D|AB                   (1 conditional copula)

Each edge is a bivariate copula fitted to (possibly conditional) uniform margins. The vine captures 6 pairwise dependence structures with only 6 bivariate fits.

When to use

  • Multi-market tail risk: compute the probability that 3+ correlated markets all crash simultaneously, accounting for asymmetric tail dependence.
  • Portfolio stress testing: condition on one market dropping to its 5th percentile and compute the implied distribution of the rest.
  • Prediction market contagion: election outcomes, sports events, or crypto markets often have dependence structures that change across the distribution. A vine captures this without forcing Gaussian assumptions.
python
# Stress test: what happens to markets C, D if A drops to 1st percentile?
stressed = monitor.conditional_dependence(
    target=2,          # market C
    given={0: 0.01},   # market A at 1st percentile
)
print(f"P(C < 5th pct | A at 1st pct) = {stressed.prob_below_05:.3f}")

Next