Lower Tail Dependence Covariance: private API
PortfolioOptimisers.lower_tail_dependence — Function
lower_tail_dependence(X::MatNum, alpha::Number = 0.05,
ex::FLoops.Transducers.Executor = FLoops.SequentialEx())Compute the lower tail dependence matrix for a set of asset returns.
The lower tail dependence (LTD) between two assets quantifies the probability that both assets experience returns in their respective lower tails (i.e., joint drawdowns or adverse events), given a specified quantile level alpha. This function estimates the LTD matrix for all pairs of assets in the input matrix X, which is particularly useful for risk management and stress testing.
Mathematical definition
For a quantile level $\alpha \in (0,1)$ and $k = \lceil T \alpha \rceil$, let $\hat{q}_i$ denote the empirical $\alpha$-quantile of asset $i$ (the $k$-th order statistic). The lower tail dependence between assets $i$ and $j$ is estimated as:
\[\begin{align} \hat{\lambda}_{ij} &= \frac{1}{k} \sum_{t=1}^{T} \mathbf{1}\left[x_{ti} \leq \hat{q}_i \text{ and } x_{tj} \leq \hat{q}_j\right]\,. \end{align}\]
The resulting matrix is symmetric with entries clamped to $[\sqrt{\varepsilon},\, 1]$, where $\varepsilon$ is the machine epsilon of eltype(X). The floor is not zero. A pair whose tails never coincide is reported as 1.4901161193847656e-8 for a Float64 input, so a caller may divide by an entry or take its logarithm.
Where:
- $\hat{\lambda}_{ij}$: Lower tail dependence estimate between assets $i$ and $j$.
- $T$: Number of observations.
- $\alpha$: Significance level (left tail probability), $\alpha \in (0, 1)$.
- $k = \lceil T \alpha \rceil$: Number of observations in the lower tail.
- $x_{ti}$: Return of asset $i$ at time $t$.
- $\hat{q}_i$: Empirical $\alpha$-quantile of asset $i$.
Algorithm
- Set $k = \lceil T \alpha \rceil$, the number of observations the lower tail holds, and allocate the result as a matrix of zeros. The allocation is
zerosand notundef, so akof zero reaches the caller as zeros and never as uninitialised memory. - When
kis zero, return that zero matrix.# Validationstates the two cases that reach this branch. - Copy
X, and partially sort each column of the copy about positionk. Positionkof the sorted column is the $k$-th order statistic, which is the empirical $\alpha$-quantile of that asset. - Build the whole boolean mask, one column at a time: entry
(t, j)is true when $x_{tj}$ is at or below the quantile of step 3. The mask is complete before any pair is counted, because the pair loop of step 5 reads a column of lower index than the one it writes. - For each pair $(i, j)$ with $i \leq j$, count the observations whose two mask entries are both true, divide that count by
k, and clamp the ratio to $[\sqrt{\varepsilon},\, 1]$. Write the clamped value into bothrho[i, j]andrho[j, i]. The executorexruns this loop.
Arguments
X: Data matrix of asset returns (observations × assets).alpha: Quantile level for the lower tail.ex: Parallel execution strategy.
Validation
ceil(Int, T * alpha) > 0. The count is zero in exactly two cases, and the function then returns a zero matrix rather than an estimate:alphais exactly0, orXcarries no observation. No small positivealphareaches this branch.ceilof any positive real is at least1, soalpha = nextfloat(0.0)on a matrix of one or more observations still selects one observation.LowerTailDependenceCovariancerules the first case out at construction, becauseassert_unit_intervalrequires0 < alpha < 1.
Returns
rho::Matrix{<:Number}: Symmetric matrix of lower tail dependence coefficients, whererho[i, j]is the estimated LTD between assetsiandj. The diagonal is exactly1, and every entry lies in $[\sqrt{\varepsilon},\, 1]$.
Related