Mean Risk: private API

PortfolioOptimisers.mean_risk_td_defaultsFunction
mean_risk_td_defaults(

) -> @NamedTuple{r::Variance{RiskMeasureSettings{Float64, Nothing, Bool}, Nothing, Nothing, Nothing, SquaredSOCRiskExpr}, obj::MinimumRisk}

Return the static defaults of the MeanRisk fields that may hold a TimeDependent.

Shared by the constructor's test-substitution pass and time_dependent_field_defaults, so the fold-less value of a field is declared once. Fields whose static default is nothing are omitted.

Related

source
PortfolioOptimisers.solve_mean_risk!Function
solve_mean_risk!(model, mr, pr, ::Val{false}, ::Val{false}, fees, attrs)
solve_mean_risk!(model, mr, pr, ::Val{true}, ::Val{false}, fees, attrs)
solve_mean_risk!(model, mr, pr, ::Val{false}, ::Val{true}, fees, attrs)
solve_mean_risk!(model, mr, pr, ::Val{true}, ::Val{true}, fees, attrs)

Solve the Mean-Risk optimisation problem.

Dispatches based on whether a return frontier and/or risk frontier sweep is requested (controlled by Val arguments). Single-point, return-frontier, risk-frontier, and combined sweeps are all handled.

The return terms are read off attrs.ret rather than taken positionally: the positional used to exist so set_portfolio_objective_function! could dispatch a logarithmic ratio problem, and it lost that reason when the ratio constraint was hoisted.

Arguments

  • model::JuMP.Model: JuMP optimisation model.
  • mr::MeanRisk: MeanRisk estimator configuration.
  • pr::AbstractPriorResult: Prior result with asset moments.
  • ::Val{bool}: Whether to do a return frontier sweep.
  • ::Val{bool}: Whether to do a risk frontier sweep.
  • fees: Optional fees configuration.
  • attrs: Pre-computed constraint and prior bundle, which carries the return terms.

Returns

  • (retcode, sol) or (retcodes, sols) depending on the sweep mode.

Related

source
PortfolioOptimisers.return_termFunction
return_term(ret, i)

Select return term i from the optimiser's ret slot.

The slot holds one term or a vector of them, so this is the one place that difference is resolved for the value-level readers. A single term answers to every index, because a single-term configuration only ever has index 1.

Related

source
PortfolioOptimisers.compute_ret_lbsFunction
compute_ret_lbs(model, mr, pr, fees, attrs)

Resolve the return frontier's sweep points, one span per swept return term.

Entries whose bound is already a vector of numbers are left alone. Every entry that still holds a Frontier is given a span read off two corner portfolios:

  1. One shared minimum-risk solve, which supplies the low end of every span.
  2. One MaximumElementReturn solve per swept term, which supplies that term's high end.

So the endpoint cost is k + 1 solves, not 2. The per-term maximum is what makes the span correct: term i's value at the aggregate maximum-return corner is an artefact of the other terms' scale, and can fall below its value at the minimum-risk corner, which leaves rt_min > rt_max and makes range descend. A portfolio that maximised term i alone maximises over the same feasible set that contains w_min, so the span ascends by construction.

Arguments

  • model::JuMP.Model: JuMP optimisation model.
  • mr::MeanRisk: MeanRisk estimator configuration.
  • pr::AbstractPriorResult: Prior result with asset moments.
  • fees::Option{<:Fees}: Optional fees configuration.
  • attrs::ProcessedJuMPOptimiserAttributes: Pre-computed bundle, which carries the terms.

Returns

  • The return frontier vector of (keys, vals) pairs, with every span resolved.

Related

source
compute_ret_lbs(ret_frontier::VecPair, ::Nothing)

Return a NearOptimalCentering return frontier unchanged.

nothing means no swept term declared a Frontier, so every sweep point was stated outright and there is no span to resolve.

Arguments

  • ret_frontier::VecPair: The :ret_frontier Model State entry.
  • ::Nothing: No per-term spans were computed.

Returns

  • ret_frontier, unchanged.

Related

source
compute_ret_lbs(ret_frontier::VecPair, rt_ends::VecPair)

Resolve a NearOptimalCentering return frontier from spans computed during setup.

NearOptimalCentering does not re-solve for its corners here, unlike MeanRisk: near_optimal_centering_setup has already paid for one minimum-risk solve and one maximum-return solve per swept term, so this only turns each span into its N sweep points.

Arguments

  • ret_frontier::VecPair: The :ret_frontier Model State entry.
  • rt_ends::VecPair: The per-term spans, as i => (rt_min_i, rt_max_i).

Returns

  • The return frontier with every span resolved into a range of sweep points.

Related

source
PortfolioOptimisers._rebuild_risk_frontierFunction
_rebuild_risk_frontier(pr::AbstractPriorResult, fees::Option{<:Fees}, r::RiskMeasure,
                       risk_frontier::VecPair, w_min::VecNum, w_max::VecNum,
                       i::Integer = 1)

Resolve one Frontier risk bound into the span of numbers the sweep writes.

The span runs between the risk of the two corner portfolios, w_min and w_max, measured by r itself. bound transforms each end, factor multiplies both, and range divides the result into N levels. A measure whose bigger value is better has its ends swapped, so the span ascends either way.

Arguments

  • pr: Prior result.
  • fees: Optional fees structure.
  • r::RiskMeasure: The measure that owns entry i, already through factory.
  • risk_frontier::VecPair: The :risk_frontier registry.
  • w_min::VecNum: Weights of the minimum-risk corner portfolio.
  • w_max::VecNum: Weights of the maximum-return corner portfolio.
  • i::Integer = 1: Position of the entry in the registry.

Returns

  • The rebuilt entry. Its keys, expression, polarity and owner are entry i's own; only the bound changes.

Details

  • Every part of the entry is read from position i. Reading the expression or the polarity from position 1 would bound the first measure's expression twice and never bound the second measure at all.

Related

source
PortfolioOptimisers.rebuild_risk_frontierFunction
rebuild_risk_frontier(model::JuMP.Model, mr::MeanRisk, pr::AbstractPriorResult,
                      fees::Option{<:Fees}, risk_frontier::VecPair, idx, attrs)

Resolve every unresolved Frontier risk bound into a span of numbers.

Two corner portfolios bound every span, and both are solved once here: a minimum-risk solve and a maximum-return solve. _rebuild_risk_frontier then turns each entry's own measure and each entry's own Frontier into that entry's span.

Arguments

  • model::JuMP.Model: The JuMP optimisation model.
  • mr::MeanRisk: MeanRisk estimator configuration.
  • pr: Prior result.
  • fees: Optional fees structure.
  • risk_frontier::VecPair: The :risk_frontier registry.
  • idx: Registry positions that still need a rebuild.
  • attrs::ProcessedJuMPOptimiserAttributes: Pre-computed constraint and prior bundle.

Returns

  • The registry, with every entry of idx resolved.

Details

  • The measure of an entry is read through risk_frontier_owners, not by indexing mr.r with idx. The registry holds one entry per bounded measure, so the two index spaces coincide only when every measure carries a Frontier bound.
  • Both corner solves must succeed. Either failure throws, because a span read off a failed solve is not a span.

Related

source
PortfolioOptimisers.unresolved_risk_frontierFunction
unresolved_risk_frontier(model::JuMP.Model)

Read the risk frontier out of model and find the entries that still need a rebuild.

An entry is resolved when its bound is already a numeric vector; anything else is a frontier range that rebuild_risk_frontier must turn into numbers. This is the shared half of every compute_risk_ubs method — the methods differ only in the rebuild_risk_frontier call they close with.

Arguments

  • model::JuMP.Model: JuMP optimisation model containing risk_frontier.

Returns

  • (risk_frontier, idx): The frontier vector of pairs, and the indices of its unresolved entries. An empty idx means that no rebuild is needed.

Related

source
PortfolioOptimisers.risk_frontier_ownersFunction
risk_frontier_owners(risk_frontier::VecPair, idx::VecInt)

Map registry positions to the positions of the risk measures that own them.

The :risk_frontier registry is not parallel to the risk measure vector. A measure registers an entry only when its settings.ub is a Front_NumVec, and a memoised measure such as UlcerIndex registers one entry for several copies of itself. So a registry position is not a measure position, and indexing the measure vector with idx picks the wrong measure whenever the two counts differ. Every entry carries its owner (set_risk_frontier_owner!); this reads it.

Arguments

  • risk_frontier::VecPair: The :risk_frontier registry.
  • idx::VecInt: Registry positions, as unresolved_risk_frontier returns them.

Returns

  • owners::Vector{Int}: One measure position per entry of idx, in the same order.

Related

source
PortfolioOptimisers.compute_risk_ubsFunction
compute_risk_ubs(model, opt, ...)

Compute or rebuild risk upper bounds for the efficient frontier sweep.

Extracts the risk frontier from the model and rebuilds any frontier bounds that have not yet been computed as numeric vectors.

Arguments

  • model::JuMP.Model: JuMP optimisation model containing the risk frontier.
  • opt: Optimiser configuration.
  • Additional arguments (prior, fees, weights, etc.).

Returns

  • Updated risk frontier vector of pairs.

Related

source
compute_risk_ubs(model::JuMP.Model, noc::NearOptimalCentering{<:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:ConstrainedNearOptimalCentering}, pr::AbstractPriorResult, fees::Option{<:Fees}, w_min::VecNum, w_max::VecNum, args...)

Compute risk upper bounds for a constrained NearOptimalCentering frontier sweep.

Identifies risk frontier entries that are not yet resolved (i.e. not concrete weight vectors) and rebuilds them using the minimum and maximum portfolio weights.

Arguments

  • model::JuMP.Model: JuMP optimisation model containing risk_frontier.
  • noc::NearOptimalCentering{..., <:ConstrainedNearOptimalCentering}: Constrained Near Optimal Centering optimiser.
  • pr::AbstractPriorResult: Prior result with asset moments.
  • fees::Option{<:Fees}: Optional fees configuration.
  • w_min::VecNum: Minimum-risk portfolio weights.
  • w_max::VecNum: Maximum-risk (maximum-return) portfolio weights.

Returns

  • Updated risk frontier vector of (keys, vals) pairs.

Related

source