JuMP Optimiser
PortfolioOptimisers.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, __T_sca, __T_imsk} <: 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.
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 constraint result. TheLinearConstraintthe centrality constraints resolve to.
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: Return term, or vector of return terms, for theJuMPmodel. Several terms are weighted-summed into the model's single scalar return expression, in the same wayMeanRisk'srtakes several risk measures.
sca: The scalariser the optimisation ran under, taken fromopt.sca. Pass it back asexpected_risk(res.r, res.w, res.pr; sca = res.sca)so the reported figure matches the optimised one.
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.
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{<:Union{<:AbstractPhylogenyConstraintResult, <:AbstractVector{<:AbstractPhylogenyConstraintResult}}}, ret::JRE_VecJRE, sca::Scalariser, imsk::Option{<:BitVector} = nothing) -> 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(), sca = SumScalariser()) isa ProcessedJuMPOptimiserAttributestrueRelated
PortfolioOptimisers.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 01_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
PortfolioOptimisers.JuMPOptimiser — Type
struct JuMPOptimiser{__T_pe, __T_slv, __T_wb, __T_bgt, __T_sbgt, __T_gbgt, __T_xbgt, __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_l2c, __T_lpc, __T_linfc, __T_l1, __T_l2, __T_lp, __T_linf, __T_brt, __T_x_src, __T_strict, __T_cache} <: 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: Net budget,1ᵀw. A number pins it, aBudgetRangebounds it. By default budgets bound the realised exposure rather than pinning it (seexbgt). Together withsbgtthis fixes the net and gross exposures only jointly; to constrain the gross exposure on its own seegbgt.
sbgt: Short-side budget,sum(sw). A number pins it, aBudgetRangebounds it; by default it bounds, sosbgt = 0.3means at most 30% short unlessxbgtpins the long/short decomposition. Together withbgtthis fixes the net and gross exposures only jointly; to constrain the gross exposure on its own seegbgt.
gbgt: Gross budget (leverage) constraint,sum(lw) + sum(sw). A number pins the gross exposure; aBudgetRangebounds it, e.g.BudgetRange(; lb = nothing, ub = 2.0)caps leverage at 2x. Unlikebgtandsbgt— which pin the net and gross exposures only together — this constrains the gross exposure on its own, leaving the net free. Requires weight bounds that admit short positions, and is bounded rather than pinned unlessxbgtis set.
xbgt: Whether to pin the long/short decomposition exactly. Whenfalse(the default),lwandsware upper bounds on the positive and negative parts ofw, sobgt,sbgtandgbgtbound the realised exposures rather than pinning them — a short budget of0.3means at most 30% short. Whentrue, the long/short binary indicators forcelw == max(w, 0)andsw == max(-w, 0), so the budgets hold exactly, at the cost of turning the problem into a mixed-integer program. It reuses the indicators the cardinality, threshold and fee builders already create (seeshort_mip_threshold_constraints) rather than adding its own, and is ignored when the weight bounds admit no shorts.
lt: Long-side minimum holding threshold.
st: Short-side minimum holding threshold.
lcse: Linear constraint set estimator(s). This is the one constraint slot that also admits anExposureConstraintEstimator, so a row may be written in the names of another basis — factor names, say — and re-based through the prior's loadings at generation time. What reaches the model is an ordinary asset-spaceLinearConstrainteither way.
cte: Centrality constraint(s). ACentralityConstraint, a vector of them, or an already-generatedLinearConstraint. Resolved bycentrality_constraintsinto thectrslot ofProcessedJuMPOptimiserAttributes.
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 assets.
tr: Tracking error constraint(s).
ple: Phylogeny constraint estimator(s).
ret: Return term, or vector of return terms, for theJuMPmodel. Several terms are weighted-summed into the model's single scalar return expression, in the same wayMeanRisk'srtakes several risk measures.
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).
l2c: 2-norm ceiling on the weights — boundsnorm(w, 2) <= l2c * k(kis the budget,1for a fully invested portfolio). Smallerl2cforces a more evenly spread portfolio. Used as a diversification floor via the reciprocal:l2c = 1 / sqrt(m)requires at leastmeffective assets (inv(norm(w, 2)^2) >= m). Norm-constraint family withlpcandlinfc. The bound isNum_NormCeilCalunder the time-dependent wrapper, so the slot takes the ceiling itself, anAbstractNormCeilingCalibrationAlgorithmthat computes it from the prior result, or a plain function of the same five arguments.
lpc: p-norm ceiling(s) on the weights at an arbitrary norm order. EachLpRegularisationsupplies a norm orderpand a boundval, enforcingnorm(w, p) <= val * k. Smallervalforces a more evenly spread portfolio. Used as a diversification floor via the reciprocal:val = m^(1/p - 1)requires at leastmorder-peffective assets (sum(abs.(w) .^ p)^inv(1 - p) >= m), which isnumber_effective_assetstaken to an arbitrary order. Norm-constraint family withl2candlinfc.
linfc: ∞-norm ceiling on the weights — a cap on the largest absolute weight:norm(w, Inf) <= linfc * k. Solinfc = 0.2caps the largest weight at 20% of a fully invested portfolio. Used as a diversification floor via the reciprocal:linfc = 1 / mspreads the portfolio across at leastmassets. Norm-constraint family withl2candlpc. The bound isNum_NormCeilCalunder the time-dependent wrapper, so the slot takes the ceiling itself, anAbstractNormCeilingCalibrationAlgorithmthat computes it from the prior result, or a plain function of the same five arguments.
l1: L1 regularisation coefficient. It is the ambiguity radius of a type-$\infty$ Wasserstein ground metric, whose dual norm is the 1-norm, so the bound isNum_AmbRadCalunder the time-dependent wrapper and the slot takes anAbstractAmbiguityRadiusCalibrationAlgorithmthat computes it from the prior result, or a plain function of the same five arguments.
l2: L2 regularisation term(s).
lp: Lp regularisation specification(s).
linf: L∞ regularisation coefficient. It is the ambiguity radius of a type-1 Wasserstein ground metric, whose dual norm is the $\infty$-norm, so the bound isNum_AmbRadCalunder the time-dependent wrapper and the slot takes anAbstractAmbiguityRadiusCalibrationAlgorithmthat computes it from the prior result, or a plain function of the same five arguments.
brt: Whether to use bootstrap returns.
x_src: Which returns matrix the clustering, phylogeny and centrality estimators read::priortakes the prior result'sX,:datatakes the raw returns result'sX. Ignored when no returns result is available, in which case the prior result'sXis used.
strict: Whether to strictly enforce weight bounds.
cache: OptionalReturnsBufferState, the fold context of the online step. It isnothinguntilpartial_fit!writes one, andoptimise(opt)with no returns reads it. The returns themselves are carried by the prior, which owns the rows once; this holds every other column of the carrier and the context pinned at the first step.factorycarries it unchanged andport_opt_viewslices it to the selected assets.
Constructors
JuMPOptimiser(; pe::Onl{<: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, gbgt::TD_Option{<:Num_BgtRg} = nothing, xbgt::Bool = false, lt::TD_Option{<:BtE_Bt} = nothing, st::TD_Option{<:BtE_Bt} = nothing, lcse::TD_Option{<:EcE_LcE_Lc_VecEcE_LcE_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{<:UniverseSets} = nothing, tr::TD_Option{<:Tr_VecTr} = nothing, ple::TD_Option{<:PlCE_PlC_VecPlCE_PlC} = nothing, ret::TD{<:JRE_VecJRE} = ArithmeticReturn(), sca::TD{<:NonHierarchicalScalariser} = SumScalariser(), ccnt::TD_Option{<:JuMPConstr_VecJuMPConstr} = nothing, cobj::TD_Option{<:JuMPObj_VecJuMPObj} = nothing, sc::Number = 1, so::Number = 1, ss::TD_Option{<:Number} = nothing, card::TD_Option{<:Integer} = nothing, scard::TD_Option{<:Int_VecInt} = nothing, l2c::TD_Option{<:Num_NormCeilCal} = nothing, lpc::TD_Option{<:LpReg_VecLpReg} = nothing, linfc::TD_Option{<:Num_NormCeilCal} = nothing, l1::TD_Option{<:Num_AmbRadCal} = nothing, l2::TD_Option{<:L2Reg_VecL2Reg} = nothing, lp::TD_Option{<:LpReg_VecLpReg} = nothing, linf::TD_Option{<:Num_AmbRadCal} = nothing, brt::Bool = false, x_src::Symbol = :prior, strict::Bool = false, cache::Option{<:ReturnsBufferState} = nothing,) -> 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, x_src, strict) stays static.
Validation
x_src in (:prior, :data).- 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
gbgtis a number:isfinite(gbgt)andgbgt >= 0. - If
gbgtis provided:wbmust admit short positions, andbgtandsbgtmust not both be pinned numbers (which already determine the gross exposure asbgt + 2 * sbgt). - If
cteis a vector:!isempty(cte). - If
cardis provided:card > 0and finite. - If
tnortris a vector: each must be non-empty. - If
l2c,linfc,l1, orlinfis provided as a number: each must be> 0and finite.l1andlinfalso take an ambiguity-radius rule, andl2candlinfca norm-ceiling rule. A rule states no number here, so the check runs on the number the rule returns, inassemble_jump_model!. - The rule in each
LpRegularisationis checked against the field that holds it:lpis a penalty, so it refuses a norm-ceiling rule, andlpcis a constraint, so it refuses an ambiguity-radius rule. The term itself carries one bound for both readings, so this is the point at which the reading is known. - If
l2,lporlpcis a vector: each must be non-empty. An empty vector builds no term, which is whatnothingalready spells. l2,lpandlpcare 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
PortfolioOptimisers.factory — Method
factory(
opt::JuMPOptimiser,
w::AbstractVector
) -> JuMPOptimiser{_A, _B, _C, _D, _E, _F, Bool, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, _Z1, var"#s185", var"#s1851", _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10, _Z11, Bool, Symbol, 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, _Z1, var"#s185"<:Number, var"#s1851"<:Number, _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10, _Z11}
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 JuMPOptimisertrueRelated
PortfolioOptimisers.port_opt_view — Method
port_opt_view(
opt::JuMPOptimiser,
i,
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
args...
) -> JuMPOptimiser{_A, _B, _C, _D, _E, _F, Bool, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, _Z1, var"#s185", var"#s1851", _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10, _Z11, Bool, Symbol, 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, _Z1, var"#s185"<:Number, var"#s1851"<:Number, _Z2, _Z3, _Z4, _Z5, _Z6, _Z7, _Z8, _Z9, _Z10, _Z11}
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: Asset returns matrix (observations x assets) used to slice tracking estimators. A precomputed prior inopt.pesupplies its ownXinstead.
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 JuMPOptimisertrueRelated
PortfolioOptimisers.needs_previous_weights — Method
needs_previous_weights(opt::JuMPOptimiser) -> Any
Return 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