JuMP Optimiser: private API
PortfolioOptimisers.ProcessedAttributes — Type
abstract type ProcessedAttributes <: AbstractResultAbstract supertype for processed optimiser attributes.
A subtype is the flat bundle of results one optimiser family produces once per optimise call and hands to its model-assembly pipeline. Every collection of processed optimiser attributes subtypes ProcessedAttributes.
Related
PortfolioOptimisers.assert_finite_nonnegative_real_or_vec — Function
assert_finite_nonnegative_real_or_vec(val::Number)
Assert that val is finite and positive; throw an ArgCheck error otherwise.
Accepts a scalar Number or a VecNum. The scalar overload requires isfinite(val) and val > 0. The vector overload is weaker: it requires at least one finite element, at least one strictly positive element, and no negative element, so a vector carrying zeros passes where the scalar 0 does not.
Arguments
val: Scalar or vector to validate.
Returns
nothing.
Examples
julia> PortfolioOptimisers.assert_finite_nonnegative_real_or_vec(1.0)julia> PortfolioOptimisers.assert_finite_nonnegative_real_or_vec([0.5, 1.0])Related
PortfolioOptimisers.jump_optimiser_td_defaults — Function
jump_optimiser_td_defaults(
) -> @NamedTuple{pe::EmpiricalPrior{PortfolioOptimisersCovariance{Covariance{SimpleExpectedReturns{Nothing, Nothing, Nothing}, GeneralCovariance{SimpleCovariance, Nothing, Nothing}, FullMoment, Nothing, Nothing, Nothing}, MatrixProcessing{Posdef{UnionAll, @NamedTuple{}}, Nothing, Nothing, Nothing, NTuple{4, Symbol}}, Nothing}, SimpleExpectedReturns{Nothing, Nothing, Nothing}, Nothing, Nothing, Nothing, Nothing}, wb::WeightBounds{Float64, Float64}, bgt::Float64, ret::ArithmeticReturn{JuMPReturnsSettings{Float64, Nothing, Bool, Bool, Bool}, Nothing, Nothing}, sca::SumScalariser}
Return the static defaults of the JuMPOptimiser 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
PortfolioOptimisers.assert_universe_axis_order — Function
assert_universe_axis_order(sets::Option{<:UniverseSets}, rd::ReturnsResult) -> NothingAssert that every axis UniverseSets declares agrees, name for name and in order, with the returns data it is about to be used against.
Nothing else in the library ties a declared universe to the data's column order. Names resolve to positions in sets.dict[sets.xkey], and those positions index the columns of pr.X; if the two disagree the model is still feasible and still solves — it just constrains the wrong assets. Converting the one silent-wrong-answer failure mode into an error is the whole point, which is why this runs even though no supported path is expected to trip it.
Both axes are checked, but only where both sides exist: rd.nx and rd.nf are optional on ReturnsResult, and the factor axis is optional on UniverseSets. The factor check is redundant with the one constraint_space_basis makes against the loadings and costs nothing when a caller copies rd.nf into the dict; the asset check is new behaviour on a path that has nothing to do with factors, and it may surface pre-existing misconfigurations — that is intended.
_update_asset_sets rebuilds sets.dict[sets.xkey] from rdo.nx before a NestedClustered outer solve, and port_opt_view slices the asset axis alongside the data, so the synthetic-universe and subset paths satisfy this by construction.
Related
PortfolioOptimisers.investable_view — Function
investable_view(
optimiser::JuMPOptimisationEstimator,
rd::ReturnsResult,
_::AbstractPriorResult,
_::Nothing
) -> Tuple{JuMPOptimisationEstimator, ReturnsResult}
Reduce an optimisation estimator and its returns data to the assets an Investable Mask keeps.
processed_jump_optimiser_attributes reduces what the bundle carries — the prior result and every constraint result. It cannot reduce what the head carries: an initial weight vector, a risk measure holding per-asset data, a tracking estimator, a custom constraint. Those travel from the head into assemble_jump_model! unmediated by the bundle, so each head takes this view of itself and of rd before it assembles a model.
The nothing method is the whole all-investable path: it returns both arguments unchanged, so a universe with nothing to exclude allocates nothing and takes the route it took before the mask existed.
The returns matrix the view slices tracking against is rd.X, and pr.X when the caller stated a fitted prior instead of data. port_opt_view reads the prior's own matrix in that case and ignores what it is given, so either is correct and only one of them always exists.
The mask is handed to port_opt_view as the index vector findall(imsk) rather than as the mask itself. Every other caller of that verb passes an integer index, and a view specialised on one index type is a view whose inference is already exercised.
Arguments
optimiser::JuMPOptimisationEstimator: The optimiser head to view.rd: The returns result to use.pr: Prior result.imsk: The Investable Mask the optimisation reduced on:trueat every asset whose prior moments were finite. It isnothingwhen every asset was investable, and that sentinel is what skips both the reduction and the expansion.investable_maskderives it once from the full-universe prior result, and the result carries it, because the reduced prior can no longer yield it.
Returns
(optimiser, rd): Both restricted to the investable assets, or both unchanged.
Related
PortfolioOptimisers.processed_jump_optimiser_attributes — Function
processed_jump_optimiser_attributes(
opt::JuMPOptimiser,
rd::ReturnsResult;
dims::Int = 1
) -> ProcessedJuMPOptimiserAttributesCompute all constraint and prior results needed for model assembly.
Resolves every estimator field of opt against rd — running priors, weight bounds, thresholds, linear constraints, centrality, cardinality, turnover, fees, and phylogeny — and returns the fully processed bundle as a ProcessedJuMPOptimiserAttributes. The result is consumed directly by assemble_jump_model! and also stored in the per-optimiser Result struct, so processing happens exactly once per optimise call.
Arguments
opt::JuMPOptimiser: JuMP optimiser configuration.rd: The returns result to use.dims::Int = 1: Observation dimension passed to the prior estimator.
Returns
ProcessedJuMPOptimiserAttributes: Fully resolved constraint and prior bundle.
Related
PortfolioOptimisers.processed_jump_optimiser — Function
processed_jump_optimiser(
opt::JuMPOptimiser,
rd::ReturnsResult;
dims::Int = 1
) -> JuMPOptimiserBuild a fully-processed JuMPOptimiser from raw configuration and returns data.
Calls processed_jump_optimiser_attributes then repackages the result via jump_optimiser_from_attributes. Used where a processed optimiser is needed for inner sub-problems (e.g. NearOptimalCentering) while the attrs bundle is reused directly by assemble_jump_model!.
Arguments
opt::JuMPOptimiser: Raw optimiser configuration.rd: The returns result to use.dims::Int = 1: Observation dimension passed to the prior estimator.
Returns
JuMPOptimiser: Optimiser with all estimator slots populated from processed results.
Related
PortfolioOptimisers.assemble_jump_model! — Function
assemble_jump_model!(
model::JuMP.Model,
optimiser::JuMPOptimisationEstimator,
opt::JuMPOptimiser,
attrs::ProcessedJuMPOptimiserAttributes,
rd::ReturnsResult,
r::Option{<:RM_VecRM} = nothing,
obj::ObjectiveFunction = MinimumRisk(),
b1::Option{<:MatNum} = nothing,
sdp_asset_phylogeny::Bool = true
) -> NothingRun the invariant model-assembly sequence shared by all single-JuMP-model optimisers.
Executes the constraint-builder pipeline — from set_linear_weight_constraints! through add_custom_constraint! — that sits between the per-optimiser head (weight variables) and tail (objective + solve). The head must have populated Model State (w/k variables) before calling this function. See Model Assembly in CONTEXT.md and 0008-jump-model-assembly.md.
The tail of the sequence is assert_frontier_sweep_cap: both frontier registries are complete here and no sweep solve has started, so this is the one point at which the total sweep — the product across every swept return term and every swept risk measure — is in hand and can be capped.
Arguments
model::JuMP.Model: The JuMP optimisation model.optimiser::JuMPOptimisationEstimator: Dispatch object for risk, tracking, and custom constraint builders.opt::JuMPOptimiser: Supplies scalar settings (l2c,lpc,linfc,l1,l2,lp,linf,card,scard,tr,ccnt,sca,ss). The four regularisation coefficients and the three norm ceilings are the one place a Calibration Rule reaches the model builders, so they are resolved againstattrs.prhere rather than byprocessed_jump_optimiser_attributes: the bundle carries no slot for them and this is where both the prior result and the optimiser are in hand. A ceiling is read against one norm order, so each of the three sites states its own order in theCalibrationContextit resolves the slot against.attrs::ProcessedJuMPOptimiserAttributes: Pre-computed constraint and prior bundle produced byprocessed_jump_optimiser_attributes.rd: The returns result to use.r::Option{<:RM_VecRM} = nothing: Risk measure(s), ornothingto skip risk constraints and scalarisation (theRelaxedRiskBudgetingpath).obj::ObjectiveFunction = MinimumRisk(): Objective used by the return constraints.b1::Option{<:MatNum} = nothing: Factor loading matrix forFactorRiskContribution;nothingfor all other optimisers.sdp_asset_phylogeny::Bool = true: Whether to apply the standard asset-space SDP phylogeny constraints.FactorRiskContributionpassesfalseand applies its own factor-space variant in its tail instead.
Returns
nothing. Mutatesmodelin place.
Related
PortfolioOptimisers.set_risk_and_scalarise! — Function
set_risk_and_scalarise!(
::Model,
::Nothing,
optimiser,
opt,
pr,
pl,
fees::Union{Nothing, Fees};
...
)
set_risk_and_scalarise!(
::Model,
::Nothing,
optimiser,
opt,
pr,
pl,
fees::Union{Nothing, Fees},
b1::Union{Nothing, AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}};
kwargs...
)
Add risk-measure constraints and scalarise the combined risk expression in model.
One step of assemble_jump_model!, dispatched on r: when r is nothing (e.g. RelaxedRiskBudgeting, whose risk lives in its head) this is a no-op.
This is the one place the fee argument is positional. Every head reaches set_risk_constraints! through it, so a head cannot mis-order the list and lose the fees: unconstrained NearOptimalCentering did exactly that while it inlined the step.
Arguments
model::JuMP.Model: JuMP optimisation model (mutated in place).r: Risk measure(s), ornothingto skip this step entirely.optimiser: Dispatch object forset_risk_constraints!.opt::JuMPOptimiser: Supplies the scalariseropt.sca.pr: Prior result passed to risk builders.pl: Phylogeny result passed to risk builders.fees: Fees result passed to risk builders.b1::Option{<:MatNum} = nothing: Factor loading matrix forFactorRiskContribution;nothingfor all other optimisers.rd: Returns result forwarded as a keyword argument to risk builders.
Returns
nothing.
Related
PortfolioOptimisers.jump_optimiser_from_attributes — Function
jump_optimiser_from_attributes(
opt::JuMPOptimiser,
attrs::ProcessedJuMPOptimiserAttributes
) -> JuMPOptimiserRepackage a ProcessedJuMPOptimiserAttributes into a JuMPOptimiser.
Maps result-named fields onto the optimiser's estimator-named slots (lcsr → lcse, plr → ple, pr → pe, …) and carries all remaining settings through from opt. Used where a processed optimiser object is needed for inner sub-problems (e.g. near_optimal_centering_setup) while the same attrs is also passed directly to assemble_jump_model! — so processing happens once and is never round-tripped.
Arguments
opt::JuMPOptimiser: Source optimiser supplying solver, scalar settings, and any fields not present inattrs.attrs::ProcessedJuMPOptimiserAttributes: Pre-computed constraint and prior bundle.
Returns
JuMPOptimiser: Optimiser with all estimator slots populated fromattrs.
Related