Skip to content
18

Budget Constraints

PortfolioOptimisers.BudgetConstraintEstimator Type
julia
abstract type BudgetConstraintEstimator <: JuMPConstraintEstimator

Abstract supertype for all budget constraint estimators.

Related

source
PortfolioOptimisers.Num_BgtCE Type
julia
const Num_BgtCE = Union{<:Number, <:BudgetConstraintEstimator}

Union of scalar budget values and BudgetConstraintEstimator instances.

source
PortfolioOptimisers.BudgetEstimator Type
julia
abstract type BudgetEstimator <: BudgetConstraintEstimator

Abstract supertype for estimators that specify the portfolio budget range (sum of weights).

Related

source
PortfolioOptimisers.BudgetCostEstimator Type
julia
abstract type BudgetCostEstimator <: BudgetConstraintEstimator

Abstract supertype for estimators that specify transaction cost budgets.

Related

source
PortfolioOptimisers.set_budget_costs! Function
julia
set_budget_costs!(args...)

Set transaction cost budget constraints in the JuMP model.

No-op fallback when no cost budget is specified.

Arguments

  • args...: Arguments (ignored).

Returns

  • nothing.

Related

source
PortfolioOptimisers.BudgetRange Type
julia
struct BudgetRange{__T_lb, __T_ub} <: BudgetEstimator

Specifies the portfolio budget constraint as a closed interval [lb,ub] on the sum of weights. At least one of lb or ub must be provided.

Fields

  • lb: Lower bound.

  • ub: Upper bound.

Constructors

julia
BudgetRange(; lb::Option{<:Number} = 1.0, ub::Option{<:Number} = 1.0) -> BudgetRange

Keywords correspond to the struct's fields.

Validation

  • At least one of lb, ub must not be nothing.

  • lb and ub must be finite.

  • lb <= ub when both are provided.

Related

source
PortfolioOptimisers.Num_BgtRg Type
julia
const Num_BgtRg = Union{<:Number, <:BudgetRange}

Alias for a scalar budget value or budget range.

Matches either a plain number (fixed budget, e.g. 1.0) or a BudgetRange (interval budget constraint). Used for dispatch in budget constraint generation.

Related

source
PortfolioOptimisers.BudgetCosts Type
julia
struct BudgetCosts{__T_bgt, __T_w, __T_vp, __T_vn, __T_up, __T_un} <: BudgetCostEstimator

Budget constraint that accounts for linear transaction costs.

Mathematical definition

Models the portfolio budget as:

vpwp+vnwn[lb,ub].

Where:

  • wp, wn: Positive and negative weight increments.

  • vp, vn: Cost coefficient vectors for positive and negative changes.

  • lb, ub: Lower and upper budget bounds.

Fields

  • bgt: Budget target or range.

  • w: Portfolio weights vector assets × 1.

  • vp: Cost coefficients for positive weight changes. Non-negative.

  • vn: Cost coefficients for negative weight changes. Non-negative.

  • up: Upper limit on positive weight changes. Non-negative.

  • un: Upper limit on negative weight changes. Non-negative.

Constructors

julia
BudgetCosts(;
    bgt::Num_BgtRg = 1.0,
    w::VecNum,
    vp::Num_VecNum = 1.0,
    vn::Num_VecNum = 1.0,
    up::Num_VecNum = 1.0,
    un::Num_VecNum = 1.0
) -> BudgetCosts

Keywords correspond to the struct's fields.

Validation

  • !isempty(w).

  • If vp is a vector: !isempty(vp) and all elements >= 0. If scalar: >= 0.

  • If vn is a vector: !isempty(vn) and all elements >= 0. If scalar: >= 0.

  • If up is a vector: !isempty(up) and all elements >= 0. If scalar: >= 0.

  • If un is a vector: !isempty(un) and all elements >= 0. If scalar: >= 0.

View parameters

When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:

Related

source
PortfolioOptimisers.BudgetMarketImpact Type
julia
struct BudgetMarketImpact{__T_bgt, __T_w, __T_vp, __T_vn, __T_up, __T_un, __T_beta} <: BudgetCostEstimator

Budget constraint that accounts for non-linear (power-law) market impact costs. Extends BudgetCosts with a beta exponent controlling the concavity of the market impact function.

Fields

  • bgt: Budget target or range.

  • w: Portfolio weights vector assets × 1.

  • vp: Cost coefficients for positive weight changes. Non-negative.

  • vn: Cost coefficients for negative weight changes. Non-negative.

  • up: Upper limit on positive weight changes. Non-negative.

  • un: Upper limit on negative weight changes. Non-negative.

  • beta: Market impact exponent in (0, 1].

Constructors

julia
BudgetMarketImpact(;
    bgt::Num_BgtRg = 1.0,
    w::VecNum,
    vp::Num_VecNum = 1.0,
    vn::Num_VecNum = 1.0,
    up::Num_VecNum = 1.0,
    un::Num_VecNum = 1.0,
    beta::Number = 2/3
) -> BudgetMarketImpact

Keywords correspond to the struct's fields.

Validation

  • !isempty(w).

  • If vp is a vector: !isempty(vp) and all elements >= 0. If scalar: >= 0.

  • If vn is a vector: !isempty(vn) and all elements >= 0. If scalar: >= 0.

  • If up is a vector: !isempty(up) and all elements >= 0. If scalar: >= 0.

  • If un is a vector: !isempty(un) and all elements >= 0. If scalar: >= 0.

  • 0 <= beta <= 1.

View parameters

When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:

Related

source
PortfolioOptimisers.set_budget_constraints! Function
julia
set_budget_constraints!(args...)
set_budget_constraints!(model::JuMP.Model, val::Number, w::VecNum)
set_budget_constraints!(model::JuMP.Model, bgt::BudgetRange, w::VecNum)
set_budget_constraints!(model::JuMP.Model, bgt::BudgetCosts, w::VecNum)
set_budget_constraints!(model::JuMP.Model, bgt::BudgetMarketImpact, w::VecNum)

Add budget constraints to the JuMP optimisation model.

The fall-through method does nothing. The concrete methods add the appropriate portfolio budget constraint based on the type of budget specification provided.

Mathematical definition

Fixed / range:

klbiwikub.

Where:

  • w: Portfolio weights vector N×1.

  • k: Budget scaling / homogenisation variable.

  • lb, ub: Lower and upper budget bounds.

Linear cost budget (BudgetCosts):

iwi+vpwp+vnwn[klb,kub].

Where:

  • w: Portfolio weights vector N×1.

  • k: Budget scaling / homogenisation variable.

  • wp, wn: Positive and negative weight increments.

  • vp, vn: Cost coefficient vectors for positive and negative changes.

  • lb, ub: Lower and upper budget bounds.

Power-law market-impact budget (BudgetMarketImpact):

iwi+vpwpβ+vnwnβ[klb,kub].

Where:

  • w: Portfolio weights vector N×1.

  • k: Budget scaling / homogenisation variable.

  • wp, wn: Positive and negative weight increments.

  • vp, vn: Market-impact cost coefficient vectors.

  • β(0,1]: Market-impact power exponent.

  • lb, ub: Lower and upper budget bounds.

Arguments

Returns

  • nothing.

Related

source
PortfolioOptimisers.set_long_short_budget_constraints! Function
julia
set_long_short_budget_constraints!(args...)

Set budget constraints for long and short portfolio positions in the JuMP model.

Various overloads handle different budget types (fixed, range), dispatching on the presence or absence of long/short budget configurations.

Arguments

  • args...: JuMP model and budget parameters.

Returns

  • nothing.

Related

source
PortfolioOptimisers.set_cost_budget_constraints! Function
julia
set_cost_budget_constraints!(model, vp, vn, val_or_bgt, w)

Set cost-budget constraints in the JuMP model.

Various overloads handle different cost types (fixed value or BudgetRange).

Arguments

  • model: JuMP optimisation model.

  • vp: Positive cost vector or scalar.

  • vn: Negative cost vector or scalar.

  • val_or_bgt: Fixed budget value or BudgetRange.

  • w: Portfolio weight vector.

Returns

  • nothing.

Related

source
PortfolioOptimisers.set_gross_budget_constraints! Method
julia
set_gross_budget_constraints!(model::JuMP.Model, gbgt::Option{<:Num_BgtRg})

Constrain the gross exposure (leverage) sum(lw) + sum(sw), independently of the net exposure.

A number pins it; a BudgetRange bounds it on either side. Whether the constraint pins the realised gross exposure norm(w, 1) or merely bounds it depends on xbgt — see short_mip_threshold_constraints.

Arguments

  • model::JuMP.Model: JuMP optimisation model.

  • gbgt: Gross budget specification, or nothing for no constraint.

Returns

  • nothing.

Related

source
PortfolioOptimisers.set_gross_budget_constraints! Method
julia
set_gross_budget_constraints!(model::JuMP.Model, gbgt::Option{<:Num_BgtRg})

Constrain the gross exposure (leverage) sum(lw) + sum(sw), independently of the net exposure.

A number pins it; a BudgetRange bounds it on either side. Whether the constraint pins the realised gross exposure norm(w, 1) or merely bounds it depends on xbgt — see short_mip_threshold_constraints.

Arguments

  • model::JuMP.Model: JuMP optimisation model.

  • gbgt: Gross budget specification, or nothing for no constraint.

Returns

  • nothing.

Related

source
PortfolioOptimisers.assert_gross_budget_admissible Function
julia
assert_gross_budget_admissible(bgt, sbgt, gbgt, wb)

Assert that a gross budget is admissible alongside the net and short budgets.

bgt and sbgt constrain the net and gross exposures only together: pinning both gives 1'w == bgt and norm(w, 1) == bgt + 2 * sbgt. gbgt exists for the combination they cannot reach — gross pinned with net free — so it is rejected when they already determine the gross exposure, and when the weight bounds forbid short positions (whereupon gross and net coincide and bgt already owns the constraint).

Only the statically-decidable contradictions are caught. Ranges may still conflict at solve time, surfacing as infeasibility, and a WeightBoundsEstimator is not resolved until then. TimeDependent schedules are reached through assert_time_dependent_substitution.

Related

source
PortfolioOptimisers.set_exact_budget_constraints! Function
julia
set_exact_budget_constraints!(
    model::Model,
    sp::AbstractMIPSpace,
    ind::AbstractMIPIndicators,
    wx::AbstractVector{<:Union{var"#s34", var"#s33"} where {var"#s34"<:Number, var"#s33"<:AbstractJuMPScalar}},
    ss,
    _::WeightsFromParts
)

Pin the long/short decomposition, so the budgets built on lw/sw hold exactly.

lw and sw carry the long and short parts of the weights, and bgt, sbgt and gbgt are all stated in terms of them. Whether those budgets pin the realised exposure or merely bound it depends on how the head related the parts to the weights, so this dispatches on the head's AbstractDecompositionContract. Both methods take the sign from ind, whichever bundle carries one — a dedicated sign bit, or the long/short bits of a builder that already needed them for thresholds or cardinality.

Mathematical definition

Both contracts emit the sign pair, which forces sw = 0 on the long side and lw = 0 on the short side:

lwiMgil0,swiMgis0.

Under PartsBoundWeights that leaves the held side free to overstate itself (lw_i may exceed w_i), so two more constraints close the slack:

lwiwiM(1bil)0,swi+wiM(1bis)0.

Where:

  • gil, gis: Long and short gates (long_gate, short_gate), which relax to continuous variables when the budget is free.

  • bil, bis: Long and short binaries (long_bin, short_bin). The slack-closing pair keys on these rather than the gates, because it must key on a bit that is exactly 0 or 1 even when the gates relax.

  • wi: Weight expression for position i in the space of sp.

  • M: Big-M constant.

Together they give lw_i == max(w_i, 0) and sw_i == max(-w_i, 0): b^l_i = 1 turns the first into lw_i <= w_i, which against the head's lw_i >= w_i is an equality; both bits zero gives lw_i == sw_i == 0, hence w_i == 0.

Under WeightsFromParts the pair alone is enough and the slack-closing constraints are not emitted: w = lw - sw is an identity, so sw_i = 0 already leaves lw_i == w_i.

Arguments

  • model::JuMP.Model: The JuMP optimisation model.

  • sp::AbstractMIPSpace: Weight space the constraints act on.

  • ind::AbstractMIPIndicators: Indicator bundle supplying the sign.

  • wx::VecNum: Weight expression in the space of sp.

  • ss: Big-M expression, as registered by set_mip_ss_expr!.

  • dc::AbstractDecompositionContract: The head's contract. There is deliberately no method for nothing — a model with no head contract has no short side, so there is no decomposition to pin and a caller that got here is confused.

Returns

  • nothing.

Related

source