OWA Risk Measure Constraints: private API
PortfolioOptimisers.set_owa_constraints! — Function
set_owa_constraints!(
model::Model,
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}};
prefix
) -> Any
Set up the OWA portfolio returns variable and equality constraint.
Introduces a vector variable owa of length T and adds the equality constraint sc * (net_X - owa) == 0. Returns the existing owa if already present.
Arguments
model::JuMP.Model: The JuMP optimisation model.X::MatNum: Asset returns matrix (T × N).
Keyword arguments
prefix::Symbol: Model State namespace (default: empty, i.e. the bare key).
Returns
owa: JuMP vector variable of lengthTfor OWA portfolio returns.
Related
PortfolioOptimisers.set_risk_constraints! — Method
set_risk_constraints!(
model::Model,
i,
r::OrderedWeightsArray{<:Any, <:Any, <:ExactOrderedWeightsArray},
opt::RiskJuMPOptimisationEstimator,
pr::AbstractPriorResult,
args...;
prefix,
kwargs...
) -> Any
Add Ordered Weights Array (OWA) risk constraints to model using the exact formulation.
The exact formulation is the linear programme that is dual to the assignment problem which sorts the sample. It adds two T × 1 auxiliary variables and one T × T block of linear constraints, and the risk is the sum of the two auxiliary variables. The block costs $T^{2}$ constraints, so ApproxOrderedWeightsArray is the cheaper formulation for a long sample.
The programme pairs the largest weight with the largest sorted return, so it attains $\mathrm{sort}(\boldsymbol{\omega})^{\intercal} \mathrm{sort}(\hat{\boldsymbol{r}})$. This equals the OWA risk when, and only when, $\boldsymbol{\omega}$ is monotonic non-decreasing, which is also the condition for the risk measure to be convex. Every weight builder in this package returns such a vector.
Mathematical definition
\[\begin{align} \hat{r}_{t} &= \boldsymbol{x}_{t}^{\intercal} \boldsymbol{w}\\ \mathrm{OWA}(\boldsymbol{w}) &= \boldsymbol{\omega}^{\intercal} \mathrm{sort}\left(\hat{\boldsymbol{r}}\right)\\ &= \begin{cases} \underset{\boldsymbol{a},\, \boldsymbol{b}}{\min} & \sum\limits_{t=1}^{T} \left(a_{t} + b_{t}\right)\\ \text{s.t.} & \hat{r}_{i} \omega_{j} - a_{j} - b_{i} \leq 0 \quad \forall i,\, j = 1,\, \ldots,\, T\,. \end{cases} \end{align}\]
Where:
- $\mathrm{OWA}(\boldsymbol{w})$: Is the ordered weighted average risk of the portfolio.
- $\boldsymbol{\omega}$: Is the OWA weight vector,
r.wif it is a vector,r.w(T)if it is a callable. - $\hat{\boldsymbol{r}}$: Is the vector of net portfolio returns, which $\mathrm{sort}$ places in ascending order.
- $\boldsymbol{x}_{t}$: Is the
N × 1vector of asset returns at time $t$. - $\boldsymbol{w}$: Is the
N × 1vector of portfolio weights. - $\boldsymbol{a},\, \boldsymbol{b}$: Are the two
T × 1auxiliary variables of the assignment dual. - $T$: Is the total number of observations.
Arguments
model::JuMP.Model: The JuMP optimisation model.i: Constraint index for unique variable and constraint naming.r::OrderedWeightsArray{<:Any, <:Any, <:ExactOrderedWeightsArray}: The OWA risk measure with the exact formulation.opt::RiskJuMPOptimisationEstimator: Risk-based optimisation estimator.pr::AbstractPriorResult: Prior result containing the returns matrixX.
Keyword arguments
prefix::Symbol: Model State namespace (default: empty, i.e. the bare key).
Returns
owa_risk: The OWA risk expression added to the model.
Related
PortfolioOptimisers.set_risk_constraints! — Method
set_risk_constraints!(
model::Model,
i,
r::OrderedWeightsArrayRange{<:Any, <:Any, <:Any, <:ExactOrderedWeightsArray},
opt::RiskJuMPOptimisationEstimator,
pr::AbstractPriorResult,
args...;
prefix,
kwargs...
) -> Any
Add JuMP risk constraints for OrderedWeightsArrayRange using the exact OWA formulation to model.
The exact formulation fuses the two tails rather than duplicating them. It forms the single weight vector $\boldsymbol{\omega}_{1} - \boldsymbol{\omega}_{2}$ and builds one assignment dual over it, so the range costs the same T × T block as a single tail. r.w2 is already reversed by the constructor of OrderedWeightsArrayRange, so the difference is the range weight vector.
Mathematical definition
\[\begin{align} \hat{r}_{t} &= \boldsymbol{x}_{t}^{\intercal} \boldsymbol{w}\\ \boldsymbol{\omega} &= \boldsymbol{\omega}_{1} - \boldsymbol{\omega}_{2}\\ \mathrm{OWA}_{\mathrm{rg}}(\boldsymbol{w}) &= \boldsymbol{\omega}^{\intercal} \mathrm{sort}\left(\hat{\boldsymbol{r}}\right)\\ &= \begin{cases} \underset{\boldsymbol{a},\, \boldsymbol{b}}{\min} & \sum\limits_{t=1}^{T} \left(a_{t} + b_{t}\right)\\ \text{s.t.} & \hat{r}_{i} \omega_{j} - a_{j} - b_{i} \leq 0 \quad \forall i,\, j = 1,\, \ldots,\, T\,. \end{cases} \end{align}\]
Where:
- $\mathrm{OWA}_{\mathrm{rg}}(\boldsymbol{w})$: Is the ordered weighted average range risk of the portfolio.
- $\boldsymbol{\omega}_{1}$: Is the loss-tail OWA weight vector,
r.w1if it is a vector,r.w1(T)if it is a callable. - $\boldsymbol{\omega}_{2}$: Is the reversed gain-tail OWA weight vector,
r.w2if it is a vector,r.w2(T)if it is a callable. - $\hat{\boldsymbol{r}}$: Is the vector of net portfolio returns, which $\mathrm{sort}$ places in ascending order.
- $\boldsymbol{a},\, \boldsymbol{b}$: Are the two
T × 1auxiliary variables of the assignment dual. - $T$: Is the total number of observations.
Arguments
model::JuMP.Model: The JuMP optimisation model.i: Constraint index for unique variable and constraint naming.r::OrderedWeightsArrayRange{<:Any, <:Any, <:Any, <:ExactOrderedWeightsArray}: The OWA range risk measure with exact formulation.opt::RiskJuMPOptimisationEstimator: Risk-based optimisation estimator.pr::AbstractPriorResult: Prior result containing the returns matrixX.
Keyword arguments
prefix::Symbol: Model State namespace (default: empty, i.e. the bare key).
Returns
owa_range_risk: The OWA range risk expression added to the model.
Related
PortfolioOptimisers.set_risk_constraints! — Method
set_risk_constraints!(
model::Model,
i,
r::OrderedWeightsArray{<:Any, <:Any, <:ApproxOrderedWeightsArray},
opt::RiskJuMPOptimisationEstimator,
pr::AbstractPriorResult,
args...;
loss,
prefix,
kwargs...
) -> Any
Add JuMP risk constraints for OrderedWeightsArray using the approximate OWA formulation to model.
The exact formulation orders the sample with a T × T block of constraints. This one drops that block. It keeps only the properties of the OWA weight vector that any ordering leaves unchanged — the minimum, the maximum, the sum, and one p-norm for each entry of r.alg.p — and it writes each p-norm as a power cone. The cost falls to T × M variables, where M is the length of r.alg.p.
Every permutation of the weight vector satisfies those properties, so the feasible set is a superset of the exact one and the risk is an upper bound on the exact OWA risk. The gap closes as the weight vector approaches a line, which is the case the source paper studies: it reports the same objective value as the exact formulation, to its printed precision, for the Gini mean difference and the tail Gini over samples of 500 to 10,000 observations.
The gap was measured here against the functor at T = 100, N = 8 with the default p. The Gini mean difference is 0.06 % high, the tail Gini is 1.7e-5 % high, and the tail Gini range is 0.37 % high. A fourth-order L-moment weight vector, which is not linear, is 4.5 % high, so prefer ExactOrderedWeightsArray for a weight vector that is far from a line.
Mathematical definition
\[\begin{align} \hat{r}_{t} &= \boldsymbol{x}_{t}^{\intercal} \boldsymbol{w}\\ \mathrm{OWA}(\boldsymbol{w}) &\approx \begin{cases} \underset{t,\, \boldsymbol{\nu},\, \boldsymbol{\eta},\, \boldsymbol{\varepsilon},\, \boldsymbol{\psi},\, \boldsymbol{\zeta},\, \boldsymbol{y}}{\min} & c_{1} t - c_{2} \boldsymbol{1}^{\intercal} \boldsymbol{\nu} + c_{3} \boldsymbol{1}^{\intercal} \boldsymbol{\eta} + \sum\limits_{k \in S} d_{k} y_{k}\\ \text{s.t.} & \hat{\boldsymbol{r}} + t \boldsymbol{1} - \boldsymbol{\nu} + \boldsymbol{\eta} - \sum\limits_{k \in S} \boldsymbol{\varepsilon}_{k} = \boldsymbol{0}\\ & \zeta_{k} + y_{k} - \boldsymbol{1}^{\intercal} \boldsymbol{\psi}_{k} = 0 \quad \forall k \in S\\ & \left(-k \zeta_{k},\, \dfrac{k}{k-1} \psi_{k,\, t},\, \varepsilon_{k,\, t}\right) \in \mathcal{P}_{3}^{1/k,\, 1-1/k} \quad \forall k \in S,\, \forall t = 1,\, \ldots,\, T\\ & \boldsymbol{\nu},\, \boldsymbol{\eta},\, \boldsymbol{y} \geq \boldsymbol{0} \end{cases}\\ c_{1} &= \boldsymbol{1}^{\intercal} \left(-\boldsymbol{\omega}\right)\\ c_{2} &= \min\left(-\boldsymbol{\omega}\right)\\ c_{3} &= \max\left(-\boldsymbol{\omega}\right)\\ d_{k} &= \lVert -\boldsymbol{\omega} \rVert_{k} \quad \forall k \in S\\ \mathcal{P}_{3}^{\alpha,\, 1-\alpha} &\coloneqq \left\{\boldsymbol{u} \in \mathbb{R}^{3} : u_{1}^{\alpha} u_{2}^{1-\alpha} \geq \lvert u_{3} \rvert,\, u_{1},\, u_{2} \geq 0\right\}\,. \end{align}\]
Where:
- $\boldsymbol{\omega}$: Is the OWA weight vector,
r.wif it is a vector,r.w(T)if it is a callable. - $\hat{\boldsymbol{r}}$: Is the vector of net portfolio returns, negated when
lossisfalse. - $S$: Is the set of p-norm orders,
r.alg.p. - $t$: Is the scalar auxiliary variable,
owa_t. - $\boldsymbol{\nu},\, \boldsymbol{\eta}$: Are the
T × 1non-negative auxiliary variables,owa_nuandowa_eta. - $\boldsymbol{\varepsilon},\, \boldsymbol{\psi}$: Are the
T × Mauxiliary variables,owa_epsilonandowa_psi. - $\boldsymbol{\zeta},\, \boldsymbol{y}$: Are the
M × 1auxiliary variables,owa_zandowa_y. - $\mathcal{P}_{3}^{\alpha,\, 1-\alpha}$: Is the three-dimensional power cone.
- $T$: Is the total number of observations.
- $M$: Is the number of p-norm orders,
length(r.alg.p).
Arguments
model::JuMP.Model: The JuMP optimisation model.i: Constraint index for unique variable and constraint naming.r::OrderedWeightsArray{<:Any, <:Any, <:ApproxOrderedWeightsArray}: The OWA risk measure with approximate formulation.opt::RiskJuMPOptimisationEstimator: Risk-based optimisation estimator.pr::AbstractPriorResult: Prior result containing the returns matrixX.
Keyword arguments
loss::Bool: Iftrue(default), the measure is applied to the net portfolio returns; iffalse, to their negation. This is the seamset_range_risk_constraints!builds the gain tail ofOrderedWeightsArrayRangethrough.prefix::Symbol: Model State namespace (default: empty, i.e. the bare key).
Returns
aowa_risk: The OWA risk expression added to the model.
Related
PortfolioOptimisers.set_risk_constraints! — Method
set_risk_constraints!(
model::Model,
i,
r::OrderedWeightsArrayRange{<:Any, <:Any, <:Any, <:ApproxOrderedWeightsArray},
opt::RiskJuMPOptimisationEstimator,
pr::AbstractPriorResult,
args...;
prefix,
kwargs...
) -> Any
Add JuMP risk constraints for OrderedWeightsArrayRange using the approximate OWA formulation to model.
Delegates to set_range_risk_constraints!, which builds the loss tail from w1 on the net portfolio returns and the gain tail from w2 on their negation, then sums the two OWA expressions. Each tail brings its own power cone block.
Arguments
model::JuMP.Model: The JuMP optimisation model.i: Constraint index for unique variable and constraint naming.r::OrderedWeightsArrayRange{<:Any, <:Any, <:Any, <:ApproxOrderedWeightsArray}: The OWA range risk measure with approximate formulation.opt::RiskJuMPOptimisationEstimator: Risk-based optimisation estimator.pr::AbstractPriorResult: Prior result containing the returns matrixX.
Returns
aowa_range_risk: The combinedloss + gainrisk expression added to the model.
Related