Factory: private API

Utility functions

PortfolioOptimisers._wprop — Function
_wprop(
    field,
    args...;
    kwargs...
) -> Union{DynamicAbstractWeights, AbstractWeights}

Resolve the new value of a @wprop-tagged observation-weights field during factory propagation.

When an ObsWeights argument is threaded through factory, the field is replaced by those weights; otherwise the existing field value is kept. This is distinct from factory_child (used by @fprop), which recurses into sub-estimators and leaves nothing/non-estimator values unchanged — a weights slot must not be confused with an optional sub-estimator that happens to be nothing.

Algorithm

The method that Julia selects is the algorithm, and the selection reads args..., never the field.

  1. The first threaded positional argument is an ObsWeights: return that value, whatever the field held.
  2. No such argument is threaded: return field unchanged.

The field's own value never selects the branch, so a field holding nothing and a field holding weights are both replaced by an incoming ObsWeights, and both are kept when none is threaded.

Related

source
PortfolioOptimisers.resolve_deferred_quantities — Function
resolve_deferred_quantities(x, ) -> ValueatRiskRange
resolve_deferred_quantities(x, , ) -> ValueatRiskRange

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::Variance,
    pr::AbstractPriorResult
) -> Variance
resolve_deferred_quantities(
    r::Variance,
    pr::AbstractPriorResult,
    
) -> Variance

Resolve a Deferred Quantity in the sigma slot of a Variance against prior result pr.

sigma and chol are one pair, so both come from the same fit. The method never meets a stated chol, because assert_derived_slot_has_source refuses one beside a deferred sigma at construction. A covariance estimator gives no factorisation, so chol becomes nothing and the model derives it from the resolved sigma. A prior estimator gives both, so the sparse factorisation of a factor prior reaches the slot unchanged. A measure whose sigma is not a Deferred Quantity returns unchanged.

Related

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

Resolve a Deferred Quantity in the sigma slot of a StandardDeviation against prior result pr.

sigma and chol come from the same fit, by the rule that resolve_deferred_quantities(r::Variance, pr::AbstractPriorResult) states. A measure whose sigma is not a Deferred Quantity returns unchanged.

Related

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

Resolve a Deferred Quantity in the sigma slot of an UncertaintySetVariance against prior result pr.

The measure has one slot that the prior supplies, and no derived slot, so resolve_slot fills sigma alone. A measure whose sigma is not a Deferred Quantity returns unchanged.

Related

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

Resolve a Deferred Quantity in LowOrderMoment'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
resolve_deferred_quantities(
    r::HighOrderMoment,
    pr::AbstractPriorResult
) -> HighOrderMoment
resolve_deferred_quantities(
    r::HighOrderMoment,
    pr::AbstractPriorResult,
    
) -> HighOrderMoment

Resolve a Deferred Quantity in HighOrderMoment'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
resolve_deferred_quantities(
    r::Kurtosis,
    pr::AbstractPriorResult
) -> Kurtosis
resolve_deferred_quantities(
    r::Kurtosis,
    pr::AbstractPriorResult,
    
) -> Kurtosis

Resolve every Deferred Quantity held by Kurtosis r against prior result pr.

Three passes, in order.

  1. A deferred mu resolves on its own.
  2. A deferred kt resolves next, and it carries the centre with it. kt is a moment about a centre, so the two are one pair of quantities out of one object: when mu is still unstated, deferred_centre reads it off the cokurtosis estimator's own me, threads it into the fit as mean =, and it becomes the resolved mu. A stated mu wins and is threaded in its place. An AbstractPriorEstimator centres itself, so the centre is read back off the prior result it produced.
  3. pe fans out into whatever both passes left nothing.

A deferred slot therefore wins over pe, which is the map's precedence rule one level down. kt lives on a HighOrderPrior, so a prior estimator named in kt or pe must compute one.

Related

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

Resolve a Deferred Quantity in NegativeSkewness's sk slot against prior result pr.

sk and V travel together, so both come from the same fit. V = negative_spectral_coskewness(sk, X, mp) is never a function of sk alone, so the fit's own processor builds it and is recorded in mp in place of the one the measure held. A CoskewnessEstimator supplies it through coskewness_processor; an AbstractPriorEstimator supplies it as the prior result's skmp, which is the field HighOrderPrior already carries for exactly this reason.

Recording it keeps the windowed rebuild in port_opt_view on the same processor that built the V it replaces. V is never rebuilt from a resolved sk: under a factor prior the negative spectral part is special, and a rebuild would throw that structure away. This is the sigma/chol rule on the sk/V pair.

The measure carries one deferrable slot, so there is no fan-out to make and it takes no pe. A coskewness estimator needs only a returns matrix, so sk resolves against a LowOrderPrior as readily as against a HighOrderPrior.

Related

source
resolve_deferred_quantities(
    alg::DistributionValueatRisk,
    pr::AbstractPriorResult
) -> DistributionValueatRisk
resolve_deferred_quantities(
    alg::DistributionValueatRisk,
    pr::AbstractPriorResult,
    
) -> DistributionValueatRisk

Resolve every Deferred Quantity held by DistributionValueatRisk alg against prior result pr.

The formulation holds three fields that the prior can fill, and mu and sigma are independent of each other. So it takes a pe, and one fit of pe fills every slot that the caller left unstated. chol is a factor of sigma and goes with it. A sigma that names its own estimator gives the factor from that same fit, and never from the fit of pe.

Algorithm

  1. If sigma is a Deferred Quantity, fit it against pr, and take sigma and its factor chol from that one fit. Otherwise keep sigma and chol as stated.
  2. Resolve mu with resolve_slot.
  3. If pe is nothing, rebuild the formulation with mu, sigma and chol, and return it.
  4. Fit pe against pr, giving fitted.
  5. If sigma is still nothing, take chol from fitted, so that the factor and the matrix come from one fit.
  6. Fill mu and sigma from fitted where they are still nothing, with fan_out_slot.
  7. Rebuild the formulation with the four values and pe = nothing, and return it.

Related

source
resolve_deferred_quantities(
    x::ValueatRisk,
    pr::AbstractPriorResult
) -> ValueatRisk
resolve_deferred_quantities(
    x::ValueatRisk,
    pr::AbstractPriorResult,
    slv
) -> ValueatRisk

Resolve the significance level alpha of a ValueatRisk against prior result pr, and resolve the formulation alg beside it.

alpha can hold a Calibration Rule in place of a number, so it resolves here. The rebuild goes through rebuild_with_slots, whose call to the inner constructor checks 0 < alpha < 1 again on the calibrated number. So the check that a number of the caller meets also refuses a rule that returns a value outside the slot.

This method is more specific than the derived recursion, so it takes over the alg slot that deferred_slots declares. It resolves that slot through resolve_deferred_child, the function that the derived recursion calls.

Algorithm

  1. Set ws to the observation weights of the measure, or to those of pr when the measure states none.
  2. Resolve alpha with resolve_calibration_slot, which gives the rule pr, ws and the solver slv. The measure holds no solver of its own.
  3. Resolve alg with resolve_deferred_child.
  4. Rebuild the measure with the resolved alpha and alg.

Related

source
resolve_deferred_quantities(
    x::ValueatRiskRange,
    pr::AbstractPriorResult
) -> ValueatRiskRange
resolve_deferred_quantities(
    x::ValueatRiskRange,
    pr::AbstractPriorResult,
    slv
) -> ValueatRiskRange

Resolve the two significance levels of a ValueatRiskRange against prior result pr, and resolve the formulation alg beside them.

Each tail has its own slot and its own bound, so a rule for the loss tail and a rule for the gain tail resolve independently. beta defaults to alpha, so a rule stated for the loss tail alone reaches both tails. The rule states the method, and the slot states the tail. The rebuild goes through rebuild_with_slots, whose call to the inner constructor checks both levels again on the calibrated numbers.

This method is more specific than the derived recursion, so it takes over the alg slot that deferred_slots declares, through resolve_deferred_child.

Algorithm

  1. Set ws to the observation weights of the measure, or to those of pr when the measure states none.
  2. Resolve alpha with resolve_calibration_slot, which gives the rule pr, ws and the solver slv.
  3. Resolve beta in the same way.
  4. Resolve alg with resolve_deferred_child.
  5. Rebuild the measure with the resolved alpha, beta and alg.

Related

source
resolve_deferred_quantities(
    x::DistributionallyRobustConditionalValueatRisk,
    pr::AbstractPriorResult
) -> DistributionallyRobustConditionalValueatRisk
resolve_deferred_quantities(
    x::DistributionallyRobustConditionalValueatRisk,
    pr::AbstractPriorResult,
    slv
) -> DistributionallyRobustConditionalValueatRisk

Resolve the significance level alpha, the tail weight l and the ambiguity radius r of a DistributionallyRobustConditionalValueatRisk against prior result pr.

Each of the three slots takes a Calibration Rule in place of a number. The rebuild calls the inner constructor, so a rule that returns a value the slot does not admit meets the same check as a number the caller writes, at fold time.

alpha resolves before l, because TailTermParity prices the tail term at the measure's own significance level. The two form a travelling pair, and the resolved alpha reaches the l slot in its CalibrationContext. A number, a plain function and a rule that reads no sibling all ignore that field. The radius reads neither slot.

Both contexts also carry the series that the measure prices. For this measure it is the returns, which is the default of calibration_series. The method passes it all the same, because the marker belongs to the measure, and a rule carries no marker of its own.

The measure holds no solver, so the rule receives the slv that the caller passes, which is nothing by default.

Algorithm

  1. Compute the effective observation weights ws, the measure's own w or else the weights of pr.
  2. Read s, the series marker, with calibration_series.
  3. Resolve alpha with resolve_calibration_slot.
  4. Resolve l, with a context that carries the resolved alpha and s.
  5. Resolve r, with a context that carries s alone.
  6. Rebuild the measure with rebuild_with_slots. It returns x itself when all three slots already held numbers, so the common case allocates nothing.

Related

source
resolve_deferred_quantities(
    x::DistributionallyRobustConditionalValueatRiskRange,
    pr::AbstractPriorResult
) -> DistributionallyRobustConditionalValueatRiskRange
resolve_deferred_quantities(
    x::DistributionallyRobustConditionalValueatRiskRange,
    pr::AbstractPriorResult,
    slv
) -> DistributionallyRobustConditionalValueatRiskRange

Resolve the two significance levels, the two tail weights and the two ambiguity radii of a DistributionallyRobustConditionalValueatRiskRange against prior result pr.

Each tail keeps its own level, weight and radius, so six slots resolve here. The method keeps the rules of the scalar measure. The rebuild re-runs every check of the constructor, and the method returns a measure whose six slots all hold numbers unchanged.

Each tail weight reads the level of its own tail. l_a reads alpha and l_b reads beta, so on a skewed sample TailTermParity gives the two tails two different weights, which is what the rule is for on a range measure. A radius reads neither level, and each radius resolves independently of the other.

Both tails price one series, the returns, so the same marker stands in all three contexts. The series belongs to the measure, and the level belongs to a tail.

Algorithm

  1. Compute the effective observation weights ws, the measure's own w or else the weights of pr.
  2. Read se, the series marker, with calibration_series.
  3. Resolve alpha and beta with resolve_calibration_slot.
  4. Build three contexts: cs carries se alone, ca carries the resolved alpha and se, and cb carries the resolved beta and se.
  5. Resolve l_a in ca, r_a in cs, l_b in cb and r_b in cs.
  6. Rebuild the measure with rebuild_with_slots, which returns x itself when every slot already held a number.

Related

source
resolve_deferred_quantities(
    x::DistributionallyRobustConditionalDrawdownatRisk,
    pr::AbstractPriorResult
) -> DistributionallyRobustConditionalDrawdownatRisk
resolve_deferred_quantities(
    x::DistributionallyRobustConditionalDrawdownatRisk,
    pr::AbstractPriorResult,
    slv
) -> DistributionallyRobustConditionalDrawdownatRisk

Resolve the significance level alpha, the tail weight l and the ambiguity radius r of a DistributionallyRobustConditionalDrawdownatRisk against prior result pr.

The steps are those of the method for DistributionallyRobustConditionalValueatRisk, except for the series. This measure prices drawdowns, so calibration_series gives AbsoluteDrawdownSeries, and the marker reaches both the l slot and the r slot. TailTermParity then prices the mean drawdown of each column against the $\mathrm{CDaR}_{\alpha}$ of that column, and a radius rule reads its scale off the drawdown sample. The keys :l and :r are the same on the two measures, so the marker is the only thing that tells a rule which quantity it prices.

A drawdown series holds one entry per observation, so a rule reads the same sample size here as on the returns.

Algorithm

  1. Compute the effective observation weights ws, the measure's own w or else the weights of pr.
  2. Read s, the series marker, which is AbsoluteDrawdownSeries.
  3. Resolve alpha with resolve_calibration_slot.
  4. Resolve l, with a context that carries the resolved alpha and s.
  5. Resolve r, with a context that carries s alone.
  6. Rebuild the measure with rebuild_with_slots, which returns x itself when all three slots already held numbers.

Related

source
resolve_deferred_quantities(
    x::RelativisticValueatRisk,
    pr::AbstractPriorResult
) -> RelativisticValueatRisk
resolve_deferred_quantities(
    x::RelativisticValueatRisk,
    pr::AbstractPriorResult,
    slv
) -> RelativisticValueatRisk

Resolve the significance level alpha and the deformation parameter kappa of a RelativisticValueatRisk against prior result pr.

alpha and kappa are a Travelling Pair. A rule in the kappa slot, such as EntropyBudget, can read the significance level of the alpha slot, so alpha resolves first. A stated number, a plain function and a rule that reads no sibling ignore the context, so the order changes nothing for them.

Algorithm

  1. Select the observation weights ws with sel(x.w, pr.w).
  2. Select the solver sv with sel(x.slv, slv). Both rules receive it, so a rule can call RRM.
  3. Read the series marker s with calibration_series. The measure prices the returns, which is also the default of the context.
  4. Resolve the alpha slot, giving alpha.
  5. Resolve the kappa slot with a CalibrationContext that holds alpha and s, giving kappa.
  6. Rebuild the measure with rebuild_with_slots. Its positional call runs the inner constructor, which checks the range of both calibrated numbers again.

Related

source
resolve_deferred_quantities(
    x::RelativisticValueatRiskRange,
    pr::AbstractPriorResult
) -> RelativisticValueatRiskRange
resolve_deferred_quantities(
    x::RelativisticValueatRiskRange,
    pr::AbstractPriorResult,
    slv
) -> RelativisticValueatRiskRange

Resolve the two significance levels and the two deformation parameters of a RelativisticValueatRiskRange against prior result pr.

Each end has its own Travelling Pair: kappa_a reads alpha, and kappa_b reads beta. The gain-side pair defaults to the loss-side pair, beta to alpha and kappa_b to kappa_a, so a pair stated on the loss side alone reaches both ends. Neither end reads the number of the other end. range_tails and the functor use the same pairing.

The four slots have four different bounds, so the constructor refuses a rule of the wrong end or of the wrong family. Both ends price the returns, so one series marker goes into the context of both kappa slots, while each end has its own significance level.

Algorithm

  1. Select the observation weights ws with sel(x.w, pr.w).
  2. Select the solver sv with sel(x.slv, slv). All four rules receive it.
  3. Read the series marker s with calibration_series.
  4. Resolve the alpha slot, giving alpha.
  5. Resolve the kappa_a slot with a CalibrationContext that holds alpha and s, giving kappa_a.
  6. Resolve the beta slot, giving beta.
  7. Resolve the kappa_b slot with a CalibrationContext that holds beta as its significance level and s, giving kappa_b.
  8. Rebuild the measure with rebuild_with_slots, which checks the range of all four calibrated numbers again.

Related

source
resolve_deferred_quantities(
    x::RelativisticDrawdownatRisk,
    pr::AbstractPriorResult
) -> RelativisticDrawdownatRisk
resolve_deferred_quantities(
    x::RelativisticDrawdownatRisk,
    pr::AbstractPriorResult,
    slv
) -> RelativisticDrawdownatRisk

Resolve the significance level alpha and the deformation parameter kappa of a RelativisticDrawdownatRisk against prior result pr.

The order is the one that RelativisticValueatRisk uses: alpha resolves first, and it reaches the kappa slot in its CalibrationContext. The drawdown series has one entry per row of the sample, so a rule reads the same sample size as it does for the value-at-risk measure.

The series differs from that of RelativisticValueatRisk. This measure prices the absolute drawdown series of the portfolio, so calibration_series states AbsoluteDrawdownSeries, and the context carries that marker beside alpha. A rule that reads the shape of a series then reads the drawdown series of each column of the sample, not the columns, and alpha is the level of that drawdown series. The key :kappa names this slot and the slot of RelativisticValueatRisk alike, so the marker is the only thing that tells the rule which series it reads.

Algorithm

  1. Select the observation weights ws with sel(x.w, pr.w).
  2. Select the solver sv with sel(x.slv, slv).
  3. Read the series marker s, which is AbsoluteDrawdownSeries.
  4. Resolve the alpha slot, giving alpha.
  5. Resolve the kappa slot with a CalibrationContext that holds alpha and s, giving kappa.
  6. Rebuild the measure with rebuild_with_slots, which checks the range of both calibrated numbers again.

Related

source
resolve_deferred_quantities(
    x::RelativeRelativisticDrawdownatRisk,
    pr::AbstractPriorResult
) -> RelativeRelativisticDrawdownatRisk
resolve_deferred_quantities(
    x::RelativeRelativisticDrawdownatRisk,
    pr::AbstractPriorResult,
    slv
) -> RelativeRelativisticDrawdownatRisk

Resolve the significance level alpha and the deformation parameter kappa of a RelativeRelativisticDrawdownatRisk against prior result pr.

The measure is hierarchical, so it reaches no JuMP model, and factory is the only route that resolves it. The Travelling Pair resolves in the order that RelativisticDrawdownatRisk uses.

This measure compounds the path, so calibration_series states RelativeDrawdownSeries, and the context carries that marker. The two drawdown measures name two different series of the same column, and a rule that reads the shape of a series gives a different answer on each.

Algorithm

  1. Select the observation weights ws with sel(x.w, pr.w).
  2. Select the solver sv with sel(x.slv, slv).
  3. Read the series marker s, which is RelativeDrawdownSeries.
  4. Resolve the alpha slot, giving alpha.
  5. Resolve the kappa slot with a CalibrationContext that holds alpha and s, giving kappa.
  6. Rebuild the measure with rebuild_with_slots, which checks the range of both calibrated numbers again.

Related

source
resolve_deferred_quantities(
    x::ComposedFunction{typeof(reverse), <:AbstractOrderedWeightsArrayFunction},
    pr::AbstractPriorResult
) -> ComposedFunction{typeof(reverse)}
resolve_deferred_quantities(
    x::ComposedFunction{typeof(reverse), <:AbstractOrderedWeightsArrayFunction},
    pr::AbstractPriorResult,
    slv
) -> ComposedFunction{typeof(reverse)}

Resolve the weight builder inside the reversal that OrderedWeightsArrayRange wraps its w2 in.

The Range constructor stores w2 as reverse ∘ w2 whenever the caller has not already reversed it, so the object the w2 slot holds is a composition and the builder a rule sits in is its inner half. Without this method the recursion would stop at the composition and a rule in the gain-side builder would never resolve, while the same rule in w1 did.

The composition is rebuilt around the resolved half, so the reversal survives. The bound names reverse and an AbstractOrderedWeightsArrayFunction, so no other composition reaches it.

Related

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

Resolve every Deferred Quantity held by Skewness r against prior result pr.

Three passes, in order.

  1. A deferred mu resolves on its own.
  2. A deferred sk resolves next, and it carries the centre with it. sk is a moment about a centre, so the two are one pair of quantities out of one object: when mu is still unstated, deferred_centre reads it off the coskewness estimator's own me, threads it into the fit as mean =, and it becomes the resolved mu. A stated mu wins and is threaded in its place. An AbstractPriorEstimator centres itself, so the centre is read back off the prior result it produced.
  3. pe fans out into whatever both passes left nothing.

A deferred slot therefore wins over pe, which is the map's precedence rule one level down. The measure reads no V, so only the sk half of the coskewness pair is kept — see NegativeSkewness for the half that needs both.

Related

source
resolve_deferred_quantities(
    r::VarianceSkewKurtosis,
    pr::AbstractPriorResult
) -> VarianceSkewKurtosis
resolve_deferred_quantities(
    r::VarianceSkewKurtosis,
    pr::AbstractPriorResult,
    slv
) -> VarianceSkewKurtosis

Resolve every Deferred Quantity held by VarianceSkewKurtosis r against prior result pr.

Two levels, in order. Each child resolves whatever it holds of its own, then the container's pe fans out into every child slot still unstated — sigma and its chol on vr, sk and mu on sk, kt and mu on kt — all from one fit.

A child that names its own quantity keeps it. This is the map's precedence rule applied one level down, and it treats a deferred child slot exactly as it already treats a stated one.

The composed measure adds a variance, a skewness and a kurtosis term, so a caller who wants the three to describe one distribution names pe on the container and states nothing on the children.

Related

source
resolve_deferred_quantities(
    r::MedianAbsoluteDeviation,
    pr::AbstractPriorResult
) -> Any
resolve_deferred_quantities(
    r::MedianAbsoluteDeviation,
    pr::AbstractPriorResult,
    
) -> Any

Resolve a Deferred Quantity in MedianAbsoluteDeviation's mu slot against prior result pr.

This is the only thing factory does to mu. The field is tagged @vprop and not @pprop, so the prior never fills it — a bare MedianAbsoluteDeviation() inside a JuMPOptimiser keeps median-centring rather than silently taking pr.mu.

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
resolve_deferred_quantities(
    rt::ArithmeticReturn,
    pr::AbstractPriorResult
) -> ArithmeticReturn
resolve_deferred_quantities(
    rt::ArithmeticReturn,
    pr::AbstractPriorResult,
    
) -> ArithmeticReturn

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

Every JuMP path reaches this through factory, which processed_jump_optimiser_attributes calls on opt.ret before any model is built. A return term needs no second entry point, unlike a risk measure.

Related

source
PortfolioOptimisers.sel — Function
sel(risk_variable, source_variable)

Unified risk-measure selector emitted by the @pprop/@cprop tags. Prefers the risk-measure value risk_variable when present, otherwise falls back to source_variable (a prior moment for @pprop, or a threaded optimiser value for @cprop). Dispatches on operand types to the appropriate leaf selector and inlines to zero cost:

  • solvers (Slv_VecSlv) → solver_selector
  • uncertainty sets (UcSE_UcS) → ucs_selector
  • a Deferred Quantity or a Calibration Rule → kept, because a slot the caller filled with the method that computes the value is a stated slot
  • everything else (moments) → nothing_scalar_array_selector

The Deferred-Quantity arm exists because @propagatable runs the selection before resolve_deferred_quantities, so a @pprop slot that admits a Deferred Quantity reaches here still holding one. The prior must not fill such a slot: the caller stated the method, and the resolution that follows replaces it with the value that method produced. The same reading covers a Calibration Rule.

Note: the solver_selector both-nothing "cannot solve" error is not reachable through sel (both-nothing routes to the moment selector and returns nothing); the JuMPOptimiser solver-required invariant makes that case unreachable in the pipeline.

Related

source