Mahalanobis level closure: private API
Functions
PortfolioOptimisers.level_closure_factors — Function
level_closure_factors(
methods::Tuple,
decay::Number,
K::Integer,
n::Integer,
hac_lags::Union{Nothing, Integer, AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}}
) -> Vector
Computes the Mahalanobis bias factor of each method at one count of observations with the closure of GaussianLevelRecursion.
Algorithm
- Tabulate the lattice of the count with
mahalanobis_lattice, round the normalisation to it, continue it past the cut withmahalanobis_cut!, and fill the differences ofmahalanobis_pair_differences!, asmahalanobis_level_biasdoes. - Run $n - 1$ levels of
level_closure_stepfrom a removed part of zero with no variance. - Read each factor off
level_closure_transformwithregime_bias_factor.
Arguments
methods::Tuple: Regime adjustment methods.decay::Number: Decay of the weights.K::Integer: Count of observations.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, ornothing.
Returns
factors::VecNum: The factor of each method.
Related
PortfolioOptimisers.level_closure_maps — Function
level_closure_maps(
grid::NamedTuple
) -> NamedTuple{(:By, :NV), <:Tuple{Any, Any}}
Makes the linear maps of the closure on the grid of mahalanobis_bias_grid.
The state of the closure is the removed part $q$ on the nodes, the eight Chebyshev nodes and the grid past the junction. The vector v of mahalanobis_level_step! holds the Chebyshev values, the five grid values at the junction, which the Chebyshev values fix, and the grid past it. The vector e of mahalanobis_q_integral! is linear in v. The closure reads both through one vector $y = (v; e)$.
Arguments
grid::NamedTuple: Grids ofmahalanobis_bias_grid.
Returns
maps::NamedTuple:By, the map from the nodes to $y$; andNV, the length ofv.
Related
PortfolioOptimisers.level_closure_point — Function
level_closure_point(
ctx::NamedTuple,
y::AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
z::Number
) -> Tuple{Any, Any}
Evaluates the mean field of one level at a point: the log-determinant $D = g - Q$ and its derivative $\rho = \rho_{0} - q$.
Arguments
ctx::NamedTuple: The context oflevel_closure_factors.y::VecNum: The mean of $y = (v; e)$.z::Number: Point to evaluate at.
Returns
(D, rho)::Tuple{<:Number, <:Number}: The two values.
Related
PortfolioOptimisers.LevelClosureTable — Type
struct LevelClosureTable{__T_x0, __T_h, __T_D, __T_R, __T_Rx}Holds the mean field of one level of the closure on a uniform grid of $\ln z$, as level_closure_table fills it.
Fields
x0: First point of the grid of $\ln z$.h: Step of the grid.D: $D$ at each point.R: $\rho$ at each point.Rx: $z \rho'$ at each point.
Related
PortfolioOptimisers.level_closure_table — Function
level_closure_table(
ctx::NamedTuple,
y::AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}
) -> LevelClosureTable
Tabulates the mean field of one level, $D$, $\rho$ and $z \rho'$, on a uniform grid of $\ln z$ of step $1/16$ from $-40$ to $40$, for level_closure_kernel, which reads them at about a million points. The derivative is a central difference of $\rho$ in $\ln z$ of step $10^{-4}$, on the interpolants of the grid, which are polynomials.
Arguments
ctx::NamedTuple: The context oflevel_closure_factors.y::VecNum: The mean of $y = (v; e)$.
Returns
table::LevelClosureTable: The grid and the three columns.
Related
PortfolioOptimisers.level_closure_read — Function
level_closure_read(
tab::LevelClosureTable,
z::Number
) -> Tuple{Any, Any, Any}
Reads the table of level_closure_table at one point with the 4-point Lagrange stencil.
Arguments
tab::LevelClosureTable: The table.z::Number: Point to read at.
Returns
(D, rho, drho)::NTuple{3, <:Number}: $D$, $\rho$ and $\rho'$ atz.
Related
PortfolioOptimisers.level_closure_integrand — Function
level_closure_integrand(
tab::LevelClosureTable,
s::Number,
t::Number,
a::Number,
b::Number,
fs::Tuple,
ft::Tuple
) -> Any
Computes the integrand of level_closure_kernel at one point $(a, b)$.
$V(s) = \ln(x^{\top} M_{s} x) - \ln(x^{\top} M x)$, with $M_{s} = M (I + s M)^{-1}$, is the log-ratio that one removed direction $x$ adds to the log-determinant, and the kernel is the covariance of $V'(s)$ and $V'(t)$. The joint transform of the two quadratic forms of $\ln(x^{\top} M_{s} x)$ and $\ln(x^{\top} M_{t} x)$ at $(a, b)$ is $e^{-E/2}$, with $E = D(p) + D(q) - D(s) - D(t)$ and $p$, $q$ the roots of $(1 + s\mu)(1 + t\mu) + 2 a \mu (1 + t\mu) + 2 b \mu (1 + s\mu)$, so the mixed derivative in $s$ and $t$ reads $D$, $\rho$ and $\rho'$ at the roots. Where the roots are close next to their size, the term $p_{st} (\rho(p) - \rho(q))$, whose factor is $1 / (q - p)$, takes the divided difference of $\rho$, so the round-off of the two values is not amplified.
Arguments
tab::LevelClosureTable: The table oflevel_closure_table.s::Number,t::Number: The two points of the kernel.a::Number,b::Number: The point of the quadrature.fs::Tuple,ft::Tuple: $(D, \rho)$ atsand att.
Returns
val::Number: $e^{-E/2} (E_{s} E_{t} / 4 - E_{st} / 2)$.
Related
PortfolioOptimisers.level_closure_kernel — Function
level_closure_kernel(
tab::LevelClosureTable,
::Type{T}
) -> Tuple{Any, Any}
level_closure_kernel(
tab::LevelClosureTable,
::Type{T},
tol::Number
) -> Tuple{Any, Any}
Computes the covariance that one removed direction adds to the removed part of the next level, $(1 + s)(1 + t) K_{\mathrm{int}}(s, t)$, on a grid of $\ln s$ of step one.
$K_{\mathrm{int}}(s, t) = \partial_{s} \partial_{t} \operatorname{Cov}(\ln A_{s}, \ln A_{t})$ with $A_{s} = x^{\top} M_{s} x$, for the mean field of the level, and $\operatorname{Cov}(\ln A_{s}, \ln A_{t}) = \iint \operatorname{Cov}(e^{-a A_{s}}, e^{-b A_{t}})\, \mathrm{d}\ln a\, \mathrm{d}\ln b$. The trapezoid rule of step one in $\ln a$ and $\ln b$ on $[-16, 26]$ holds it. The scaled kernel is bounded: it tends to $\operatorname{Var}[q(0)]$ at zero and to zero past the saturation, where $s q(s)$ is the count of the removed directions, so its interpolant has no error that $s t$ multiplies. The grid stops three steps past the point where the saturated count $s \rho(s)$ reaches its limit to $10^{-4}$, and the kernel is constant past it.
Arguments
tab::LevelClosureTable: The table oflevel_closure_table.T::Type: The number type.tol::Number: The relative floor oflevel_closure_span, $10^{-7}$ by default. Zero reads every point.
Returns
(xc, K)::Tuple: The grid of $\ln s$ and the scaled kernel on it.
Related
PortfolioOptimisers.level_closure_span — Function
level_closure_span(
dm::AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
tol::Number
) -> Any
Returns the points of the quadrature in $\ln a$ where one node of the kernel holds weight: the span where $|\partial_{s} m_{1}(s, a)|$ is at least tol times its largest value. The covariance of the two exponentials falls with each of the two factors, so the points outside the span add nothing that the rule resolves.
Arguments
dm::VecNum: $\partial_{s} m_{1}(s, a)$ at each point.tol::Number: The relative floor.
Returns
span::UnitRange{Int}: The points.
Related
PortfolioOptimisers.level_closure_form — Function
level_closure_form(
Y::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
i0::Integer,
w::NTuple{8, var"#s3185"} where var"#s3185"<:Number
) -> Any
Computes the quadratic form $w^{\top} Y w$ of one 8-point stencil of $y$, the variance of the value that the stencil reads.
Arguments
Y::MatNum: Covariance of $y$.i0::Integer: Index of the first point of the stencil in $y$.w::NTuple{8, <:Number}: Its weights.
Returns
val::Number: The form.
Related
PortfolioOptimisers.level_closure_node — Function
level_closure_node(
grid::NamedTuple,
NV::Integer,
a::Integer,
Y::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}
) -> NamedTuple{(:qi, :qw, :Qi, :Qw, :Yq, :YQ, :vQ, :cQq), <:Tuple{Vector, Vector, Vector, Vararg{Any, 5}}}
Returns the stencils of the removed part $q$ and of its integral $Q$ at one node, with their products with the covariance of $y$, which every step of the node reads.
A Chebyshev node reads its own value of v, and its integral through the Chebyshev weights; a grid node reads v and e at its own index.
Arguments
grid::NamedTuple: Grids ofmahalanobis_bias_grid.NV::Integer: The length ofv.a::Integer: The node.Y::MatNum: The covariance of $y = (v; e)$.
Returns
node::NamedTuple: The indicesqi,Qiand weightsqw,Qwof the two stencils,Yq = Y qandYQ = Y Q, $\operatorname{Var}[Q]$ asvQand $\operatorname{Cov}(Q, q)$ ascQq.
Related
PortfolioOptimisers.level_closure_pair — Function
level_closure_pair(
Y::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
y::AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
node::NamedTuple,
qs::Tuple,
Qs::Tuple,
NV::Integer
) -> NTuple{4, Any}
Reads one step of one node of the closure: the values of the two stencils of the point $s + u$ on the mean, and the variance of $\Delta Q$ and its covariance with $\Delta q$, the differences between $s + u$ and the node.
Arguments
Y::MatNum: The covariance of $y = (v; e)$.y::VecNum: The mean of $y$.node::NamedTuple: The node, fromlevel_closure_node.qs::Tuple,Qs::Tuple: The stencils of the point onvand one, from the pairs ofmahalanobis_bias_grid.NV::Integer: The length ofv.
Returns
(yq, yQ, var, cov)::NTuple{4, <:Number}: $q$ and $Q$ at the point, $\operatorname{Var}[\Delta Q]$ and $\operatorname{Cov}(\Delta Q, \Delta q)$.
Related
PortfolioOptimisers.level_closure_spread — Function
level_closure_spread(
xc::AbstractRange,
Kc::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
sn::AbstractArray{T, 1}
) -> Any
Reads the scaled kernel of level_closure_kernel at every pair of nodes, and removes its scale: $K_{\mathrm{int}}(s, t)$ is the kernel read with a clamped 8-point Lagrange stencil in $\ln s$ and in $\ln t$, over $(1 + s)(1 + t)$. The clamp holds the kernel constant past the ends of its grid.
Arguments
xc::AbstractRange: The grid of $\ln s$ of the kernel.Kc::MatNum: The scaled kernel on it.sn::AbstractVector{T}: The nodes.
Returns
Kint::Matrix{T}: The kernel at each pair of nodes.
Related
PortfolioOptimisers.level_closure_step — Function
level_closure_step(
ctx::NamedTuple,
nq::AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
Kq::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}
) -> Tuple{Any, Any}
Runs one level of the closure: the mean of the removed part on the nodes and its covariance.
Algorithm
- Map the mean and the covariance of the nodes to $y = (v; e)$.
- At each node $s$ and step $u$, average the integrand of
mahalanobis_level_step!over the Gaussian law of the level: with $\Delta Q$ and $\Delta q$ the differences between $s + u$ and $s$, the integrand is $e^{-\Delta D / 2 + \operatorname{Var}[\Delta Q] / 8} (\Delta \rho - \operatorname{Cov}(\Delta Q, \Delta q) / 2)$. - Accumulate the linear response of the step: a perturbation of the level moves the new removed part by $\frac{h}{2} \sum_{u} \psi (\Delta \delta q - \frac{1}{2} \Delta \rho\, \Delta \delta Q)$. Every term of it vanishes as $u \to 0$.
- The new covariance is the response of the old one plus the kernel of
level_closure_kernelat the nodes, read with a clamped 8-point Lagrange stencil.
Arguments
ctx::NamedTuple: The context oflevel_closure_factors.nq::VecNum: The mean of the removed part on the nodes.Kq::MatNum: Its covariance.
Returns
(nq, Kq)::Tuple: The mean and the covariance of the next level.
Related
PortfolioOptimisers.level_closure_transform — Function
level_closure_transform(
ctx::NamedTuple,
y::AbstractVector{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
Y::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}
) -> Tuple{Any, Any}
Evaluates the last transform of the closure, $e^{-D/2 + \operatorname{Var}[Q]/8}$, on the output grid, with the cut of mahalanobis_transform where the count has one.
Arguments
ctx::NamedTuple: The context oflevel_closure_factors.y::VecNum: The mean of $y = (v; e)$.Y::MatNum: Its covariance.
Returns
(so, L)::Tuple{<:VecNum, <:VecNum}: The grid and the transform on it.
Related