Vine Copulas
Vine copulas extend bivariate copulas to model dependence among three or more markets. Where a single bivariate copula captures the relationship between two markets, a vine copula decomposes a high-dimensional dependence structure into a cascade of bivariate copulas arranged in a tree structure. Horizon implements both C-vine (canonical) and D-vine (drawable) constructions. All computation runs in Rust via PyO3.C-Vine
Star-shaped tree with a central node. Best when one market dominates the dependence structure.
D-Vine
Path-shaped tree. Best when markets form a sequential dependence chain.
Tail Risk
Compute joint tail probabilities across many markets simultaneously.
Pipeline Integration
hz.vine_risk_monitor() tracks multi-market tail risk in real time within hz.run().Why Vine Copulas?
Bivariate copulas work well for pairs of markets, but portfolio risk depends on the joint behavior of many markets simultaneously. The challenge is that most multivariate copula families (e.g., multivariate Gaussian, multivariate t) impose a single dependence structure across all pairs. Vine copulas solve this by:- Pair-by-pair flexibility: each pair of markets can have its own copula family (Clayton for one pair, Gumbel for another)
- Tail dependence heterogeneity: some pairs can exhibit lower-tail dependence while others exhibit upper-tail dependence
- Scalability: the vine structure decomposes an n-dimensional problem into n*(n-1)/2 bivariate problems
Vine copulas build on the bivariate copula module. See the Copula Dependence page for details on the underlying copula families (Gaussian, Clayton, Gumbel, Frank).
API
VineType Enum
| Variant | Tree Structure | Best For |
|---|---|---|
CVine | Star-shaped: one central node per tree level | Markets dominated by a single driver (e.g., BTC drives alts) |
DVine | Path-shaped: sequential chain per tree level | Markets with sequential dependence (e.g., election timeline) |
hz.fit_vine
Fit a vine copula to multivariate uniform data. The function selects the best bivariate copula family for each pair from Gaussian, Clayton, Gumbel, and Frank.| Parameter | Type | Description |
|---|---|---|
data | list[list[float]] | N lists of uniform marginals, each of length T. All values in (0, 1). |
vine_type | VineType | CVine or DVine |
VineCopulaResult.
VineCopulaResult Type
| Field | Type | Description |
|---|---|---|
vine_type | VineType | The vine structure used |
n_dimensions | int | Number of variables (markets) |
pair_copulas | list[PairCopula] | All fitted pair copulas in the vine |
log_likelihood | float | Total log-likelihood of the vine |
aic | float | AIC of the full vine model |
tree_order | list[int] | Variable ordering used in the vine |
PairCopula Type
Each pair copula in the vine decomposition.| Field | Type | Description |
|---|---|---|
tree | int | Tree level (0-indexed; tree 0 has unconditional pairs) |
var_a | int | First variable index |
var_b | int | Second variable index |
conditioned_on | list[int] | Variables conditioned on (empty for tree 0) |
family | str | Best-fit copula family name |
parameter | float | Fitted copula parameter |
kendall_tau | float | Implied Kendall’s tau |
log_likelihood | float | Log-likelihood for this pair |
Sampling
hz.vine_sample
Generate multivariate correlated samples from a fitted vine copula.| Parameter | Type | Description |
|---|---|---|
vine | VineCopulaResult | A fitted vine copula from fit_vine() |
n | int | Number of samples to generate |
seed | int | Random seed for reproducibility (optional) |
list[tuple[float, ...]]: n samples, each of dimension vine.n_dimensions.
Tail Risk
hz.vine_tail_risk
Compute joint tail probabilities from a fitted vine copula. Estimates the probability that all (or a subset of) markets simultaneously fall below (or exceed) specified quantiles.| Parameter | Type | Description |
|---|---|---|
vine | VineCopulaResult | A fitted vine copula |
quantile | float | Quantile threshold in (0, 1) |
direction | str | "lower" (all below quantile) or "upper" (all above quantile) |
n_simulations | int | Monte Carlo sample count (default: 100000) |
seed | int | Random seed (optional) |
float: estimated joint tail probability.
Joint tail probabilities are estimated via Monte Carlo simulation from the fitted vine. Increase
n_simulations for more precise estimates of rare tail events. For a 4-market joint 5% tail event, 100,000 simulations typically provide 2 significant digits of precision.Pipeline Integration
hz.vine_risk_monitor
Pipeline function that fits a vine copula across all monitored markets and injects tail risk metrics intoctx.params["vine_risk"].
ctx.params["vine_risk"] dict contains:
| Key | Type | Description |
|---|---|---|
vine_type | str | Vine structure used ("CVine" or "DVine") |
n_markets | int | Number of markets in the vine |
joint_lower_tail_10pct | float | Joint probability all markets below 10th percentile |
joint_upper_tail_90pct | float | Joint probability all markets above 90th percentile |
max_pairwise_tau | float | Strongest pairwise Kendall’s tau in the vine |
aic | float | AIC of the fitted vine model |
last_refit | float | Timestamp of the last vine refit |
C-Vine vs D-Vine
When to Use C-Vine
C-vine (canonical vine) uses a star-shaped tree where one central variable is connected to all others at each level. Use C-vine when:- One market dominates the dependence structure (e.g., BTC in crypto prediction markets)
- You want to condition all other pairwise relationships on the most connected market
- The most correlated variable can be identified a priori
When to Use D-Vine
D-vine (drawable vine) uses a path-shaped tree where variables form a sequential chain. Use D-vine when:- Markets have a natural ordering (e.g., sequential election primaries)
- Dependence is strongest between “neighboring” markets
- No single variable dominates the dependence structure
Mathematical Background
Vine Decomposition
Vine Decomposition
Bedford and Cooke (2001) showed that any n-dimensional copula density can be decomposed into a product of n*(n-1)/2 bivariate copula densities arranged in a nested tree structure called a regular vine (R-vine).For n=4, the decomposition produces 6 pair copulas across 3 tree levels:
- Tree 1: 3 unconditional pairs
- Tree 2: 2 conditional pairs (conditioned on 1 variable)
- Tree 3: 1 conditional pair (conditioned on 2 variables)
Conditional Copulas
Conditional Copulas
Beyond tree 0, pair copulas are fit to conditional distributions. The conditional CDF F(x|z) is computed using the h-function:
h(u|v; theta) = dC(u,v; theta) / dvEach bivariate copula family has a closed-form h-function. The h-function transforms observations to conditional uniform marginals, which are then used to fit the next tree level.Model Selection
Model Selection
At each edge of the vine,
fit_vine evaluates all four copula families (Gaussian, Clayton, Gumbel, Frank) and selects the best by AIC. This means different edges can use different families, providing maximum flexibility. The total vine AIC is the sum of all pair copula AICs.Tail Risk Computation
Tail Risk Computation
Joint tail probabilities are computed via Monte Carlo simulation from the fitted vine. The vine sampling algorithm (Aas et al., 2009) proceeds sequentially through the tree levels:
- Sample the first variable uniformly
- For each subsequent variable, sample conditionally using the inverse h-function
- Count the fraction of samples where all variables fall below (or above) the specified quantile