ℓ1 Uncertainty Sets
PortfolioOptimisers.L1UncertaintySet — Type
struct L1UncertaintySet{__T_eps, __T_sd, __T_mu} <: AbstractUncertaintySetResult$\ell_1$ (cross-polytope) uncertainty set on the characteristic vector.
The set is $\mathcal{S} = \{\hat{\boldsymbol{\mu}} + \boldsymbol{e} : \lVert \boldsymbol{e} \oslash \boldsymbol{\sigma} \rVert_1 \leq \epsilon\}$, with a single error budget shared across every asset and both signs. Produced by CharacteristicUncertaintySet and consumed by ArithmeticReturn. It bounds a mean/characteristic vector alone, and has no covariance analogue.
Mathematical definition
The worst case of a linear characteristic over the set collapses to a scaled infinity norm (Lemmas 1 and 8 of [4]):
\[\underset{\boldsymbol{\mu} \in \mathcal{S}}{\min}\, \boldsymbol{\mu}^{\intercal} \boldsymbol{w} = \hat{\boldsymbol{\mu}}^{\intercal} \boldsymbol{w} - \epsilon \lVert \boldsymbol{\sigma} \odot \boldsymbol{w} \rVert_{\infty}\,.\]
Where:
- $\hat{\boldsymbol{\mu}}$: Estimated characteristic vector.
- $\epsilon$: Radius of the set.
- $\boldsymbol{\sigma}$: Per-asset scaling (
sd); $\boldsymbol{1}$ whensdisnothing. - $\odot$, $\oslash$: Element-wise product and division.
Because the right-hand side is concave and positively homogeneous, this is an LP once the infinity norm is epigraphed — no conic solver is needed.
Fields
eps: Radius of the $\ell_1$ uncertainty set on the characteristic vector. Larger values admit more estimation error, and therefore activate more assets.
sd: Per-asset scaling vector for the $\ell_1$ uncertainty set (the estimated standard deviations).nothingleaves the set unscaled, so every element of the characteristic vector is assumed to suffer the same estimation error.
mu: Characteristic vector the $\ell_1$ set is a neighbourhood of.nothingdefers to the consumer's own characteristic. When it is set, it takes precedence over the returns estimator's field and over the prior.
Constructors
L1UncertaintySet(; eps::Number, sd::Option{<:VecNum} = nothing, mu::Option{<:VecNum} = nothing) -> L1UncertaintySetKeywords correspond to the struct's fields.
Validation
isfinite(eps)andeps >= 0.- If
sdis provided:!isempty(sd)andall(sd .> 0). - If
muis provided:!isempty(mu)andall(isfinite, mu). - If both
sdandmuare provided:length(mu) == length(sd).
Examples
julia> L1UncertaintySet(; eps = 0.1)L1UncertaintySet eps ┼ Float64: 0.1 sd ┼ nothing mu ┴ nothingRelated
SignedL1UncertaintySetCharacteristicUncertaintySet: the estimator that fits this set. It is mean-only, sosigma_ucsis not defined for it.L1UncertaintySetAlgorithmAbstractUncertaintySetResultmu_ucs: a set it builds carries inmuthe characteristic vector its radius was calibrated on, so the consumer bounds that vector and not an unrelated one.port_opt_view
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.SignedL1UncertaintySet — Type
struct SignedL1UncertaintySet{__T_ep, __T_en, __T_sd, __T_mu} <: AbstractUncertaintySetResultSigned $\ell_1$ uncertainty set on the characteristic vector, with a separate error budget per sign.
The set is $\mathcal{A}_2 = \{\hat{\boldsymbol{\mu}} + \boldsymbol{e} : \boldsymbol{1}^{\intercal} [\boldsymbol{e} \oslash \boldsymbol{\sigma}]_{+} \leq \epsilon_{+},\, -\boldsymbol{1}^{\intercal} [\boldsymbol{e} \oslash \boldsymbol{\sigma}]_{-} \leq \epsilon_{-}\}$. It bounds a mean/characteristic vector alone, and has no covariance analogue. [4] introduces it in order to decouple the long-short problem into two independent problems (its equations 27 and 28), which its Remark 12 then recombines only when the two legs happen to have complementary support; modelling the worst case below directly keeps the problem coupled, so that caveat does not arise.
Mathematical definition
\[\underset{\boldsymbol{\mu} \in \mathcal{A}_2}{\min}\, \boldsymbol{\mu}^{\intercal} \boldsymbol{w} = \hat{\boldsymbol{\mu}}^{\intercal} \boldsymbol{w} - \epsilon_{+} \left[\underset{i}{\max}\, (-\sigma_i w_i)\right]_{+} - \epsilon_{-} \left[\underset{i}{\max}\, (\sigma_i w_i)\right]_{+}\,.\]
Where:
- $\epsilon_{+}$, $\epsilon_{-}$: Radii of the positive- and negative-error sides (
ep,en). - $[\cdot]_{+}$, $[\cdot]_{-}$: Element-wise positive and negative parts.
Still concave and LP-representable, with one epigraph variable per sign.
Setting $\epsilon_{+} = \epsilon_{-}$ does not recover $\mathcal{S}$: the joint set shares one budget across both signs, giving $\max(t_{+}, t_{-})$, whereas this one spends a budget per sign, giving $\epsilon_{+} t_{+} + \epsilon_{-} t_{-}$. The two worst cases agree only when $\boldsymbol{w}$ is single-signed.
Fields
ep: Radius of the positive-error side of the signed $\ell_1$ uncertainty set.
en: Radius of the negative-error side of the signed $\ell_1$ uncertainty set.
sd: Per-asset scaling vector for the $\ell_1$ uncertainty set (the estimated standard deviations).nothingleaves the set unscaled, so every element of the characteristic vector is assumed to suffer the same estimation error.
mu: Characteristic vector the $\ell_1$ set is a neighbourhood of.nothingdefers to the consumer's own characteristic. When it is set, it takes precedence over the returns estimator's field and over the prior.
Constructors
SignedL1UncertaintySet(; ep::Number, en::Number, sd::Option{<:VecNum} = nothing, mu::Option{<:VecNum} = nothing) -> SignedL1UncertaintySetKeywords correspond to the struct's fields.
Validation
isfinite(ep)andep >= 0.isfinite(en)anden >= 0.- If
sdis provided:!isempty(sd)andall(sd .> 0). - If
muis provided:!isempty(mu)andall(isfinite, mu). - If both
sdandmuare provided:length(mu) == length(sd).
Examples
julia> SignedL1UncertaintySet(; ep = 0.1, en = 0.2)SignedL1UncertaintySet ep ┼ Float64: 0.1 en ┼ Float64: 0.2 sd ┼ nothing mu ┴ nothingRelated
L1UncertaintySet: the joint set. Under a long-only budget the weights are single-signed, the two worst cases coincide, and the joint set is the simpler choice.SignedL1UncertaintySetAlgorithmCharacteristicUncertaintySet: the estimator that fits this set. It is mean-only, sosigma_ucsis not defined for it.mu_ucs: a set it builds carries inmuthe characteristic vector its radii were calibrated on, so the consumer bounds that vector and not an unrelated one.AbstractUncertaintySetResultport_opt_view
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.L1UncertaintySetAlgorithm — Type
struct L1UncertaintySetAlgorithm{__T_method, __T_scaled, __T_paired} <: AbstractUncertaintySetAlgorithmShape algorithm selecting a joint $\ell_1$ uncertainty set.
scaled picks between the two sets of [4]: false gives $\mathcal{S}$ (its equation 5) and true gives $\mathcal{A}_1$ (its equation 18). It defaults to false because $\mathcal{S}$ is the base construction of the paper, the one whose closed forms give the $1/N$ and quintile portfolios. SignedL1UncertaintySetAlgorithm defaults the other way, because the paper defines its set only in the scaled form.
Fields
method: Radius of the $\ell_1$ uncertainty set. A number is the radius itself; anAbstractUncertaintyEpsAlgorithmcomputes it from the data.
scaled: Whether to scale the uncertainty set by the estimated standard deviations.falseassumes every characteristic suffers the same estimation error;trueassumes assets with larger variance suffer larger estimation error, which yields inverse-volatility weights.
paired:paired: Which closed form calibrates the radius whenmethodis anAbstractUncertaintyEpsAlgorithm. The number of assets a radius activates depends on the sign structure of the problem it is used in, which an uncertainty set cannot observe, so the caller must say.falsetakes the long-only ladder, for a problem withw >= 0andbgt = 1(Corollaries 4 and 11 of [4]).truetakes the paired ladder, for a dollar-neutral problem withbgt = 0andsbgt = 1/2, where assets activate in long/short pairs (Corollary 7). Using the wrong one mis-calibrates the radius; it does not make the optimisation incorrect. Inert whenmethodis a number.
Constructors
L1UncertaintySetAlgorithm(; method::Num_UcSEps = ActiveAssetsUncertaintyAlgorithm(), scaled::Bool = false, paired::Bool = false) -> L1UncertaintySetAlgorithmKeywords correspond to the struct's fields.
Validation
- If
methodis aNumber:isfinite(method)andmethod >= 0.
Examples
julia> L1UncertaintySetAlgorithm()L1UncertaintySetAlgorithm method ┼ ActiveAssetsUncertaintyAlgorithm │ active ┴ Float64: 0.2 scaled ┼ Bool: false paired ┴ Bool: falseRelated
L1UncertaintySetSignedL1UncertaintySetAlgorithmActiveAssetsUncertaintyAlgorithmCharacteristicUncertaintySetAbstractUncertaintySetAlgorithml1_resolve_eps: the function that readsmethodandpairedand returns the radius.
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.SignedL1UncertaintySetAlgorithm — Type
struct SignedL1UncertaintySetAlgorithm{__T_mp, __T_mm, __T_scaled} <: AbstractUncertaintySetAlgorithmShape algorithm selecting a signed $\ell_1$ uncertainty set.
The two ladders are fixed by the construction of [4] and need no paired flag: $\epsilon_{-}$ governs the long leg and is calibrated against the top of the ranking, $\epsilon_{+}$ governs the short leg and is calibrated against the bottom (its Corollary 13). scaled defaults to true because the paper defines $\mathcal{A}_2$ only in the volatility-scaled form, and states Corollary 13 in that form alone. L1UncertaintySetAlgorithm defaults the other way, because its base set carries no scaling.
Fields
mp: Radius of the positive-error side. A number is the radius itself; anAbstractUncertaintyEpsAlgorithmcomputes it from the data.
mm: Radius of the negative-error side. A number is the radius itself; anAbstractUncertaintyEpsAlgorithmcomputes it from the data.
scaled: Whether to scale the uncertainty set by the estimated standard deviations.falseassumes every characteristic suffers the same estimation error;trueassumes assets with larger variance suffer larger estimation error, which yields inverse-volatility weights.
Constructors
SignedL1UncertaintySetAlgorithm(; mp::Num_UcSEps = ActiveAssetsUncertaintyAlgorithm(), mm::Num_UcSEps = ActiveAssetsUncertaintyAlgorithm(), scaled::Bool = true) -> SignedL1UncertaintySetAlgorithmKeywords correspond to the struct's fields.
Validation
- If
mp/mmis aNumber:isfiniteand>= 0.
Examples
julia> SignedL1UncertaintySetAlgorithm()SignedL1UncertaintySetAlgorithm mp ┼ ActiveAssetsUncertaintyAlgorithm │ active ┴ Float64: 0.2 mm ┼ ActiveAssetsUncertaintyAlgorithm │ active ┴ Float64: 0.2 scaled ┴ Bool: trueRelated
SignedL1UncertaintySetL1UncertaintySetAlgorithmActiveAssetsUncertaintyAlgorithmCharacteristicUncertaintySetAbstractUncertaintySetAlgorithml1_resolve_eps: the function that readsmpandmmand returns each radius.
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.CharacteristicUncertaintySet — Type
struct CharacteristicUncertaintySet{__T_pe, __T_alg} <: AbstractUncertaintySetEstimatorFits an $\ell_1$ uncertainty set on the characteristic vector, mean-only and with a calibrated radius.
pe supplies both the characteristic vector $\hat{\boldsymbol{\mu}}$ and, when the shape algorithm is scaled, the per-asset scaling $\hat{\boldsymbol{\sigma}} = \sqrt{\mathrm{diag}(\hat{\mathbf{\Sigma}})}$. The sets are the robust best-characteristic sets of [4]. Maximising the worst-case characteristic over one of them recovers the heuristic $1/N$, quintile, and inverse-volatility portfolios as exact solutions of a robust optimisation problem, with the radius controlling how many assets are held — which is why this library ships no dedicated quintile optimiser. Compose the set with MeanRisk instead:
MeanRisk(; r = NoRisk(), obj = MaximumReturn(), opt = JuMPOptimiser(; slv = slv, bgt = 1.0, ret = ArithmeticReturn(; ucs = CharacteristicUncertaintySet())))Fields
pe: Prior estimator the set fits on the returns it is handed, ornothing. Withnothingthe set holds no prior of its own and is calibrated on the prior result it is handed — inside an optimiser, the prior the optimiser is solving on, so its centre is the objective's own — through the prior-result arm of the ucs triple; the returns-data form then refuses by name. The default,EmpiricalPrior(), fits an empirical prior on the returns.
alg:alg: Shape algorithm —L1UncertaintySetAlgorithmorSignedL1UncertaintySetAlgorithm.
Constructors
CharacteristicUncertaintySet(; pe::Option{<:AbstractLowOrderPriorEstimator} = EmpiricalPrior(), alg::AbstractUncertaintySetAlgorithm = L1UncertaintySetAlgorithm()) -> CharacteristicUncertaintySetKeywords correspond to the struct's fields.
Validation
algmust be anL1UncertaintySetAlgorithmor aSignedL1UncertaintySetAlgorithm.ucsandsigma_ucsalways throw anArgumentErroron this estimator. The $\ell_1$ ball bounds a characteristic vector, [4] defines no covariance analogue, and there is therefore no covariance set for either to return.
Examples
The radius is calibrated, not given. Three assets whose sample means are $0.125$, $0.0625$ and $0.03125$ give the activation ladder $[0, 0.0625, 0.125]$, and the default active of 0.2 targets one active asset, so the radius is the midpoint of the first rung and the second:
julia> X = [0.1875 0.09375 0.0625 0.0625 0.03125 0.0];julia> mu_ucs(CharacteristicUncertaintySet(), X)L1UncertaintySet eps ┼ Float64: 0.03125 sd ┼ nothing mu ┴ Vector{Float64}: [0.125, 0.0625, 0.03125]Related
L1UncertaintySetSignedL1UncertaintySetL1UncertaintySetAlgorithmSignedL1UncertaintySetAlgorithmActiveAssetsUncertaintyAlgorithmmu_ucs: the only fitting verb this estimator answers.StandardDeviationExpectedReturns: the characteristic need not be an expected return. A prior built on this estimator ranks on volatility, the Low Volatility factor, and reproduces Table III of [4].AbstractUncertaintySetEstimator
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.ActiveAssetsUncertaintyAlgorithm — Type
struct ActiveAssetsUncertaintyAlgorithm{__T_active} <: AbstractUncertaintyEpsAlgorithmCalibrates the $\ell_1$ uncertainty radius to a target number of active assets.
The radius $\epsilon$ of an $\ell_1$ uncertainty set has no natural scale — it is a sum of characteristic differences, so on daily returns it is of order $10^{-3}$, and on annualised returns roughly $250$ times larger. This algorithm converts the quantity a caller can reason about (how many assets should the portfolio hold?) into the radius that produces it, by inverting the closed forms of [4]. The inversion is exact, and only for the bare problem those closed forms assume: the budget and sign constraints, and nothing else.
Fields
active: Target number of active assets on the unconstrained problem, as a count (integer>= 1) or a fraction of the universe (float in(0, 1)). This is a radius calibration, not a cardinality constraint: it selects the radius that would activate this many assets subject only to the budget and sign constraints. Any further constraint may change the realised count. Usecardfor a hard cardinality constraint.
Constructors
ActiveAssetsUncertaintyAlgorithm(; active::Union{<:Integer, <:AbstractFloat} = 0.2) -> ActiveAssetsUncertaintyAlgorithmKeywords correspond to the struct's fields.
Validation
- If
activeis anInteger:active >= 1. - If
activeis anAbstractFloat:0 < active < 1.
The type of active decides which rule applies, so the boundary is sharp: active = 1 is a count of one asset and is accepted, while active = 1.0 is the whole universe as a fraction and is rejected.
Examples
julia> ActiveAssetsUncertaintyAlgorithm()ActiveAssetsUncertaintyAlgorithm active ┴ Float64: 0.2Related
AbstractUncertaintyEpsAlgorithmL1UncertaintySetAlgorithmSignedL1UncertaintySetAlgorithmCharacteristicUncertaintySetl1_resolve_eps: the function that reads this algorithm and returns the radius.JuMPOptimiser: itscardfield bounds the number of holdings outright. Adding weight bounds, cardinality or linear constraints may move the realised count away from the one calibrated here, and this algorithm neither knows nor checks.
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.port_opt_view — Method
port_opt_view(
risk_ucs::L1UncertaintySet,
i,
args...
) -> L1UncertaintySet
Return a view of an L1UncertaintySet restricted to the asset indices i.
The radius is a scalar budget shared across the universe, so it passes through unchanged; the per-asset scaling and the carried characteristic are sliced. The slice preserves the order of i, so the restricted set indexes the assets in the order the optimiser hands it.
Algorithm
- Take
nothing_scalar_array_view(risk_ucs.sd, i), the per-asset scaling restricted to the selected assets, which passes anothingthrough unchanged. - Take
nothing_scalar_array_view(risk_ucs.mu, i), the carried characteristic restricted to the same assets, which passes anothingthrough unchanged. - Build an
L1UncertaintySetfromrisk_ucs.epsand the two views. The radius is not rescaled, because it budgets the total error across whichever assets the set covers.
Arguments
risk_ucs: $\ell_1$ uncertainty set.i: Cluster or asset index.args...: Additional positional arguments (ignored).
Returns
risk_ucs::L1UncertaintySet: The set restricted toi.
Examples
julia> ucs = L1UncertaintySet(; eps = 0.5, sd = [0.1, 0.2, 0.3], mu = [0.05, 0.03, 0.01]);julia> PortfolioOptimisers.port_opt_view(ucs, [1, 3])L1UncertaintySet eps ┼ Float64: 0.5 sd ┼ SubArray{Float64, 1, Vector{Float64}, Tuple{Vector{Int64}}, false}: [0.1, 0.3] mu ┴ SubArray{Float64, 1, Vector{Float64}, Tuple{Vector{Int64}}, false}: [0.05, 0.01]Related
PortfolioOptimisers.port_opt_view — Method
port_opt_view(
risk_ucs::SignedL1UncertaintySet,
i,
args...
) -> SignedL1UncertaintySet
Return a view of a SignedL1UncertaintySet restricted to the asset indices i.
Both radii are scalar budgets shared across the universe, so they pass through unchanged; the per-asset scaling and the carried characteristic are sliced. The slice preserves the order of i, so the restricted set indexes the assets in the order the optimiser hands it.
Algorithm
- Take
nothing_scalar_array_view(risk_ucs.sd, i), the per-asset scaling restricted to the selected assets, which passes anothingthrough unchanged. - Take
nothing_scalar_array_view(risk_ucs.mu, i), the carried characteristic restricted to the same assets, which passes anothingthrough unchanged. - Build a
SignedL1UncertaintySetfromrisk_ucs.ep,risk_ucs.enand the two views. Neither radius is rescaled, because each budgets the total error of its own sign across whichever assets the set covers.
Arguments
risk_ucs: Signed $\ell_1$ uncertainty set.i: Cluster or asset index.args...: Additional positional arguments (ignored).
Returns
risk_ucs::SignedL1UncertaintySet: The set restricted toi.
Examples
julia> ucs = SignedL1UncertaintySet(; ep = 0.4, en = 0.6, sd = [0.1, 0.2, 0.3], mu = [0.05, 0.03, 0.01]);julia> PortfolioOptimisers.port_opt_view(ucs, [1, 3])SignedL1UncertaintySet ep ┼ Float64: 0.4 en ┼ Float64: 0.6 sd ┼ SubArray{Float64, 1, Vector{Float64}, Tuple{Vector{Int64}}, false}: [0.1, 0.3] mu ┴ SubArray{Float64, 1, Vector{Float64}, Tuple{Vector{Int64}}, false}: [0.05, 0.01]Related
PortfolioOptimisers.mu_ucs — Function
mu_ucs(ue::CharacteristicUncertaintySet, X::MatNum,
F::Option{<:MatNum} = nothing; dims::Int = 1, kwargs...)
mu_ucs(ue::CharacteristicUncertaintySet{Nothing}, pr::AbstractPriorResult; rd = nothing, kwargs...)Construct an $\ell_1$ uncertainty set on the characteristic vector, from the set's own prior fitted on returns data or from a prior result the set is handed.
The two signatures are the two routes a set with a pe field takes and share one tail. The returns-data method fits ue.pe once through ucs_prior, which refuses a pe of nothing by name, and hands the result to the prior-result method of the same set with its pe set to nothing, which is where the two shapes are dispatched. The prior-result method is defined only for a set whose pe is nothing: inside an optimiser pr is the prior the optimiser is solving on, so the characteristic vector the radius is calibrated on is the objective's own mu.
The calibration runs on the ranking, and the set is returned in the universe's own order: mu and sd carry one entry per asset in the order the prior produced them, which is the order the optimiser indexes and the order port_opt_view slices. Only the ladders see the sorted vector, and a ladder needs no asset identity. The set carries $\hat{\boldsymbol{\mu}}$ in its mu field, so the consumer bounds the characteristic vector the radius was calibrated on.
Algorithm
The returns-data method runs step 1 and forwards; the two prior-result methods share steps 2 to 4 and differ in the fifth.
- Fit the prior with
ucs_prioronue.pe,XandF, givingpr, and forward to the prior-result method of the set withpe = nothing. - Read
alg = ue.alg, the shape algorithm. - When
alg.scaled, takesd = sqrt.(diag(pr.sigma)), the per-asset scaling; otherwise takenothing. - Take
idx = sortperm(pr.mu; rev = true), the ranking that sorts the characteristic non-increasing, and apply it topr.muand tosd. - Resolve the radii with
l1_resolve_epsagainst the sorted vectors, and build the set from them withmu = pr.muandsdin the universe's order.
For an L1UncertaintySetAlgorithm step 5 resolves the single radius eps from alg.method, passing alg.paired, and builds an L1UncertaintySet.
For a SignedL1UncertaintySetAlgorithm step 5 resolves two radii against two ladders and builds a SignedL1UncertaintySet. en comes from alg.mm on the sorted ranking, and ep from alg.mp on the reversed, negated ranking, which is the same ladder read from the other end (Corollary 13 of [4]). Neither call passes paired, because the construction fixes both ladders. The consumer spends en against $\max_i (\sigma_i w_i)$ and ep against $\max_i (-\sigma_i w_i)$, so en prices the long leg and ep the short one, matching the end each was calibrated against.
Arguments
ue: Characteristic uncertainty set estimator.X: Data matrix (e.g. returns).F: Optional factor matrix. Used by the prior estimator.dims: Dimension along which to perform the computation.pr: Fitted prior result the set is calibrated on.pr.muis read, andpr.sigmawhenalg.scaled.rd: Returns result the three-argument form passes beside the prior. Not read.kwargs...: Additional keyword arguments passed to the prior estimator.
Returns
mu_ucs::Union{<:L1UncertaintySet, <:SignedL1UncertaintySet}: The uncertainty set.
Examples
julia> X = [0.1875 0.09375 0.0625 0.0625 0.03125 0.0];julia> alg = SignedL1UncertaintySetAlgorithm(; scaled = false);julia> mu_ucs(CharacteristicUncertaintySet(; alg = alg), X)SignedL1UncertaintySet ep ┼ Float64: 0.015625 en ┼ Float64: 0.03125 sd ┼ nothing mu ┴ Vector{Float64}: [0.125, 0.0625, 0.03125]Related
CharacteristicUncertaintySetL1UncertaintySetSignedL1UncertaintySetl1_resolve_epsucs_priorport_opt_view
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.ucs — Function
ucs(ue::CharacteristicUncertaintySet, X::MatNum, F::Option{<:MatNum} = nothing; kwargs...)
sigma_ucs(ue::CharacteristicUncertaintySet, X::MatNum, F::Option{<:MatNum} = nothing; kwargs...)
ucs(ue::CharacteristicUncertaintySet{Nothing}, pr::AbstractPriorResult; kwargs...)
sigma_ucs(ue::CharacteristicUncertaintySet{Nothing}, pr::AbstractPriorResult; kwargs...)Always throw. CharacteristicUncertaintySet is mean-only.
All four methods are refusals rather than procedures, so none carries an # Algorithm section. The returns-data pair takes the same (X, F) signature as the rest of the family rather than a catch-all, so that the ReturnsResult forwarders in the base reach them without ambiguity, and the prior-result pair takes the signature the family's prior-result arm shares, so that the three-argument routing of a set with no prior of its own reaches the same refusal.
Arguments
ue: Characteristic uncertainty set estimator.X: Data matrix (e.g. returns).F: Optional factor matrix.pr: Fitted prior result (ignored).kwargs...: Additional keyword arguments (ignored).
Validation
- Both methods always throw an
ArgumentError. The $\ell_1$ set bounds a characteristic (mean) vector, [4] defines no covariance analogue, and there is therefore no covariance set to return. Each message names the fix:mu_ucsfor the mean set, andNormalUncertaintySet,DeltaUncertaintySetorARCHUncertaintySetfor a covariance set.
Returns
- Neither method returns. Both throw.
Related
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
PortfolioOptimisers.l1_resolve_eps — Function
l1_resolve_eps(method, mus::VecNum, sds::Option{<:VecNum}, paired::Bool)Resolve a radius from a Num_UcSEps against the characteristic vector.
mus must be sorted in non-increasing order, with sds under the same permutation. The method that takes a Number is a passthrough: it returns the radius the caller gave, runs no procedure, and carries neither an # Algorithm nor a # Validation section. The method that takes an ActiveAssetsUncertaintyAlgorithm calibrates against the long-only ladder when paired is false, and against the paired ladder when it is true.
Mathematical definition
The paired ladder adds the ladder of the ranking to the ladder of the reversed, negated ranking, which is Lemma 6 of [4]:
\[\begin{align} F_m &= \sum_{i=1}^{m} \frac{\hat{\mu}_i - \hat{\mu}_m}{\sigma_i} + \sum_{j=1}^{m} \frac{\hat{\mu}_{N-m+1} - \hat{\mu}_{N-j+1}}{\sigma_{N-j+1}}\,, \quad m = 1,\, \ldots,\, \left\lfloor N/2 \right\rfloor\,. \end{align}\]
Where:
- $F_m$: Activation threshold of the $m$-th long/short pair.
- $\hat{\mu}_i$: $i$-th entry of the characteristic vector, sorted non-increasing.
- $\sigma_i$: Per-asset scaling of the $i$-th entry of the characteristic vector; $1$ when the set is unscaled.
- $N$: Number of assets.
A radius in $(F_q,\, F_{q+1})$ makes the top $q$ assets long and the bottom $q$ short, so it activates $2q$ assets (Corollary 7). Lemma 5 gives the reason the ladder stops at $\lfloor N/2 \rfloor$: an optimal dollar-neutral solution satisfies $w_i = -w_{N+1-i}$, so with an odd $N$ the middle asset pairs with itself, its weight solves $w = -w$, and it is never active. The largest count the paired branch can reach is therefore $2 \lfloor N/2 \rfloor$, which is $N-1$ when $N$ is odd.
Algorithm
- Read
N = length(mus), the size of the universe. - When
pairedisfalse, build the long-only ladder withl1_activation_ladder, convertmethod.activeto a count withl1_active_count, and return the radiusl1_eps_from_ladderresolves against them. - Otherwise read
half = N ÷ 2, the number of pairs the universe admits. - Add the ladder of
musto the ladder of the reversed, negated ranking and keep the firsthalfentries, givingladder, the paired ladder. - Halve the target: an
Integeractivecounts assets and givesmax(active ÷ 2, 1)pairs; anAbstractFloatactiveis a fraction of the universe and givesclamp(round(Int, active * N / 2), 1, half)pairs. Both name pairs, so a count and the matching fraction agree whenever the count is even. An odd count truncates while the matching fraction rounds to nearest, so the two can differ by one pair:active = 7gives three pairs andactive = 7/Ngives four. - Return the radius
l1_eps_from_ladderresolves againstladderand the pair count.
Arguments
method: A radius (Number) or anActiveAssetsUncertaintyAlgorithm.mus: Characteristic vector, sorted in non-increasing order.sds: Per-asset scaling under the same permutation, ornothing.paired: Whether to calibrate against the paired ladder rather than the long-only one.
Validation
N ÷ 2 >= 1whenpairedistrue, otherwise anArgumentErroris thrown. A single asset admits no long/short pair, so no paired ladder exists to calibrate against.
Returns
eps::Number: The resolved radius.
Examples
julia> PortfolioOptimisers.l1_resolve_eps(0.25)0.25julia> alg = ActiveAssetsUncertaintyAlgorithm(; active = 2);julia> mus = [0.125, 0.0625, 0.03125, 0.0];julia> PortfolioOptimisers.l1_resolve_eps(alg, mus, nothing, false)0.09375julia> PortfolioOptimisers.l1_resolve_eps(alg, mus, nothing, true)0.046875Related
l1_activation_ladderl1_active_countl1_eps_from_ladderL1UncertaintySetAlgorithmSignedL1UncertaintySetAlgorithm
References
- [4] R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).
References
- [4]
- R. Zhou and D. P. Palomar. Understanding the Quintile Portfolio. IEEE Transactions on Signal Processing 68, 4030–4040 (2020).