Result investable view: private API

PortfolioOptimisers.extract_pr — Function
extract_pr(res::OptimisationResult) -> Any
extract_pr(
    res::OptimisationResult,
    pr::Union{Nothing, AbstractPriorResult, ReturnsResult}
) -> Any

Extracts the prior result for risk calculation from an optimisation result.

An explicitly provided pr wins. Otherwise the one test is hasproperty(res, :pr), which property forwarding answers for a nested result: a JuMP leaf reaches its prior at res.jr.pa.pr, and res.pr resolves to it. A result that exposes no pr property throws.

Arguments

  • res: Optimisation result, which carries a prior result as its pr property or reaches one by property forwarding.
  • pr: Optional prior result to use for risk calculation, which takes precedence over the one found in res.

Returns

  • pr::Pr_RR: The prior result to use for risk calculation. Throws an ArgumentError when none is found.

A result's prior is on the universe the fit solved, so a consumer that pairs it with res.w, which is on the caller's, reads both through result_investable_view rather than through this verb alone.

Related

source
PortfolioOptimisers.result_investable_carrier — Function
result_investable_carrier(imsk, res::OptimisationResult, pr::Nothing)
result_investable_carrier(imsk::Nothing, res::OptimisationResult, pr::MatNum_Pr)
result_investable_carrier(imsk::BitVector, res::OptimisationResult, pr::Pr_RR)
result_investable_carrier(imsk::BitVector, res::OptimisationResult, X::MatNum)

Resolve the returns carrier a result-taking consumer reads: the result's own prior, or a caller's viewed at the result's Investable Mask.

The carrier half of result_investable_view. The result's own prior is on the universe the fit solved, so it is read through extract_pr and taken as it is, and so is that prior when a caller hands it back, expected_risk(r, res, res.pr): it is the one carrier already on the investable universe, and it is recognised by identity, never by width, because a reduced and a full-universe carrier share a width only by coincidence. Every other caller's carrier is on the caller's universe, the one res.w spans, so under a BitVector mask it is viewed at findall(imsk): a prior result or a ReturnsResult through the port_opt_view its owner writes, which is the rule fold_factor_returns applies to a caller's rd on a fold, and a bare matrix by its columns. Under a nothing mask nothing left, and a caller's carrier is returned unchanged.

Arguments

  • imsk: The Investable Mask of res, or nothing.
  • res::OptimisationResult: Fitted optimisation result.
  • pr: A caller's carrier on the universe of res.w, or nothing.

Returns

  • The carrier on the investable universe of res.

Related

source
PortfolioOptimisers.result_investable_fees — Function
result_investable_fees(imsk, res::OptimisationResult, fees::Nothing)
result_investable_fees(imsk::Nothing, res::OptimisationResult, fees::Fees)
result_investable_fees(imsk::BitVector, res::OptimisationResult, fees::Fees)

Resolve the fee a result-taking consumer charges: the result's own, or a caller's viewed at the result's Investable Mask.

The fee half of result_investable_view, and the rule fold_fees applies on a fold. The result's own fee was reduced at the fit's door, its five per-asset fields to the mask and its two liquidation carriers to the complement, and is marked with that mask, so it is read through extract_fees and taken as it is. A caller's fee is stated on the caller's universe, so it takes the same door a fee takes at the fit, investable_fees_view, which slices the per-asset fields to the mask and the carriers to its complement, and strips the carriers under a nothing mask, because nothing left. The door needs the width of the unreduced universe to derive the complement, and a result holds no full-width matrix, so the width is the mask's own length.

Arguments

  • imsk: The Investable Mask of res, or nothing.
  • res::OptimisationResult: Fitted optimisation result.
  • fees: A caller's Fees on the universe of res.w, or nothing.

Returns

  • fees::Option{<:Fees}: The fee on the two axes the result's mask leaves, or nothing.

Related

source
PortfolioOptimisers.result_investable_view — Function
result_investable_view(res::OptimisationResult, pr = nothing, fees = nothing, nx = nothing)
result_investable_view(imsk::Nothing, res::OptimisationResult, pr, fees, nx)
result_investable_view(imsk::BitVector, res::OptimisationResult, pr, fees, nx)

Pair the weights, the returns carrier, the fee and the axis names a result-taking consumer reads, on the investable universe of the result.

A result carries three things on two universes. An optimisation reduces to its Investable Mask at the entry and expands the solved weights back, so res.w is on the full universe the caller stated, while res.pr is the prior of the universe the fit solved, and res.fees was reduced at the same door, its five per-asset fields to the mask and its two liquidation carriers to the complement. A consumer that reads two of the three separately pairs a full vector with a reduced one: a per-asset fee indexed at a full-length mask raises a BoundsError, a reduced returns matrix against a full weight vector a DimensionMismatch, and a reduced mu under the caller's full names draws every bar after the gap under the name of the asset before it. This verb is the one place the pairing is made, so every result-taking arity of expected_risk, calc_net_returns, factor_attribution, performance_summary and the plotting extension reads all three through it.

The answers are on the investable universe of res, which is the universe its own prior and fee are already on. The weights are viewed at the mask through investable_weights_view. The carrier is resolved by result_investable_carrier and the fee by result_investable_fees: the result's own are taken as they are, and a caller's, stated on the universe res.w spans, is viewed at the mask, the carrier through the port_opt_view its owner writes and the fee through the door a fee takes at the fit. The axis names ride the asset axis, so they take the mask directly, and a drawn figure labels each bar with its own asset.

A result whose mask is nothing reduced on nothing, so the weights and the names are returned unchanged. A per-asset answer a consumer forms on the investable universe expands back through expand_investable_weights with the mask this verb returns first, as the value-level doors do.

Algorithm

  1. Read the Investable Mask of res with result_investable_mask.
  2. On a nothing mask, return nothing, res.w, the carrier through result_investable_carrier, the fee through result_investable_fees, and nx unchanged.
  3. On a BitVector mask, return it, the view of res.w at it, the carrier and the fee through the same two verbs, and the view of nx at it.

Arguments

  • res::OptimisationResult: Fitted optimisation result.
  • pr: A caller's returns carrier on the universe of res.w, a prior result, a ReturnsResult or a returns matrix, or nothing to read the result's own prior.
  • fees: A caller's Fees on the universe of res.w, or nothing to read the result's own.
  • nx: Asset names on the universe of res.w, or nothing.
  • imsk: The Investable Mask of res, or nothing.

Returns

  • (imsk, w, pr, fees, nx): The Investable Mask, and the weights, the carrier, the fee and the names on the investable universe of res.

Related

source