The risk ceiling of a programme Allocation Set: private API

PortfolioOptimisers.assert_risk_ceiling — Function
assert_risk_ceiling(r::Nothing)
assert_risk_ceiling(r::RiskMeasure)
assert_risk_ceiling(rs::VecRM)

Refuses a risk measure that cannot be the ceiling of a ProgrammeAllocationSet.

The ceiling of a measure is its settings.ub, and a one-step projection can bound the measure by one number only. The function refuses a measure with no ub, with a Frontier or with a per-asset vector, and it refuses an empty vector of measures. A set with no measure passes.

Arguments

  • r: The set's risk measure, nothing, or a vector of measures.

Validation

  • settings.ub of a measure is not a finite non-negative number. An ArgumentError is thrown.
  • rs is empty. An IsEmptyError is thrown.

Returns

  • nothing.

Related

source
PortfolioOptimisers.risk_reads_rows — Function
risk_reads_rows(r::Nothing)
risk_reads_rows(r::Variance)
risk_reads_rows(r::StandardDeviation)
risk_reads_rows(r::RiskMeasure)
risk_reads_rows(rs::VecRM)

Tells whether a programme set's ceiling reads the head's rows.

A Variance or a StandardDeviation that holds its covariance matrix reads no rows. A variance with risk-contribution rows in rc is the exception: the shared semidefinite builder resolves those rows against a prior, so it reads them. Every other measure is built on a prior fitted on the rows, so it reads them too. A vector reads the rows when one of its members does.

Arguments

  • r: The set's risk measure, nothing, or a vector of measures.

Returns

  • flag::Bool: true when the ceiling reads the head's rows.

Related

source
PortfolioOptimisers.allocation_set_prior — Function
allocation_set_prior(set::ProgrammeAllocationSet, X::Option{<:ReturnsResult})
allocation_set_prior(set::BoundedAllocationSet, X::Option{<:ReturnsResult})

Fits the prior result that a programme set's row-reading slots are built on.

The set fits its pe on the head's rows carrier the same way a batch head fits a prior on any carrier. The fit reads the rows as they are and the Asset Panel beside them, so the result answers NaN at an asset outside the prior's Coverage Universe. A set that reads no rows fits nothing, and a bounded set never fits anything.

Algorithm

  1. Ask rows_needed whether the set reads the head's rows. It answers nothing when a slot reads them.
  2. If no slot reads them, return nothing.
  3. Check that X is not nothing.
  4. Fit set.pe on X with prior, and return the result.

Arguments

  • set: The resolved Allocation Set.
  • X: The head's rows carrier, a ReturnsResult, or nothing outside an Online Update.

Validation

  • A slot reads the rows and X is nothing. An ArgumentError is thrown.

Returns

  • pr::Option{<:AbstractPriorResult}: The fitted prior result, or nothing.

Related

source
PortfolioOptimisers.assert_set_prior_priced — Function
assert_set_prior_priced(pr::Nothing, X)
assert_set_prior_priced(pr::AbstractPriorResult, X::Nothing)
assert_set_prior_priced(pr::AbstractPriorResult, X::ReturnsResult)

Refuses a programme set prior that cannot price an asset the model trades, and names the asset.

The projection programme reduces the model to the prior's Investable Mask before it builds, so its prior always passes. A leader's model trades the Investable Mask of the leader's own prior, and the set fits its prior on the same rows. When both priors are plain, the two masks agree and the check passes. When the set's pe is plain and the leader's prior is mask-aware, a young asset that the leader trades can have no price in the set's prior. Its ceiling would then carry NaN, so the check refuses it here, before the model reaches the solver.

Algorithm

  1. Read the Investable Mask of pr, imsk.
  2. If imsk is nothing, the prior prices every asset: return.
  3. Otherwise, throw an error that names the assets of X.nx outside imsk.

Arguments

  • pr: The set's prior result, or nothing when the set fitted none.
  • X: The head's rows carrier, or nothing.

Validation

  • pr carries an Investable Mask. An ArgumentError is thrown, and it names the assets the prior cannot price.

Returns

  • nothing.

Related

source
PortfolioOptimisers.set_allocation_risk_ceiling! — Function
set_allocation_risk_ceiling!(model::JuMP.Model, r::Nothing, set::ProgrammeAllocationSet, pr, pl; prefix::Symbol = Symbol(""))
set_allocation_risk_ceiling!(model::JuMP.Model, r::RiskMeasure, set::ProgrammeAllocationSet, pr, pl; prefix::Symbol = Symbol(""))
set_allocation_risk_ceiling!(model::JuMP.Model, rs::VecRM, set::ProgrammeAllocationSet, pr::Nothing, pl; prefix::Symbol = Symbol(""))
set_allocation_risk_ceiling!(model::JuMP.Model, rs::VecRM, set::ProgrammeAllocationSet, pr::AbstractPriorResult, pl; prefix::Symbol = Symbol(""))

Adds a programme set's risk ceilings to the model, one row block for each measure, at the measure's index.

Each ceiling goes through the measure's own JuMP builder, set_risk_constraints!, with the set as the RiskConstraintOwner. The builder bounds each measure at its settings.ub through set_risk_upper_bound!, and its own # JuMP formulation names the rows. So the set writes the rows that a JuMP optimiser writes for the same bound. A Variance takes the semidefinite formulation under the conditions that select it in a head, sdp_variance_flag!: risk-contribution rows, an earlier variance with such rows on the same weights, or a semidefinite phylogeny in pl. Otherwise it takes the second-order cone. The variance marks variance_flag, so a semidefinite phylogeny on the same weights adds no p · tr(W) penalty, as in a head.

The source of the covariance matrix does not change the formulation. With a prior result, each measure is resolved against it first. Without one, every ceiling is a Variance or a StandardDeviation that holds its matrix, on a set that reads no rows, and the builder reads that matrix with pr = nothing.

Under a prefix, the builders put their entries in that namespace. assemble_allocation_set! registers the head's w under the prefix before any builder runs. This keeps the ceiling's entries apart from the entries of the head's own measures. The lifted matrix $\mathbf{W}$ and the marks belong to the weights, weights_prefix, so in a leader's model the ceiling, the set's phylogeny and the leader's measures read one $\mathbf{W}$.

Algorithm

For one measure:

  1. Wrap r in a vector and call the vector method.

For a vector and a prior result:

  1. Resolve each measure against pr with factory and set.slv. A moment that the measure holds, such as its own covariance, stays. A cache that the head filled from another prior is not read.
  2. Clear the measure's rke with no_risk_expr_risk_measure, so its expression joins no objective. The measure's scale weights its expression only in the objective, so a ceiling ignores it.
  3. Call set_risk_constraints! on the vector of ceilings, with the set as owner, pr, pl and prefix.

For a vector and no prior result:

  1. For each measure at index i, clear its rke, as above.
  2. Call the index-aware set_risk_constraints! at i, with the set as owner, pr = nothing, pl and prefix.

Arguments

  • model::JuMP.Model: The JuMP optimisation model.
  • r: The set's risk measure, nothing, or a vector of measures.
  • set: The resolved programme Allocation Set.
  • pr: The set's prior result, or nothing when the set reads no rows.
  • pl: The set's resolved phylogeny constraints, or nothing.
  • prefix: The Model State namespace of the entries, Symbol("") on the bare projection model.

Returns

  • nothing.

Related

source
PortfolioOptimisers.risk_contribution_constraints — Method
risk_contribution_constraints(r::Variance, set::ProgrammeAllocationSet, pr::AbstractPriorResult)
risk_contribution_constraints(r::Variance, set::ProgrammeAllocationSet, pr::Nothing)

Resolves the risk-contribution rows of a Variance ceiling on a programme set.

The set resolves r.rc over its own sets, under the strict of the head that runs the step, the same way an optimiser resolves its own rows. When there are rows, the shared builder takes the semidefinite formulation.

Without a prior result the set reads no rows. risk_reads_rows sends a variance with rows to the prior, so r.rc is nothing here, and the method returns it.

Arguments

  • r: The variance ceiling.
  • set: The programme Allocation Set.
  • pr: The set's prior result, or nothing when the set reads no rows.

Returns

  • rc::Option{<:LinearConstraint}: The resolved rows, or nothing when r.rc is nothing.

Related

source
PortfolioOptimisers.clip_at_zero — Function
clip_at_zero(w::AbstractVector)

Raises every negative entry of a projection programme's answer to zero.

A geometry whose domain is the non-negative orthant needs this. The solver meets a zero lower bound only to within its tolerance, so a leg that the programme closes can come back slightly below zero. The next step forms its raw step multiplicatively from the allocation it holds, and would then take log w of a negative number. The clip does not renormalise, so the sum rises by the clipped mass, which is at the size of the solver's tolerance.

Mathematical definition

\[\begin{align} w'_i &= \max(w_i, 0)\,. \end{align}\]

Where:

  • $w_i$: Entry $i$ of the programme's answer.
  • $w'_i$: Entry $i$ of the clipped answer.

Arguments

  • w: The programme's answer.

Returns

  • w'::Vector: w with no entry below zero, in the element type of w.

Related

source