JuMP Optimiser
PortfolioOptimisers.ProcessedAttributes Type
abstract type ProcessedAttributes <: AbstractResultAbstract supertype for processed optimiser attributes. Every collection of processed optimiser attributes should subtype
Related
sourcePortfolioOptimisers.ProcessedJuMPOptimiserAttributes Type
struct ProcessedJuMPOptimiserAttributes{__T_pr, __T_wb, __T_lt, __T_st, __T_lcsr, __T_ctr, __T_gcardr, __T_sgcardr, __T_smtx, __T_sgmtx, __T_slt, __T_sst, __T_sglt, __T_sgst, __T_tn, __T_fees, __T_plr, __T_ret} <: ProcessedAttributesFlat bundle of all processed constraint and prior results consumed by assemble_jump_model!.
Produced once per optimise call by processed_jump_optimiser_attributes and passed directly to the model-assembly pipeline, so every builder reads already-resolved results rather than re-processing estimators. See ADR 0008 (0008-jump-model-assembly.md).
Fields
pr: Prior result.wb: Weight bounds.lt: Long-side minimum holding threshold.st: Short-side minimum holding threshold.lcsr: Processed linear constraint set result.ctr: Centrality result.gcardr: Processed grouped cardinality constraint result.sgcardr: Processed sub-grouped cardinality constraint result.smtx: Sub-group selection matrix or estimator.sgmtx: Sub-grouped selection matrix or estimator.slt: Sub-group long threshold.sst: Sub-group short threshold.sglt: Sub-grouped long threshold.sgst: Sub-grouped short threshold.tn: Turnover result.fees: Fees result.plr: Phylogeny result.ret: Returns estimator for theJuMPmodel.
Constructors
ProcessedJuMPOptimiserAttributes(;
pr::AbstractPriorResult, wb::Option{<:WeightBounds}, lt::Option{<:Threshold},
st::Option{<:Threshold}, lcsr::Option{<:Lc_VecLc}, ctr::Option{<:Lc_CC_VecCC},
gcardr::Option{<:LinearConstraint}, sgcardr::Option{<:Lc_VecLc},
smtx::Option{<:MatNum_VecMatNum}, sgmtx::Option{<:MatNum_VecMatNum},
slt::Option{<:Bt_VecOptBt}, sst::Option{<:Bt_VecOptBt}, sglt::Option{<:Bt_VecOptBt},
sgst::Option{<:Bt_VecOptBt}, tn::Option{<:Tn_VecTn}, fees::Option{<:Fees},
plr::Option{<:AbstractPhylogenyConstraintResult}, ret::JuMPReturnsEstimator
) -> ProcessedJuMPOptimiserAttributesKeywords correspond to the struct's fields. The field types are the result side of the matching JuMPOptimiser estimator slots: this bundle holds the constraint and prior results produced by processed_jump_optimiser_attributes, not the raw estimators (ret aside — a returns estimator has no separate result form). In practice, construct via processed_jump_optimiser_attributes rather than directly.
Examples
julia> pr = prior(EmpiricalPrior(),
ReturnsResult(; nx = ["a", "b"], X = [0.1 -0.2; -0.1 0.2; 0.05 0.1]));
julia> ProcessedJuMPOptimiserAttributes(; pr = pr, wb = nothing, lt = nothing, st = nothing,
lcsr = nothing, ctr = nothing, gcardr = nothing,
sgcardr = nothing, smtx = nothing, sgmtx = nothing,
slt = nothing, sst = nothing, sglt = nothing,
sgst = nothing, tn = nothing, fees = nothing,
plr = nothing, ret = ArithmeticReturn()) isa
ProcessedJuMPOptimiserAttributes
trueRelated
sourcePortfolioOptimisers.JuMPOptimisationResult Type
struct JuMPOptimisationResult{__T_pa, __T_retcode, __T_sol, __T_model} <: BaseJuMPOptimisationResultShared field core for JuMP-based optimisation results.
Holds the fields common to every JuMP optimisation result. Embedded as the first field (jr) of each concrete JuMP result, analogous to how JuMPOptimiser is embedded as opt in each JuMP optimiser. The concrete result keeps only its unique fields plus the trailing fb.
Defined here (rather than in 08_Base_JuMPOptimisation.jl, where its BaseJuMPOptimisationResult supertype lives) so its typed constructor can bind pa::ProcessedJuMPOptimiserAttributes and sol::JuMPOptimisationSolution, both in scope at this point in load order.
Fields
pa: Processed optimisation attributes.retcode: Optimisation return code.sol: Optimisation solution.model: :JuMP.Model`: The JuMP optimisation model.
Constructors
JuMPOptimisationResult(;
pa::ProcessedJuMPOptimiserAttributes,
retcode::OptRetCode_VecOptRetCode,
sol::JuMPOptSol_VecJuMPOptSol,
model::Option{<:JuMP.Model}
) -> JuMPOptimisationResultKeywords correspond to the struct's fields.
Related
sourcePortfolioOptimisers.assert_finite_nonnegative_real_or_vec Function
assert_finite_nonnegative_real_or_vec(val::Number)Assert that val is finite and non-negative; throw an ArgCheck error otherwise.
Accepts a scalar Number or a VecNum; the vector overload requires at least one finite and non-negative element and no negative elements.
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
sourcePortfolioOptimisers.JuMPOptimiser Type
struct JuMPOptimiser{__T_pe, __T_slv, __T_wb, __T_bgt, __T_sbgt, __T_lt, __T_st, __T_lcse, __T_cte, __T_gcarde, __T_sgcarde, __T_smtx, __T_sgmtx, __T_slt, __T_sst, __T_sglt, __T_sgst, __T_tn, __T_fees, __T_sets, __T_tr, __T_ple, __T_ret, __T_sca, __T_ccnt, __T_cobj, __T_sc, __T_so, __T_ss, __T_card, __T_scard, __T_wn2, __T_wnp, __T_wninf, __T_l1, __T_l2, __T_linf, __T_lp, __T_brt, __T_cle_pr, __T_strict} <: BaseJuMPOptimisationEstimatorMain JuMP-based portfolio optimiser configuration.
JuMPOptimiser collects all the inputs needed to formulate and solve a JuMP-based portfolio optimisation problem: prior estimator, solver, constraints, bounds, fees, tracking, regularisation, and more. It is intended to be passed to a higher-level optimiser such as MeanRisk or RiskBudgeting.
Fields
pe: Prior estimator.slv: Solver or vector of solvers.wb: Weight bounds estimator or weight bounds.bgt: Portfolio budget constraint.sbgt: Short-sale budget constraint.lt: Long-side minimum holding threshold.st: Short-side minimum holding threshold.lcse: Linear constraint set estimator(s).cte: Centring constraint estimator or constraint(s).gcarde: Grouped cardinality constraint estimator.sgcarde: Sub-grouped cardinality constraint estimator(s).smtx: Sub-group selection matrix or estimator.sgmtx: Sub-grouped selection matrix or estimator.slt: Sub-group long threshold.sst: Sub-group short threshold.sglt: Sub-grouped long threshold.sgst: Sub-grouped short threshold.tn: Turnover constraint estimator(s).fees: Fee estimator or fee structure.sets: Sets used to map estimator values to features.tr: Tracking error constraint(s).ple: Phylogeny constraint estimator(s).ret: Returns estimator for theJuMPmodel.sca: Scalariser for combining multiple risk measures.ccnt: CustomJuMPconstraint.cobj: CustomJuMPobjective.sc: Constraint scale factor.so: Objective scale factor.ss: Optional scalar shrinkage parameter.card: Global cardinality constraint.scard: Sub-group cardinality constraint(s).wn2: 2-norm weight constraint. Lower bound on the effective number of assets,inv(norm(w, 2)^2) >= wn2.wnp: P-norm weight constraint(s). EachLpRegularisationsupplies a norm orderpand a lower boundvalon the p-norm effective number of assets,inv(norm(w, p)^p) >= val.wninf: Infinity-norm weight constraint. Lower bound oninv(norm(w, Inf)), equivalently an upper boundinv(wninf)on the largest weight.l1: L1 regularisation coefficient.l2: L2 regularisation term(s).linf: L∞ regularisation coefficient.lp: Lp regularisation specification(s).brt: Whether to use bootstrap returns.cle_pr: Whether to pass the prior result to the clustering estimator.strict: Whether to strictly enforce weight bounds.
Constructors
JuMPOptimiser(;
pe::TD{<:PrE_Pr} = EmpiricalPrior(),
slv::Slv_VecSlv,
wb::TD_Option{<:WbE_Wb} = WeightBounds(),
bgt::TD_Option{<:Num_BgtCE} = 1.0,
sbgt::TD_Option{<:Num_BgtRg} = nothing,
lt::TD_Option{<:BtE_Bt} = nothing,
st::TD_Option{<:BtE_Bt} = nothing,
lcse::TD_Option{<:LcE_Lc_VecLcE_Lc} = nothing,
cte::TD_Option{<:Lc_CC_VecCC} = nothing,
gcarde::TD_Option{<:LcE_Lc} = nothing,
sgcarde::TD_Option{<:LcE_Lc_VecLcE_Lc} = nothing,
smtx::TD_Option{<:MatNum_ASetMatE_VecMatNum_ASetMatE} = nothing,
sgmtx::TD_Option{<:MatNum_ASetMatE_VecMatNum_ASetMatE} = nothing,
slt::TD_Option{<:BtE_Bt_VecOptBtE_Bt} = nothing,
sst::TD_Option{<:BtE_Bt_VecOptBtE_Bt} = nothing,
sglt::TD_Option{<:BtE_Bt_VecOptBtE_Bt} = nothing,
sgst::TD_Option{<:BtE_Bt_VecOptBtE_Bt} = nothing,
tn::TD_Option{<:TnE_Tn_VecTnE_Tn} = nothing,
fees::TD_Option{<:FeesE_Fees} = nothing,
sets::TD_Option{<:AssetSets} = nothing,
tr::TD_Option{<:Tr_VecTr} = nothing,
ple::TD_Option{<:PlCE_PhC_VecPlCE_PlC} = nothing,
ret::TD{<:JuMPReturnsEstimator} = ArithmeticReturn(),
sca::TD{<:NonHierarchicalScalariser} = SumScalariser(),
ccnt::TD_Option{<:CustomJuMPConstraint} = nothing,
cobj::TD_Option{<:CustomJuMPObjective} = nothing,
sc::Number = 1,
so::Number = 1,
ss::TD_Option{<:Number} = nothing,
card::TD_Option{<:Integer} = nothing,
scard::TD_Option{<:Int_VecInt} = nothing,
wn2::TD_Option{<:Number} = nothing,
wnp::TD_Option{<:LpReg_VecLpReg} = nothing,
wninf::TD_Option{<:Number} = nothing,
l1::TD_Option{<:Number} = nothing,
l2::TD_Option{<:L2Reg_VecL2Reg} = nothing,
linf::TD_Option{<:Number} = nothing,
lp::TD_Option{<:LpReg_VecLpReg} = nothing,
brt::Bool = false,
cle_pr::Bool = true,
strict::Bool = false,
) -> JuMPOptimiserKeywords correspond to the struct's fields. Fields typed TD_Option or TD may hold a TimeDependent per-fold schedule instead of a static value; a cross-validation fold loop resolves it per fold, and a fold-less optimise runs with the field at its static default. The problem definition — the prior estimator, returns model, scalariser and asset sets as much as the constraints — may therefore vary over folds; execution control (slv, sc, so, brt, cle_pr, strict) stays static.
Validation
If
slvis a vector:!isempty(slv).If
bgtis a number:isfinite(bgt).If
bgtis aBudgetCostEstimator:isnothing(sbgt).If
sbgtis a number:isfinite(sbgt)andsbgt >= 0.If
cteis a vector:!isempty(cte).If
cardis provided:card > 0and finite.If
tnortris a vector: each must be non-empty.If
wn2,wninf,l1, orlinfis provided: each must be> 0and finite.If
lpis a vector:!isempty(lp).l2,lpandwnpare validated by their own estimator constructors (L2Regularisation,LpRegularisation).If
scardis provided: compatiblesmtx,slt,sstsizes required.If
sgcardeis provided: compatiblesgmtx,sglt,sgstsizes required.If any estimator-type field (
wb,lt,fees, etc.) is provided:!isnothing(sets).If any field holds a
TimeDependent: every vector entry is test-substituted through this constructor (with the other time-dependent fields at their static defaults) so type and cross-field compatibility errors surface immediately. Validation coupling a time-dependent field to static fields is deferred to the per-fold rebuild.
Related
sourcePortfolioOptimisers.needs_previous_weights Method
needs_previous_weights(opt::JuMPOptimiser) -> AnyReturn true if any sub-estimator of opt requires previous portfolio weights.
Checks turnover, fees, tracking error, custom constraint, and custom objective fields.
Arguments
opt::JuMPOptimiser: JuMP optimiser configuration.
Returns
Bool:trueif any sub-estimator needs previous weights;falseotherwise.
Examples
julia> PortfolioOptimisers.needs_previous_weights(JuMPOptimiser(;
slv = Solver(; solver = nothing)))
falseRelated
sourcePortfolioOptimisers.factory Method
factory(
opt::JuMPOptimiser,
w::AbstractVector
) -> JuMPOptimiser{_A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, var"#s179", var"#s1791", _Z1, _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10, Bool, Bool, Bool} where {_A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, var"#s179"<:Number, var"#s1791"<:Number, _Z1, _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10}Return a copy of opt with all weight-tracking estimator fields updated via factory for the new weights w.
Updates turnover, fees, tracking error, custom constraint, and custom objective fields; all other fields are carried through unchanged.
Arguments
opt::JuMPOptimiser: JuMP optimiser configuration.w::AbstractVector: New portfolio weights.
Returns
JuMPOptimiser: Updated optimiser with weight-tracking fields refreshed.
Examples
julia> opt = JuMPOptimiser(; slv = Solver(; solver = nothing));
julia> PortfolioOptimisers.factory(opt, fill(0.1, 10)) isa JuMPOptimiser
trueRelated
sourcePortfolioOptimisers.port_opt_view Method
port_opt_view(
opt::JuMPOptimiser,
i,
X::AbstractMatrix{<:Union{var"#s29", var"#s28"} where {var"#s29"<:Number, var"#s28"<:AbstractJuMPScalar}},
args...
) -> JuMPOptimiser{_A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, var"#s179", var"#s1791", _Z1, _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10, Bool, Bool, Bool} where {_A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, var"#s179"<:Number, var"#s1791"<:Number, _Z1, _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10}Return a cluster-sliced copy of opt restricted to asset indices i.
Slices all per-asset estimator fields (prior, weight bounds, thresholds, turnover, fees, tracking, custom constraint/objective) to the cluster; solver and scalar parameters are carried through unchanged.
Arguments
opt::JuMPOptimiser: JuMP optimiser configuration.i: Asset index or index set for the cluster.X::MatNum: FullMoment returns matrix used to slice tracking estimators.
Returns
JuMPOptimiser: Cluster-restricted optimiser.
Examples
julia> opt = JuMPOptimiser(; slv = Solver(; solver = nothing));
julia> X = rand(50, 5);
julia> PortfolioOptimisers.port_opt_view(opt, 1:3, X) isa JuMPOptimiser
trueRelated
sourcePortfolioOptimisers.jump_optimiser_td_defaults Function
jump_optimiser_td_defaults(
) -> @NamedTuple{pe::EmpiricalPrior{PortfolioOptimisersCovariance{Covariance{SimpleExpectedReturns{Nothing}, GeneralCovariance{SimpleCovariance, Nothing}, FullMoment}, MatrixProcessing{Posdef{UnionAll, @NamedTuple{}}, Nothing, Nothing, Nothing, NTuple{4, Symbol}}}, SimpleExpectedReturns{Nothing}, Nothing}, wb::WeightBounds{Float64, Float64}, bgt::Float64, ret::ArithmeticReturn{Nothing, 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
sourcePortfolioOptimisers.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
sourcePortfolioOptimisers.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(),
miprb_flag::Bool = false,
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.
Arguments
model::JuMP.Model: The JuMP optimisation model.optimiser::JuMPOptimisationEstimator: Dispatch object for risk, tracking, and custom constraint builders.opt::JuMPOptimiser: Supplies scalar settings (wn2,wninf,l1,l2,linf,lp,card,scard,tr,ccnt,sca,ss).attrs::ProcessedJuMPOptimiserAttributes: Pre-computed constraint and prior bundle produced byprocessed_jump_optimiser_attributes.rd: The returns result to use.r::Option{<:RiskMeasure} = nothing: Risk measure(s), ornothingto skip risk constraints and scalarisation (theRelaxedRiskBudgetingpath).obj::ObjectiveFunction = MinimumRisk(): Objective used by the return constraints.miprb_flag::Bool = false: Mixed-integer risk-budgeting flag forset_mip_constraints!; onlyRiskBudgetingpassestrue.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.
Examples
julia> using PortfolioOptimisers
julia> pr = prior(EmpiricalPrior(),
ReturnsResult(; nx = ["a", "b"], X = [0.1 -0.2; -0.1 0.2; 0.05 0.1]));
julia> ProcessedJuMPOptimiserAttributes(; pr = pr, wb = nothing, lt = nothing, st = nothing,
lcsr = nothing, ctr = nothing, gcardr = nothing,
sgcardr = nothing, smtx = nothing, sgmtx = nothing,
slt = nothing, sst = nothing, sglt = nothing,
sgst = nothing, tn = nothing, fees = nothing,
plr = nothing, ret = ArithmeticReturn()) isa
ProcessedJuMPOptimiserAttributes
trueRelated
PortfolioOptimisers.set_risk_and_scalarise! Function
set_risk_and_scalarise!(
::Model,
::Nothing,
args...;
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. extra is the optional trailing-argument tuple — empty for most optimisers, or (b1,) for FactorRiskContribution — splatted into set_risk_constraints! so the non-factor call signature is reproduced exactly.
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.extra: Trailing-argument tuple splatted into risk builders (()or(b1,)).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