Weight norm constraints: private API
PortfolioOptimisers.set_weight_norm_2_constraints! — Function
set_weight_norm_2_constraints!(model::JuMP.Model, val::Number)
set_weight_norm_2_constraints!(args...)Constrain the 2-norm of the weights.
val is a direct upper bound on $\lVert \boldsymbol{w} \rVert_2$, expressed relative to the budget k: the constraint is $\lVert \boldsymbol{w} \rVert_2 \leq \mathrm{val} \cdot k$. Smaller val forces the weights to spread more evenly across the assets.
The builder takes a number. The caller-facing slot also takes an AbstractNormCeilingCalibrationAlgorithm, which computes the ceiling from the universe the prior result carries, and assemble_jump_model! resolves it before it calls here.
Mathematical definition
\[\begin{align} \mathrm{l2c} &\geq \lVert \boldsymbol{w} \rVert_2\,, \\ \mathrm{l2c} &\leq \mathrm{val} \cdot k\,. \end{align}\]
Where:
- $\mathrm{l2c}$: Auxiliary variable upper-bounding $\lVert \boldsymbol{w} \rVert_2$.
- $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
- $k$: Budget scaling / homogenisation variable.
- $\mathrm{val}$: Upper bound on the 2-norm of the weights.
Diversification interpretation
The 2-norm and the effective number of assets are reciprocally related: for a fully invested portfolio ($k = 1$), $\mathrm{ENA}(\boldsymbol{w}) = 1 / \lVert \boldsymbol{w} \rVert_2^2$. To require at least m effective assets, set val = 1 / sqrt(m):
\[\begin{align} \lVert \boldsymbol{w} \rVert_2 \leq \frac{1}{\sqrt{m}} \iff \mathrm{ENA}(\boldsymbol{w}) = \frac{1}{\lVert \boldsymbol{w} \rVert_2^2} \geq m\,. \end{align}\]
Arguments
model::JuMP.Model: The JuMP optimisation model.val::Number: Upper bound on the 2-norm of the weights.
Returns
nothing.
Details
val::Number: Introduces the auxiliary variablel2c, bounds it below by $\lVert \boldsymbol{w} \rVert_2$ with aSecondOrderConeconstraint, and adds the linear constraintl2c <= val * k.args...: No-op, used when no 2-norm weight constraint is configured.
Related
PortfolioOptimisers.set_weight_norm_p_constraints! — Function
set_weight_norm_p_constraints!(model::JuMP.Model, lps::LpReg_VecLpReg)
set_weight_norm_p_constraints!(args...)Constrain the p-norm of the weights.
Generalises set_weight_norm_2_constraints! to an arbitrary norm order $p > 1$. Each term supplies its own norm order and bound, so several may be imposed at once.
Each term is an LpRegularisation, reused here as a constraint rather than a penalty: its p field is the norm order, and its val field is a direct upper bound on $\lVert \boldsymbol{w} \rVert_p$, expressed relative to the budget k. Smaller val forces a more evenly spread portfolio.
That reuse is why val carries two readings and one bound. Here it is a ceiling, so norm_ceiling_factory refuses an AbstractAmbiguityRadiusCalibrationAlgorithm in it, resolves an AbstractNormCeilingCalibrationAlgorithm against the prior result, and hands each term its own norm order first. Every val this builder sees is therefore a number.
Mathematical definition
\[\begin{align} \mathrm{t}_{p,\, i} &\geq \lVert \boldsymbol{w} \rVert_{p_i}\,, \\ \mathrm{t}_{p,\, i} &\leq \mathrm{val}_i \cdot k\,. \end{align}\]
Where:
- $\mathrm{t}_{p,\, i}$: Auxiliary variable upper-bounding $\lVert \boldsymbol{w} \rVert_{p_i}$.
- $p_i$: Norm order of the $i$-th term, its
pfield. - $\mathrm{val}_i$: Upper bound on the $p_i$-norm of the weights, its
valfield. - $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
- $k$: Budget scaling / homogenisation variable.
Diversification interpretation
For a fully invested portfolio ($k = 1$), the order-$p$ effective number of assets is $\mathrm{ENA}_p(\boldsymbol{w}) = \left(\sum_i \lvert w_i \rvert^p\right)^{1/(1 - p)}$. To require at least m order-$p$ effective assets, set val = m^(1/p - 1):
\[\begin{align} \lVert \boldsymbol{w} \rVert_p \leq m^{1/p - 1} \iff \mathrm{ENA}_p(\boldsymbol{w}) = \left(\sum_i \lvert w_i \rvert^p\right)^{\frac{1}{1 - p}} \geq m\,. \end{align}\]
This is number_effective_assets taken to an arbitrary order. At $p = 2$ the two are the same number, and at every order an equal-weight portfolio over $m$ assets reports exactly $m$. The exponent is also $-1/q$ for the conjugate order $q$, and it tends to $-1$ as $p$ grows, which is the ceiling set_weight_norm_inf_constraints! states.
Arguments
model::JuMP.Model: The JuMP optimisation model.lps::LpReg_VecLpReg: One or more p-norm weight constraints.
Returns
nothing.
Details
lps::LpReg_VecLpReg: For each term, introduces the auxiliary variablest_lpc_iandr_lpc_i, bounds $\lVert \boldsymbol{w} \rVert_{p_i}$ above byt_lpc_iwith a set ofMOI.PowerConeconstraints, and adds the linear constraintt_lpc_i <= val * k. Variables and constraints are suffixed by the term's index, so terms do not collide, and are named distinctly from those ofset_lp_regularisation!so a model may carry both an Lp penalty and a p-norm constraint.args...: No-op, used when no p-norm weight constraint is configured.
Related
PortfolioOptimisers.set_weight_norm_inf_constraints! — Function
set_weight_norm_inf_constraints!(model::JuMP.Model, val::Number)
set_weight_norm_inf_constraints!(args...)Constrain the ∞-norm of the weights, capping the largest absolute weight.
The limiting case of set_weight_norm_p_constraints!. val is a direct upper bound on the largest absolute weight, expressed relative to the budget k: the constraint is $\lVert \boldsymbol{w} \rVert_\infty \leq \mathrm{val} \cdot k$. So a fully invested portfolio ($k = 1$) constrained with val = 0.2 holds no position larger than 20%. Smaller val forces a more evenly spread portfolio.
The builder takes a number. The caller-facing slot also takes an AbstractNormCeilingCalibrationAlgorithm, which computes the ceiling from the universe the prior result carries, and assemble_jump_model! resolves it before it calls here.
Mathematical definition
\[\begin{align} \mathrm{t}_\infty &\geq \lVert \boldsymbol{w} \rVert_\infty\,, \\ \mathrm{t}_\infty &\leq \mathrm{val} \cdot k\,. \end{align}\]
Where:
- $\mathrm{t}_\infty$: Auxiliary variable upper-bounding $\lVert \boldsymbol{w} \rVert_\infty$.
- $\mathrm{val}$: Upper bound on the largest absolute weight.
- $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
- $k$: Budget scaling / homogenisation variable.
Diversification interpretation
Capping the largest weight spreads the portfolio across a minimum number of assets. To spread across at least m assets, set val = 1 / m: no single position can then exceed a $1 / m$ share of a fully invested portfolio.
Arguments
model::JuMP.Model: The JuMP optimisation model.val::Number: Upper bound on the largest absolute weight.
Returns
nothing.
Details
val::Number: Introduces the auxiliary variablet_linfc, bounds it below by $\lVert \boldsymbol{w} \rVert_\infty$ with aMOI.NormInfinityConeconstraint, and adds the linear constraintt_linfc <= val * k.args...: No-op, used when no ∞-norm weight constraint is configured.
Related
PortfolioOptimisers.norm_ball_dual_norm_epigraph! — Function
norm_ball_dual_norm_epigraph!(model::JuMP.Model, prefix::Symbol, i, x, p::Number)Register an epigraph variable of the dual norm of x, raising the cone the dual order of p names.
The cone follows the dual norm order q = dual_norm_order(p), and the four routes are the ones set_weight_norm_2_constraints!, set_weight_norm_inf_constraints!, set_weight_norm_p_constraints! and the box return builder raise for the weights: a second-order cone at $q = 2$, a norm-one cone at $q = 1$ ($p = \infty$), a norm-infinity cone at $q = \infty$ ($p = 1$), and one power cone per entry of x otherwise. Both norm-ball consumers call it, the mean builder on $\mathbf{L}^{\intercal}\boldsymbol{w}$ and the covariance builder on $\mathbf{L}^{\intercal}\operatorname{vec}(\mathbf{W} + \mathbf{E})$, so it takes prefix and i and registers every entry under both.
JuMP formulation
Variables
t_nbucs_i: epigraph of the dual norm, $t \geq \lVert \boldsymbol{x} \rVert_{q}$.r_nbucs_i: one auxiliary per entry ofx, on the power-cone route only.
Constraints
nbucs_cone_i: $(s_c t, s_c \boldsymbol{x}) \in \mathcal{K}_{q}$, with $\mathcal{K}_{2}$ the second-order cone, $\mathcal{K}_{1}$ the norm-one cone and $\mathcal{K}_{\infty}$ the norm-infinity cone. On the power-cone route the entry holds one row per entry ofx: $(s_c r_j, s_c t, s_c x_j) \in \mathcal{P}_{1/q}$, that is $r_j^{1/q} t^{1 - 1/q} \geq \lvert x_j \rvert$.nbucs_cone_sum_i: $s_c \left(\sum_j r_j - t\right) = 0$, on the power-cone route only, which closes $t^{q} \geq \sum_j \lvert x_j \rvert^{q}$.
Where:
- $\boldsymbol{x}$: The affine expression whose dual norm is bounded.
- $q$: Dual norm order of
p. - $s_c$: Constraint scale. It multiplies both sides of a row, so a positive value leaves the feasible set unchanged.
Arguments
model::JuMP.Model: The JuMP optimisation model.prefix: Model State prefix the entries are registered under.i: Index of the term, which suffixes every name the builder registers.x: Affine expression, a vector of at least one entry.p::Number: Norm order of the ball,p >= 1withInfadmitted.
Returns
t_nbucs: The epigraph variable.
Related