Non-Optimisation Risk Measures: private API

PortfolioOptimisers.resolve_deferred_quantitiesMethod
resolve_deferred_quantities(x, ) -> StandardDeviation
resolve_deferred_quantities(x, , ) -> StandardDeviation

Resolve every Deferred Quantity held by x against prior result pr, returning a struct of the same type whose deferred slots hold plain values.

This resolves the deferred state and nothing else. A slot left unstated stays nothing, so whichever fallback the consumer already applies — sel on the factory path, chol_sigma_selector and its siblings on the JuMP path — keeps working unchanged. The two paths are separate: a JuMP model builder reads the risk measure's slots directly and never calls factory, so both entry points resolve.

Given a prior result the rule has two halves. Container recursion is derived from deferred_slots, so a type that only holds children needs no method at all. A type that resolves a quantity of its own defines a method, which overrides the derived one. Writing that half per type — rather than per field — is what lets slots that travel together be resolved together: a deferred sigma supplies chol from the same fit, so the pair is never mixed across two sources.

slv is the effective solver, and it is what a Calibration Rule in the same struct reads. It carries the value the optimisation settled on, so a rule resolves against one solver on both routes. On the factory route the @cprop selection has already put that solver on the struct, so the argument stays at its default. On the JuMP route no selection runs, so set_risk_constraints! reads the solver off the estimator and threads it here. A type that carries a solver of its own settles it locally as sel(x.slv, slv), beside the observation weights it already settles that way, and a type that carries none gives its rules none on either route.

Algorithm

  1. Return x unchanged. This method is the arm for a second argument that is not a prior result: with no prior in hand nothing can be fitted, so the deferred state travels on.

A more specific method dominates this one on a prior result: the one that deferred_slots derives for a container, and the hand-written one of a type that resolves a quantity of its own.

Related

source
resolve_deferred_quantities(x, pr::AbstractPriorResult, slv = nothing)

Resolve the children that deferred_slots declared and the slots that calibration_slots declared, and return x itself when none of them changed.

This is the derived half of the resolution rule. A container declares its children once and both entry points follow: factory reaches them through @fprop, and the JuMP builders reach them through this method. Neither needs a forwarding method per container.

A type that resolves a quantity of its own overrides this with its own method, which is more specific. So the derivation carries container recursion alone, and never guesses how a matrix, a tensor or the centre a moment was taken about comes out of a fit.

Both channels end in one rebuild: a measure that carries both kinds of slot must not be rebuilt twice. resolve_calibration_slots states the calibration half and returns its resolved slots rather than a rebuilt object, and the two answers merge here. The deferred half merges last, so it wins a key both channels declare. A container names one child in both, and the child the recursion resolved is the one to keep.

slv is the effective solver, and the recursion threads it to every child. A container states no solver of its own, so it changes none: each child settles the one it was handed against the one it carries.

Algorithm

  1. Read the slots x declares with deferred_slots, giving slots.
  2. Read the resolved calibration slots with resolve_calibration_slots, giving calibrated.
  3. Return x unchanged when both are empty. A type with neither kind of slot needs no method of its own.
  4. Resolve every entry of slots with resolve_deferred_child, threading pr and slv to each, giving resolved.
  5. Refuse a slot the recursion left unresolved with assert_declared_slot_resolver.
  6. Hand merge(calibrated, resolved) to rebuild_with_slots, which returns x itself when no entry moved and a rebuilt copy when one did.

Returns

  • x itself when no slot moved, and a rebuilt copy of x when one did.

Related

source
resolve_deferred_quantities(
    r::ThirdCentralMoment,
    pr::AbstractPriorResult
) -> ThirdCentralMoment
resolve_deferred_quantities(
    r::ThirdCentralMoment,
    pr::AbstractPriorResult,
    
) -> ThirdCentralMoment

Resolve a Deferred Quantity in ThirdCentralMoment's mu slot against prior result pr. The measure carries one prior-derived slot, so the slot itself admits the estimator and there is no fan-out to make.

Related

source
PortfolioOptimisers.calc_moment_targetMethod
calc_moment_target(::TCM_Sk{Nothing, Nothing}, ::Any, x::VecNum)
calc_moment_target(r::TCM_Sk{<:StatsBase.AbstractWeights, Nothing}, ::Any, x::VecNum)
calc_moment_target(r::TCM_Sk{<:Any, <:VecNum}, w::VecNum, ::Any)
calc_moment_target(r::TCM_Sk{<:Any, <:VecScalar}, w::VecNum, ::Any)
calc_moment_target(r::TCM_Sk{<:Any, <:Number}, ::Any, ::Any)

Compute the centering target for ThirdCentralMoment and Skewness risk measures.

Dispatches on the observation-weight type T1 and mean type T2 of TCM_Sk:

  • No weights, no mu: arithmetic mean of x.
  • AbstractWeights, no mu: weighted mean of x.
  • VecNum mu: dot product $\boldsymbol{w}^\intercal \boldsymbol{\mu}$.
  • VecScalar mu: $\boldsymbol{w}^\intercal \boldsymbol{\mu}_v + \mu_s$.
  • Number mu: the scalar r.mu directly.

Related

source
PortfolioOptimisers.calc_deviations_vecFunction
calc_deviations_vec(
    r::Union{Skewness{<:Any, <:Any, <:Any, T1, T2}, ThirdCentralMoment{<:Any, T1, T2}} where {T1, T2},
    w::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Any
calc_deviations_vec(
    r::Union{Skewness{<:Any, <:Any, <:Any, T1, T2}, ThirdCentralMoment{<:Any, T1, T2}} where {T1, T2},
    w::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    fees::Union{Nothing, Fees}
) -> Any

Compute the vector of deviations from the centering target for ThirdCentralMoment and Skewness risk measures.

Related

source
PortfolioOptimisers.calc_deviations_vecMethod
calc_deviations_vec(
    r::Union{Skewness{<:Any, <:Any, <:Any, T1, T2}, ThirdCentralMoment{<:Any, T1, T2}} where {T1, T2},
    x::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Any

Compute the vector of deviations from the centering target for a precomputed returns series for ThirdCentralMoment and Skewness risk measures.

Single-argument form used by the precomputed-returns functor r(x::VecNum).

Related

source