Mahalanobis regime bias

Functions

PortfolioOptimisers.mahalanobis_level_bias — Function
mahalanobis_level_bias(
    method::RegimeAdjustedMethod,
    decay::Number,
    Ks::AbstractVector{<:Integer},
    n::Integer
) -> Any
mahalanobis_level_bias(
    method::RegimeAdjustedMethod,
    decay::Number,
    Ks::AbstractVector{<:Integer},
    n::Integer,
    hac_lags::Union{Nothing, Integer, AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}}
) -> Any

Computes the bias factor of the squared Mahalanobis distance that a regime method reads, at each count of observations in Ks, by the level recursion.

The squared distance of a correctly calibrated return $u$, independent of the estimate, is $u^{\top} \hat{C}^{-1} u = \chi^{2}_{n} R$, where $R = 1 / S$ and $S$ is the Schur complement of one direction in $W = \sum_{j} w_{j} z_{j} z_{j}^{\top}$, $z_{j} \sim N(0, I_{n})$. Each method reads its own moment of $R$, as regime_bias_factor states, so the factor comes from the Laplace transform of $S$. Given the other directions, $S$ is a weighted sum of $\chi^{2}_{1}$ terms. The exact step from $k$ directions to $k + 1$ then reads the mean log-determinant of the deflated weights, and the recursion takes the mean inside the exponential. That is the one approximation. It is exact at one asset and at equal weights, where the spectrum is not random, and on exponential weights at 12 assets and a half-life of 10 the three factors are 5e-4 to 7e-4 below a Monte Carlo of a million draws, against 0.55 %, 2.5 % and 4.5 % above it for the factor of the mean alone.

A HAC estimate is $Z^{\top} A Z$ with the banded weight matrix $A$ of regime_bias_table, so it has the law of a plain estimate whose weights are the eigenvalues $\mu$ of $A$, and the recursion starts from $D_{0}(s) = \ln \det(I + s A)$. $A$ has negative eigenvalues, so $D_{0}$ is real only below the first zero of the determinant, and no moment of $R$ is finite: the Schur complement has a positive density at zero. The transform is cut at the maximum $s^{*}$ of $D_{0}$, where $\rho_{0} = 0$, as the table of one direction is. For the recursion, mahalanobis_cut! continues $D_{0}$ as the transform of its saturated weights, so the recursion runs as on the plain weights, and mahalanobis_transform cuts the last transform at $s^{*}$. The factor is then exact at one asset on that cut and where $A$ is positive definite. At 12 assets, a half-life of 10 and two lags the three factors are 1.2e-3, 8e-4 and 3e-4 below a Monte Carlo of 4 million draws of the HAC estimate itself, against 1.8 %, 5.3 % and 8.9 % above it for the factor of the mean. Where the effective count of observations is near the gate the recursion is 0.2 % to 0.7 % below the Monte Carlo, with or without HAC: at 3.6 effective observations and three assets the plain weights give 0.9 % and 0.6 %, and the HAC weights 0.7 % and 0.3 %. The first scored rows of five assets at a half-life of 5 and one lag, where 4e-4 of draws are not positive definite, read 0.3 % and 0.03 % below it.

Mathematical definition

\[\begin{align} D_{0}(s) &= \sum_{j} \ln(1 + s w_{j})\,, \qquad \rho_{k} = D_{k}'\,, \qquad D_{k}(0) = 0\,, \\ \rho_{k+1}(s) &= \rho_{k}(s) + \frac{1}{2} \int_{0}^{\infty} e^{-(D_{k}(s + u) - D_{k}(s)) / 2}\, \bigl(\rho_{k}(s + u) - \rho_{k}(s)\bigr)\, \frac{\mathrm{d}u}{u}\,, \\ \mathbb{E}\bigl[e^{-t S}\bigr] &\approx e^{-D_{n-1}(2 t) / 2}\,, \qquad 2 t \leq s^{*}\,. \end{align}\]

Where:

  • $w_{j}$: Normalised weight of the observation $j$ steps before the newest, or the eigenvalue $\mu_{j}$ of $A$ with a HAC adjustment.
  • $D_{k}$: Log-determinant of the Laplace transform after $k$ directions are removed.
  • $s^{*}$: The cut, $\infty$ without a HAC adjustment or where $A$ is positive definite. The recursion reads $D_{0}$ with the continuation of mahalanobis_cut!.

Algorithm

  1. Tabulate $D_{0}$ and its derivative on the lattice for the weights $\lambda^{j}$, or for the banded matrix $A / c$, with mahalanobis_lattice, and keep a copy at each count of Ks.
  2. For each count, round the normalisation $c = (1 - \lambda) / (1 - \lambda^{K})$ to the lattice, $\tilde{c} = e^{m h_{f}}$, so the weights $\tilde{c} \lambda^{j}$ read the lattice without interpolation.
  3. Where the count has a cut, continue the lattice with mahalanobis_cut!.
  4. Run the recursion for $n - 1$ levels on the removed part $q_{k} = \rho_{0} - \rho_{k}$, with the trapezoid rule on $\ln u$. The result at $s$ reads $q_{k}$ only on $[s, \infty)$, so an error moves only toward smaller $s$.
  5. Read the factor of the method off the transform of mahalanobis_transform with regime_bias_factor, and scale it by $\tilde{c} / c$.

Arguments

  • method::RegimeAdjustedMethod: Regime adjustment method, which names the moment.
  • decay::Number: Decay of the weights.
  • Ks::AbstractVector{<:Integer}: Counts of observations, each above n + 1.
  • n::Integer: Count of assets that contribute to the statistic, at least two.
  • hac_lags::Option{<:Union{<:Integer, <:VecNum}}: Count of HAC lags, the weight of each lag, or nothing.

Returns

  • factors::VecNum: The factor at each count of Ks.

Related

source
mahalanobis_level_bias(method, decay::Number, Ks, n::Integer, hac_lags,
                       centring::AbstractCentring, debias)

Computes the Mahalanobis bias factor at each count of Ks on the law of centring.

The bias is a moment of the law of the deviations, so the factor reads the law that centring_law names. ZeroStartCentring reads the factor of PreCentred. A new centring that shares a law of the library returns that law, and needs no method of this verb.

A centring with a law of its own returns itself from centring_law, and adds a method of this verb with centring bound to its own type. Without that method this method raises a MethodError, because the law has no factor.

Arguments

  • method::RegimeAdjustedMethod: Regime adjustment method, which names the moment.
  • decay::Number: Decay of the weights.
  • Ks::AbstractVector{<:Integer}: Counts of observations, each above n + 1.
  • n::Integer: Count of assets that contribute to the statistic, at least two.
  • hac_lags::Option{<:Union{<:Integer, <:VecNum}}: Count of HAC lags, the weight of each lag, or nothing.
  • centring::AbstractCentring: The centring of the estimator.
  • debias::AbstractRegimeDebias: The debias rule, ExactDebias by default.

Returns

  • factors::VecNum: The factor at each count of Ks.

Related

source
mahalanobis_level_bias(method, decay::Number, Ks, n::Integer, hac_lags, ::PreCentred, debias)
mahalanobis_level_bias(method, decay::Number, Ks, n::Integer, hac_lags, ::EstimatedCentring, debias)

Computes the Mahalanobis bias factor at each count of Ks on the law of the centring of the estimator.

A pre-centred estimate reads mahalanobis_level_bias without a centring: its deviation does not share the terms of the estimate, so the debias rule changes nothing. Under EstimatedCentring a count up to $K_{h} = \lceil \ln \sqrt{\epsilon} / \ln \lambda \rceil$ reads estimated_mahalanobis_level_bias. Past $K_{h}$ both factors change as $\lambda^{K}$, so a count takes the pre-centred factor times the ratio of the two at $K_{h}$, as regime_bias_table does. The forward lattice then stops at $K_{h}$.

Arguments

  • method::RegimeAdjustedMethod: Regime adjustment method, which names the moment.
  • decay::Number: Decay of the weights.
  • Ks::AbstractVector{<:Integer}: Counts of observations, each above n + 1.
  • n::Integer: Count of assets that contribute to the statistic, at least two.
  • hac_lags::Option{<:Union{<:Integer, <:VecNum}}: Count of HAC lags, the weight of each lag (pre-centred law only), or nothing.
  • centring: The centring of the estimator.
  • debias::AbstractRegimeDebias: The debias rule, ExactDebias by default.

Returns

  • factors::VecNum: The factor at each count of Ks.

Related

source