Cross-Sectional Idiosyncratic Diagnostics
Functions
PortfolioOptimisers.standardised_idio_returns — Function
standardised_idio_returns(eps::MatNum, vs::MatNum) -> Matrix{<:Real}Return the standardised idiosyncratic returns of a cross-sectional fit.
It is the level-0 kernel of the idiosyncratic group. Every calibration series of this file reads it: the fit predicted a variance for each asset at each observation, and the standardised return states how large the realised return was against that prediction. A well calibrated fit leaves a cross-section of standardised returns whose standard deviation is 1.
Mathematical definition
\[z_{ti} = \frac{\varepsilon_{ti}}{\sqrt{\max(v_{ti}, 0)}}\]
Where:
- $\varepsilon_{ti}$: Idiosyncratic return of asset $i$ at observation $t$.
- $v_{ti}$: Idiosyncratic variance predicted for asset $i$ at observation $t$.
Arguments
eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.
Validation
!isempty(eps).size(vs) == size(eps).
Returns
z::Matrix{<:Real}: Standardised idiosyncratic returnsobservations × assets. An entry whose predicted volatility is zero, or whose return is not finite, isNaN.
Examples
julia> standardised_idio_returns([1.0 -2.0; 3.0 4.0], [0.25 4.0; 1.0 0.0])2×2 Matrix{Float64}: 2.0 -1.0 3.0 NaNRelated
PortfolioOptimisers.idio_calibration — Function
idio_calibration(z::MatNum) -> Vector{<:Real}
idio_calibration(eps::MatNum, vs::MatNum) -> Vector{<:Real}
idio_calibration(csfm::CrossSectionalFactorModel) -> Vector{<:Real}Return the cross-sectional standard deviation of the standardised idiosyncratic returns, one entry per observation.
It is the headline calibration series of a cross-sectional fit. The fit predicted a variance for each asset, and dividing the realised idiosyncratic return by the predicted volatility leaves a cross-section whose standard deviation is 1 when the prediction was right. A series that sits above 1 is a fit whose specific risk is too small, and one that sits below 1 is a fit whose specific risk is too large.
The deviation is the sample one, so it divides by $n - 1$. An observation at which fewer than two assets carry a finite standardised return reads NaN.
Mathematical definition
\[c_{t} = \sqrt{\frac{n_{t}}{n_{t} - 1} m_{2t}}\]
Where:
- $m_{2t}$: Second central moment of the cross-section of observation $t$.
- $n_{t}$: Number of assets at which the standardised return is finite.
Arguments
z: Standardised idiosyncratic returnsobservations × assets.eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.
Validation
!isempty(eps)andsize(vs) == size(eps), on the two-argument form.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
c::Vector{<:Real}: The series, one entry per observation. An observation with fewer than two finite assets isNaN.
Related
PortfolioOptimisers.idio_tail_rate — Function
idio_tail_rate(z::MatNum; threshold::Real = 3) -> Vector{<:Real}
idio_tail_rate(eps::MatNum, vs::MatNum; threshold::Real = 3) -> Vector{<:Real}
idio_tail_rate(csfm::CrossSectionalFactorModel; threshold::Real = 3) -> Vector{<:Real}Return the share of assets whose standardised idiosyncratic return exceeds a threshold, one entry per observation.
The Gaussian reference of a threshold of three is $2 \Phi(-3) \approx 0.0027$, so a series that sits above it is a fit whose standardised returns carry heavier tails than the normal law implies. A rate of one to three percent is ordinary for an equity factor model, and it is not by itself a defect of the fit.
An asset enters the denominator when its standardised return is finite, and the numerator when the absolute value of that return exceeds the threshold. An observation at which no asset carries a finite standardised return reads NaN.
Mathematical definition
\[r_{t} = \frac{1}{n_{t}} \sum_{i \in \mathcal{F}_{t}} \mathbb{1} \left\{ \left| z_{ti} \right| > c \right\}\]
Where:
- $\mathcal{F}_{t}$: The assets at which the standardised return is finite.
- $n_{t}$: Size of $\mathcal{F}_{t}$.
- $c$: The threshold.
Arguments
z: Standardised idiosyncratic returnsobservations × assets.eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.threshold: Absolute standardised return above which an asset enters the rate.
Validation
!isempty(eps)andsize(vs) == size(eps), on the two-argument form.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
r::Vector{<:Real}: The series, one entry per observation. An observation with no finite asset isNaN.
Related
PortfolioOptimisers.idio_kurtosis — Function
idio_kurtosis(z::MatNum) -> Vector{<:Real}
idio_kurtosis(eps::MatNum, vs::MatNum) -> Vector{<:Real}
idio_kurtosis(csfm::CrossSectionalFactorModel) -> Vector{<:Real}Return the cross-sectional excess kurtosis of the standardised idiosyncratic returns, one entry per observation.
The Gaussian reference is 0, and a positive value is a cross-section whose tails are heavier than the normal law implies. Read it beside idio_tail_rate: the rate counts the assets beyond a threshold, and the kurtosis weighs how far beyond it they went.
The estimate is bias corrected, so it matches the ordinary sample estimator of the excess kurtosis. An observation at which fewer than four assets carry a finite standardised return reads NaN, and so does one whose cross-section is constant.
Mathematical definition
\[k_{t} = \frac{n_{t} - 1}{(n_{t} - 2)(n_{t} - 3)} \left[ (n_{t} + 1) \left( \frac{m_{4t}}{m_{2t}^{2}} - 3 \right) + 6 \right]\]
Where:
- $m_{2t}$, $m_{4t}$: Second and fourth central moments of the cross-section of observation $t$.
- $n_{t}$: Number of assets at which the standardised return is finite.
Arguments
z: Standardised idiosyncratic returnsobservations × assets.eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.
Validation
!isempty(eps)andsize(vs) == size(eps), on the two-argument form.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
k::Vector{<:Real}: The series, one entry per observation. An observation with fewer than four finite assets isNaN.
Related
PortfolioOptimisers.idio_skewness — Function
idio_skewness(z::MatNum) -> Vector{<:Real}
idio_skewness(eps::MatNum, vs::MatNum) -> Vector{<:Real}
idio_skewness(csfm::CrossSectionalFactorModel) -> Vector{<:Real}Return the cross-sectional skewness of the standardised idiosyncratic returns, one entry per observation.
The Gaussian reference is 0. A cross-section that is persistently skewed is a fit whose residual carries a direction the factors did not take, which a sector or a style the exposures do not name can produce.
The estimate is bias corrected, so it matches the ordinary sample estimator of the skewness. An observation at which fewer than three assets carry a finite standardised return reads NaN, and so does one whose cross-section is constant.
Mathematical definition
\[s_{t} = \frac{m_{3t}}{m_{2t}^{3/2}} \frac{\sqrt{n_{t}(n_{t} - 1)}}{n_{t} - 2}\]
Where:
- $m_{2t}$, $m_{3t}$: Second and third central moments of the cross-section of observation $t$.
- $n_{t}$: Number of assets at which the standardised return is finite.
Arguments
z: Standardised idiosyncratic returnsobservations × assets.eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.
Validation
!isempty(eps)andsize(vs) == size(eps), on the two-argument form.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
s::Vector{<:Real}: The series, one entry per observation. An observation with fewer than three finite assets isNaN.
Related
PortfolioOptimisers.idio_vol_ic — Function
idio_vol_ic(eps::MatNum, vs::MatNum) -> Vector{<:Real}
idio_vol_ic(csfm::CrossSectionalFactorModel) -> Vector{<:Real}Return the information coefficient of the predicted idiosyncratic volatility, one entry per pair of observations.
The fit predicted a volatility for each asset at observation $t$, and the assets it called the most volatile should be the assets that moved the most at observation $t + 1$. This series scores that ranking with the rank correlation of the predicted volatility against the absolute idiosyncratic return of the next observation.
A high value is a fit that ranks specific risk across the assets well. The series also picks up a broad cross-sectional effect such as size or liquidity, so read it beside idio_vol_residual_dependence, which states whether the level of the prediction still leaks into what the fit standardised.
Mathematical definition
\[\mathrm{IC}_{t} = \rho_{S} \left( \hat{\sigma}_{t \cdot}, \left| \boldsymbol{\varepsilon}_{t + 1, \cdot} \right| \right)\]
Where:
- $\hat{\sigma}_{ti} = \sqrt{\max(v_{ti}, 0)}$: Predicted idiosyncratic volatility.
- $\rho_{S}$: The cross-sectional rank correlation, over the assets at which both cross-sections are finite.
Arguments
eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.
Validation
!isempty(eps),size(vs) == size(eps)andsize(eps, 1) > 1.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
c::Vector{<:Real}: The series,observations - 1entries. An observation sharing fewer than five finite assets isNaN.
Related
PortfolioOptimisers.idio_vol_residual_dependence — Function
idio_vol_residual_dependence(eps::MatNum, vs::MatNum) -> Vector{<:Real}
idio_vol_residual_dependence(csfm::CrossSectionalFactorModel) -> Vector{<:Real}Return the rank correlation of the predicted idiosyncratic volatility against the next observation's standardised absolute idiosyncratic return, one entry per pair of observations.
Dividing the realised move by the volatility the fit predicted should remove the level of that prediction. So a well calibrated fit leaves a series near 0: how large an asset's standardised move was should not depend on how volatile the fit said the asset would be. A series that stays positive is a fit that under-predicts the volatile assets, and one that stays negative is a fit that over-predicts them.
The target divides the absolute return of observation $t + 1$ by the volatility predicted at observation $t$, and not by the volatility predicted at observation $t + 1$. Both quantities are written $z_{t+1}$ in the literature, and they differ wherever the prediction moved between the two observations.
Read it beside idio_vol_ic. A fit that ranks well and leaves no residual dependence carries a high information coefficient and a dependence near 0.
Mathematical definition
\[d_{t} = \rho_{S} \left( \hat{\sigma}_{t \cdot}, \frac{\left| \boldsymbol{\varepsilon}_{t + 1, \cdot} \right|}{\hat{\sigma}_{t \cdot}} \right)\]
Where:
- $\hat{\sigma}_{ti} = \sqrt{\max(v_{ti}, 0)}$: Predicted idiosyncratic volatility.
- $\rho_{S}$: The cross-sectional rank correlation, over the assets at which both cross-sections are finite.
Arguments
eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.
Validation
!isempty(eps),size(vs) == size(eps)andsize(eps, 1) > 1.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
d::Vector{<:Real}: The series,observations - 1entries. An observation sharing fewer than five finite assets isNaN.
Related
PortfolioOptimisers.idio_calibration_summary — Function
idio_calibration_summary(eps::MatNum, vs::MatNum; threshold::Real = 3)
idio_calibration_summary(csfm::CrossSectionalFactorModel; threshold::Real = 3)Return the five time-aggregated numbers of the calibration of a cross-sectional fit.
The four calibration series each answer per observation, and a caller who judges a whole fit reads their time aggregate instead. The five numbers are the mean and the median of idio_calibration, and the means of idio_kurtosis, of idio_skewness and of idio_tail_rate. Every aggregate skips the observations that had too few assets to answer.
Under the normal law the expected values are 1, 1, 0, 0 and $2 \Phi(-c)$. A fit of an equity universe ordinarily carries a positive excess kurtosis and a tail rate above the Gaussian reference, so read the first two numbers for the scale of the specific risk and the last three for the shape of its tails.
Arguments
eps: Idiosyncratic return historyobservations × assets.vs: Idiosyncratic variance historyobservations × assets.csfm: A cross-sectional factor model block.threshold: Absolute standardised return above which an asset enters the tail rate.
Validation
!isempty(eps)andsize(vs) == size(eps), on the two-argument form.csfm.csris notnothing, else anIsNothingErrornamingcsris raised.csfm.vsis notnothing, else anIsNothingErrornamingvsis raised.
Returns
mean_cs_std::Real: Mean of the calibration series.median_cs_std::Real: Median of the calibration series.mean_kurtosis::Real: Mean of the excess kurtosis series.mean_skewness::Real: Mean of the skewness series.mean_tail_rate::Real: Mean of the tail rate series.
Related