Entropy Pooling (b): private API

PortfolioOptimisers.ep_view_terms — Function
ep_view_terms(res::ParsingResult, sets::UniverseSets, X::MatNum; strict::Bool = false)

Resolve one parsed tail view into the assets it names, their coefficients, its operator and its target.

ep_view_terms routes a ParsingResult through get_linear_constraints, which resolves the variable names against the universe and reports the ones it cannot place, then undoes the sign flip that entry point applies to a >= equation so the operator survives. The linear view machinery never needs the operator back, because a row of A x <= b carries it; a tail view does, because each operator picks a different formulation.

Algorithm

  1. Resolve the view against the universe with get_linear_constraints, giving lc. Return nothing where it places no name of the view.
  2. Read the sign sgn and the inequality flag of the view's operator with comparison_sign_ineq_flag, and pick from them the operator op the view carries and the block blk it landed in.
  3. Scale the row A and the target rhs by sgn, which undoes the flip get_linear_constraints applies to a >= equation.
  4. Return the indices of the non-zero entries of A, the coefficients at those indices, op and rhs.

Arguments

  • res: Parsed view constraint.
  • sets: Asset set mapping asset names to indices.
  • X: Asset returns matrix, read for its element type.
  • strict: If true, throws error for missing assets; otherwise, issue warnings.

Returns

  • nothing: If no name in the view could be placed in the universe.
  • terms::@NamedTuple{idx::VecInt, coef::VecNum, op::Symbol, rhs::Number}: The assets the view names, their coefficients, its operator (:eq, :geq or :leq) and its target.

Related

source
PortfolioOptimisers.ep_normalise_view_term — Function
ep_normalise_view_term(coef::Number, op::Symbol, rhs::Number)

Divide a single-asset tail view by its coefficient.

Returns the operator and target of the equivalent view whose coefficient is one, flipping the operator when the coefficient is negative.

Algorithm

  1. Divide the target by the coefficient, giving rhs.
  2. Where the coefficient is negative, exchange :geq and :leq, giving op. An equality is unchanged, because dividing both sides by a negative number preserves it.

Arguments

  • coef: Coefficient the view gives the asset's risk measure.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.

Returns

  • op::Symbol: Operator of the normalised view.
  • rhs::Number: Target of the normalised view.

Related

source
PortfolioOptimisers.ep_view_formulations — Function
ep_view_formulations(alg, N::Integer, key::Symbol)

Spread the tail view formulation setting of an entropy pooling prior over its views.

A single formulation applies to every view, a vector supplies one per view, and nothing leaves the choice to the view.

Arguments

  • alg: Formulation setting.
  • N: Number of views.
  • key: Field name, used in the error message.

Validation

  • If alg is a vector, length(alg) == N.

Returns

  • algs::AbstractVector: One entry per view.

Related

source
PortfolioOptimisers.ep_sbar — Function
ep_sbar(sbar, T::Integer, alpha::Number, w::VecNum, ord::VecInt)

Resolve the number of largest losses the integer conditional value-at-risk formulation considers.

Algorithm

  1. An Integer sbar is a count. Return it, capped at T.
  2. Any other number is a fraction of T. Return ceil(Int, sbar * T), never below one and capped at T.
  3. nothing takes the rule of thumb of [1]. Walk the losses from the largest down, accumulating the prior probabilities, and stop at the position s at which they first reach alpha.
  4. Return twice s, never below ceil(Int, 2 * alpha * T), never below one and capped at T. A view above the prior CVaR moves mass into the tail and needs about the position s; a view below it moves mass out and needs more.

Arguments

  • sbar: Setting held by IntegerConditionalValueatRiskView. An Integer is a count, a fraction in (0, 1) is a fraction of T, and nothing applies the rule of thumb of [1].
  • T: Number of observations.
  • alpha: Significance level of the view.
  • w: Prior probability weights.
  • ord: Indices of the losses in ascending order, so the largest loss is last.

Returns

  • sbar::Int: Number of largest losses, in 1:T.

Related

References

  • [1] D. Cajas. Entropy Pooling with CVaR and EVaR Views. Available at SSRN 7120258 (2026).
source
PortfolioOptimisers.ep_assert_reachable_view — Function
ep_assert_reachable_view(op::Symbol, rhs::Number, x::AbstractVector{<:VecNum},
                         coef::VecNum, w::VecNum, eqn::AbstractString,
                         name::AbstractString)

Reject a tail view no reweighting of the sample can reach.

A tail risk measure of a reweighted sample lies between the smallest and the largest loss the sample holds where the prior probability is positive, so a coefficient-weighted sum of measures lies between the sums of those bounds, and a view outside that band is infeasible however the probabilities move. The band is exact for one asset, and an outer bound for several: a reweighting that puts every asset at its worst loss at once need not exist. The posterior of entropy pooling puts no mass where the prior puts none, so an observation of zero prior probability widens nothing.

Algorithm

  1. Read hi, the sum over the assets of the coefficient times the largest loss where the coefficient is positive, and times the smallest loss where it is negative, over the observations with w > 0. Read lo the other way round.
  2. Where op asks the statistic to reach or exceed rhs, raise unless rhs sits below hi.
  3. Where op asks the statistic to reach or fall below rhs, raise unless rhs sits above lo.

Arguments

  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • x: Per asset the view names, its loss series.
  • coef: Per asset, the coefficient the view gives its risk measure.
  • w: Prior probability weights.
  • eqn: Equation of the view, used in the error message.
  • name: Name of the view family, used in the error message.

Validation

  • If op is :geq or :eq, rhs < hi.
  • If op is :leq or :eq, rhs > lo.

Returns

  • nothing.

Related

source
PortfolioOptimisers.ep_cvar_formulation — Function
ep_cvar_formulation(alg::Option{<:AbstractConditionalValueatRiskViewFormulation},
                    mixed::Bool, op::Symbol, rhs::Number, pv::Number)

Pick the formulation of one conditional value-at-risk view.

A stated formulation is returned unchanged. nothing takes LinearConditionalValueatRiskView wherever it expresses the view exactly, which is every view whose lower level set is convex, and IntegerConditionalValueatRiskView otherwise: a view whose coefficients carry both signs, an upper bound, and an equality below the prior value of the left hand side.

The branch each input takes:

algmixedoprhs against pvBranch
statedanyanyanyalg, unchanged
nothingfalse:geqanyLinearConditionalValueatRiskView
nothingfalse:eqrhs >= pvLinearConditionalValueatRiskView
nothingfalse:eqrhs < pvIntegerConditionalValueatRiskView
nothingfalse:leqanyIntegerConditionalValueatRiskView
nothingtrueanyanyIntegerConditionalValueatRiskView

SequentialConditionalValueatRiskView is never the default. It writes every view the integer formulation does with no integer variable, but its posterior is a local minimiser of the divergence, and nothing stands for the exact formulation.

Arguments

  • alg: Stated formulation, or nothing.
  • mixed: Whether the coefficients of the view carry both signs.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • pv: Prior value of the view's left hand side.

Returns

  • alg::AbstractConditionalValueatRiskViewFormulation: The formulation to use.

Related

source
PortfolioOptimisers.ep_evar_formulation — Function
ep_evar_formulation(alg::Option{<:AbstractEntropicValueatRiskViewFormulation}, mixed::Bool,
                    single::Bool, op::Symbol, rhs::Number, pv::Number)

Pick the formulation of one entropic value-at-risk view.

A stated formulation is returned unchanged. nothing takes ConicEntropicValueatRiskView wherever it expresses the view exactly, which is every view whose lower level set is convex. An upper bound and an equality below the prior value take GridEntropicValueatRiskView when the view names one asset. The grid is one asset's, so the same views over several assets take SequentialEntropicValueatRiskView, the one formulation that expresses them. So does a view whose coefficients carry both signs.

The branch each input takes:

algmixedsingleoprhs against pvBranch
statedanyanyanyanyalg, unchanged
nothingfalseany:geqanyConicEntropicValueatRiskView
nothingfalseany:eqrhs >= pvConicEntropicValueatRiskView
nothingfalsetrue:eqrhs < pvGridEntropicValueatRiskView
nothingfalsetrue:leqanyGridEntropicValueatRiskView
nothingfalsefalse:eqrhs < pvSequentialEntropicValueatRiskView
nothingfalsefalse:leqanySequentialEntropicValueatRiskView
nothingtruefalseanyanySequentialEntropicValueatRiskView

Arguments

  • alg: Stated formulation, or nothing.
  • mixed: Whether the coefficients of the view carry both signs.
  • single: Whether the view names one asset.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • pv: Prior value of the view's left hand side.

Returns

  • alg::AbstractEntropicValueatRiskViewFormulation: The formulation to use.

Related

source
PortfolioOptimisers.ep_rlvar_formulation — Function
ep_rlvar_formulation(alg::Option{<:AbstractRelativisticValueatRiskViewFormulation},
                     mixed::Bool, single::Bool, op::Symbol, rhs::Number, pv::Number)

Pick the formulation of one relativistic value-at-risk view.

A stated formulation is returned unchanged. nothing takes ConicRelativisticValueatRiskView wherever it expresses the view exactly, which is every view whose lower level set is convex. An upper bound and an equality below the prior value take GridRelativisticValueatRiskView when the view names one asset. The grid is one asset's, so the same views over several assets take SequentialRelativisticValueatRiskView, the one formulation that expresses them. So does a view whose coefficients carry both signs.

The branch each input takes:

algmixedsingleoprhs against pvBranch
statedanyanyanyanyalg, unchanged
nothingfalseany:geqanyConicRelativisticValueatRiskView
nothingfalseany:eqrhs >= pvConicRelativisticValueatRiskView
nothingfalsetrue:eqrhs < pvGridRelativisticValueatRiskView
nothingfalsetrue:leqanyGridRelativisticValueatRiskView
nothingfalsefalse:eqrhs < pvSequentialRelativisticValueatRiskView
nothingfalsefalse:leqanySequentialRelativisticValueatRiskView
nothingtruefalseanyanySequentialRelativisticValueatRiskView

Arguments

  • alg: Stated formulation, or nothing.
  • mixed: Whether the coefficients of the view carry both signs.
  • single: Whether the view names one asset.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • pv: Prior value of the view's left hand side.

Returns

  • alg::AbstractRelativisticValueatRiskViewFormulation: The formulation to use.

Related

source
PortfolioOptimisers.ep_sequential_sides — Function
ep_sequential_sides(x::AbstractVector{<:VecNum}, coef::VecNum, op::Symbol, rhs::Number,
                    pv::Number)

Orient a tail view as a lower bound, and split its assets into the dual side and the primal side of a sequential formulation.

Algorithm

  1. Orient the view. An upper bound, and an equality whose target sits at or below the prior value of the left hand side, are negated on both sides, so the view reads >=. A lower bound, and an equality the prior sits below, are kept. An equality is therefore written as the bound the prior violates, which the entropy minimiser makes tight.
  2. Put every asset whose oriented coefficient is positive on the dual side, whose measure is concave in the probabilities and takes its exact dual block. Put every other asset on the primal side, whose measure takes a linear upper bound.

Arguments

  • x: Per asset the view names, its loss series.
  • coef: Per asset, the coefficient the view gives its risk measure.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • pv: Prior value of the view's left hand side.

Returns

  • xd::AbstractVector{<:VecNum}: Loss series of the assets on the dual side.
  • cd::VecNum: Their oriented coefficients, positive.
  • xp::AbstractVector{<:VecNum}: Loss series of the assets on the primal side.
  • cp::VecNum: Their oriented coefficients, negative.
  • rhs::Number: Target of the oriented view.

Related

source
PortfolioOptimisers.ep_add_cvar_view! — Function
ep_add_cvar_view!(tvs::AbstractVector, alg::AbstractConditionalValueatRiskViewFormulation,
                  x::AbstractVector{<:VecNum}, coef::VecNum, op::Symbol, rhs::Number,
                  alpha::Number, w::VecNum, pv::Number, eqn::AbstractString)

Lower one conditional value-at-risk view into the tail view constraint its formulation needs.

Algorithm

  1. LinearConditionalValueatRiskView checks the three preconditions below, then appends one LinearConditionalValueatRiskViewConstraint carrying x, coef, alpha and rhs.
  2. IntegerConditionalValueatRiskView sorts the loss series of each asset the view names, giving the ascending order o, and resolves the length sb of that asset's tail window with ep_sbar.
  3. It keeps the last sb positions of o as ord[k], and the losses at those positions as xw[k].
  4. It appends one IntegerConditionalValueatRiskViewConstraint carrying those windows, coef, alpha, op and rhs.
  5. SequentialConditionalValueatRiskView orients the view and splits its assets with ep_sequential_sides, builds a SequentialConditionalValueatRiskViewConstraint with an empty surrogate row, reads its first row from the prior w with ep_sequential_start, and appends it.

Arguments

  • tvs: Tail view constraints, appended to.
  • alg: Formulation of the view.
  • x: Per asset the view names, its loss series.
  • coef: Per asset, the coefficient the view gives its CVaR.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • alpha: Significance level of the view.
  • w: Prior probability weights.
  • pv: Prior value of the view's left hand side.
  • eqn: Equation of the view, used in the error messages.

Validation

  • LinearConditionalValueatRiskView needs coefficients of one sign, an operator other than <=, and, for an equality, a target at or above the prior value of the left hand side.

Returns

  • nothing: The function mutates tvs in-place.

Related

source
PortfolioOptimisers.ep_add_evar_view! — Function
ep_add_evar_view!(epc::AbstractDict, tvs::AbstractVector,
                  alg::AbstractEntropicValueatRiskViewFormulation,
                  x::AbstractVector{<:VecNum}, coef::VecNum, alpha::Number, op::Symbol,
                  rhs::Number, w::VecNum, zstar::VecNum, pv::Number, eqn::AbstractString;
                  args::Tuple = (), kwargs::NamedTuple = (;),
                  zlo_frac::Option{<:Number} = nothing)

Lower one entropic value-at-risk view into the constraints its formulation needs.

ConicEntropicValueatRiskView and SequentialEntropicValueatRiskView produce one tail view constraint each. GridEntropicValueatRiskView produces linear rows on the posterior probabilities for the lower-bound half of the view, and a tail view constraint for the upper-bound half, so an equality view produces both.

Algorithm

  1. ConicEntropicValueatRiskView checks the three preconditions below, then appends one ConicEntropicValueatRiskViewConstraint carrying x, coef, alpha and rhs.
  2. GridEntropicValueatRiskView checks that the view names one asset, and normalises w to sum to one, giving wi.
  3. It builds the grid z of dual variables with ep_evar_grid.
  4. It keeps the points whose row is finite, giving keep, and raises where keep is empty. For the upper-bound half it keeps only the points whose bound is positive, and raises where none is.
  5. For the lower-bound half of the view, it builds the row of each kept point with ep_evar_grid_row, and adds it to epc under :ineq with add_ep_constraint!, negated so the row reads as the <= sense that key states.
  6. For the upper-bound half of the view, it appends one GridEntropicValueatRiskViewConstraint carrying x, the kept grid, alpha, rhs and the big-M multiplier M.
  7. SequentialEntropicValueatRiskView orients the view and splits its assets with ep_sequential_sides, builds a SequentialEntropicValueatRiskViewConstraint with an empty surrogate row, reads its first row from the prior w with ep_sequential_start, and appends it.

Arguments

  • epc: Dictionary of entropy pooling constraints, mapping keys to (lhs, rhs) pairs.
  • tvs: Tail view constraints, appended to.
  • alg: Formulation of the view. A grid formulation is also where the number of steps and the tolerance of the anchor live, and a sequential one where the number of re-solves and their tolerance live.
  • x: Per asset the view names, its loss series.
  • coef: Per asset, the coefficient the view gives its EVaR.
  • alpha: Significance level of the view.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • w: Prior probability weights. They start the search for the dual variable the grid is centred on, and they are where the first surrogate row of a sequential view is read.
  • zstar: Per asset, the dual variable that attains its prior EVaR.
  • pv: Prior value of the view's left hand side.
  • eqn: Equation of the view, used in the error messages.
  • args: Additional positional arguments passed to the optimisation function.
  • kwargs: Additional keyword arguments passed to the optimisation function.
  • zlo_frac: Lower end of the bracket of the dual variable, as a fraction of the upper end, forwarded to ep_evar.

Validation

  • ConicEntropicValueatRiskView needs coefficients of one sign, an operator other than <=, and, for an equality, a target at or above the prior value of the left hand side.
  • GridEntropicValueatRiskView needs one asset, and at least one grid point whose row is finite, and whose bound is positive where the view carries an upper-bound half. ep_evar_grid_row overflows at a dual variable near zero, and its bound underflows to zero there. The grid sits there when pct approaches one, and wholly there when alpha * T falls below one, because ep_evar's minimiser is then at the end of its bracket. Those points are dropped, and a grid that keeps none of them raises.

Returns

  • nothing: The function mutates epc and tvs in-place.

Related

source
PortfolioOptimisers.ep_add_grid_tail_view! — Function
ep_add_grid_tail_view!(epc::AbstractDict, grid::AbstractVector, op::Symbol, row, msg)

Keep the usable points of a tail view grid, and add the rows of its lower-bound half.

ep_add_grid_tail_view! is the scaffold shared by GridEntropicValueatRiskView and GridRelativisticValueatRiskView. Both build a grid of points, drop the points whose row is not usable, and add one linear row per kept point. They differ in what a point is and in how its row is built, and both reach the scaffold through row.

A point whose row is not finite is not a grid point, because a non-finite coefficient reaches the solver as NaN * x[j]. The caller's msg names the setting that put the whole grid there.

The upper-bound half also drops a point whose bound is at or below zero. Its coefficients are positive and the posterior sums to one, so its row holds at no posterior. The lower-bound half keeps such a point: its row holds at every posterior, so it costs nothing and changes no answer.

The rows of the lower-bound half keep the norm scale of add_ep_constraint!. A row whose bound is small sits at the small end of the grid, and there the row is slack by many orders of magnitude at a posterior that meets a lower bound, because that posterior moves mass toward the largest loss, where every row takes its largest coefficient. Division by the bound would put coefficients of the order of the reciprocal of that bound into the dual that OptimEntropyPooling solves.

Algorithm

  1. Build the row of every point with row, and keep the points whose coefficients and whose right-hand side are all finite.
  2. Raise with msg where no point is kept.
  3. Where the view carries a lower-bound half, add the row of each kept point to epc under :ineq with add_ep_constraint!, negated so the row reads as the <= sense that key states.
  4. Where the view carries an upper-bound half, keep only the points whose right-hand side is positive, and raise with msg where none is kept.
  5. Return the kept points, which the caller carries into the tail view constraint of the upper-bound half.

Arguments

  • epc: Dictionary of entropy pooling constraints, mapping keys to (lhs, rhs) pairs.
  • grid: Points of the grid.
  • op: Comparison operator of the view.
  • row: Function taking one point to the coefficients and the right-hand side of its row.
  • msg: Function of no arguments giving the message of the error raised where no point is kept. It is called only where the grid keeps no point.

Validation

  • At least one point of the grid has a finite row, and, where the view carries an upper-bound half, at least one such row has a positive bound. A grid that keeps no point raises an ArgumentError carrying msg().

Returns

  • grid::AbstractVector: Points of the grid whose row is finite and, where the view carries an upper-bound half, whose bound is positive.

Related

source
PortfolioOptimisers.ep_add_rlvar_view! — Function
ep_add_rlvar_view!(epc::AbstractDict, tvs::AbstractVector,
                   alg::AbstractRelativisticValueatRiskViewFormulation,
                   x::AbstractVector{<:VecNum}, coef::VecNum, alpha::Number,
                   kappa::Number, op::Symbol, rhs::Number, w::VecNum, zstar::VecNum,
                   pv::Number, eqn::AbstractString; args::Tuple = (),
                   kwargs::NamedTuple = (;),
                   bracket::Option{<:RelativisticValueatRiskViewBracket} = nothing)

Lower one relativistic value-at-risk view into the constraints its formulation needs.

ConicRelativisticValueatRiskView and SequentialRelativisticValueatRiskView produce one tail view constraint each. GridRelativisticValueatRiskView produces linear rows on the posterior probabilities for the lower-bound half of the view, and a tail view constraint for the upper-bound half, so an equality view produces both.

Algorithm

  1. ConicRelativisticValueatRiskView checks the three preconditions below, then appends one ConicRelativisticValueatRiskViewConstraint carrying x, coef, alpha, kappa and rhs.
  2. GridRelativisticValueatRiskView checks that the view names one asset, and normalises w to sum to one, giving wi.
  3. It builds the grid t, z of primal points with ep_rlvar_grid.
  4. It keeps the points whose row is finite, giving keep, and raises where keep is empty. For the upper-bound half it keeps only the points whose bound is positive, and raises where none is.
  5. For the lower-bound half of the view, it builds the row of each kept point with ep_rlvar_grid_row, and adds it to epc under :ineq with add_ep_constraint!, negated so the row reads as the <= sense that key states.
  6. For the upper-bound half of the view, it appends one GridRelativisticValueatRiskViewConstraint carrying x, the kept grid, alpha, kappa, rhs and the big-M multiplier M.
  7. SequentialRelativisticValueatRiskView orients the view and splits its assets with ep_sequential_sides, builds a SequentialRelativisticValueatRiskViewConstraint with an empty surrogate row, reads its first row from the prior w with ep_sequential_start, and appends it.

Arguments

  • epc: Dictionary of entropy pooling constraints, mapping keys to (lhs, rhs) pairs.
  • tvs: Tail view constraints, appended to.
  • alg: Formulation of the view. A grid formulation is also where the number of steps and the tolerance of the anchor live, and a sequential one where the number of re-solves and their tolerance live.
  • x: Per asset the view names, its loss series.
  • coef: Per asset, the coefficient the view gives its RLVaR.
  • alpha: Significance level of the view.
  • kappa: Deformation parameter of the view.
  • op: Comparison operator of the view.
  • rhs: Target value of the view.
  • w: Prior probability weights. They start the search for the point the grid is centred on, and they pin the shift of each grid point where that search does not converge. They are also where the first surrogate row of a sequential view is read.
  • zstar: Per asset, the dual variable that attains its prior RLVaR.
  • pv: Prior value of the view's left hand side. With rhs it fixes the translation a grid centred on the prior carries.
  • eqn: Equation of the view, used in the error messages.
  • args: Additional positional arguments passed to the optimisation function.
  • kwargs: Additional keyword arguments passed to the optimisation function.
  • bracket: Spans of the searches, forwarded to ep_rlvar and ep_rlvar_shift.

Validation

  • ConicRelativisticValueatRiskView needs coefficients of one sign, an operator other than <=, and, for an equality, a target at or above the prior value of the left hand side.
  • GridRelativisticValueatRiskView needs one asset, and at least one grid point whose row is finite, and whose bound is positive where the view carries an upper-bound half. ep_rlvar_tail overflows at a dual variable near zero, which is where the grid sits when kappa approaches one. The bound rhs - t - z * ln_kappa(1 / (alpha * T)) of a point is at or below zero where the target lies below what the point can reach. Those points are dropped, and a grid that keeps none of them raises.

Returns

  • nothing: The function mutates epc and tvs in-place.

Related

source
PortfolioOptimisers.ep_tail_view_prior_args — Function
ep_tail_view_prior_args(tail_views::ConditionalValueatRiskView, w::VecNum)
ep_tail_view_prior_args(tail_views::EntropicValueatRiskView, w::VecNum)
ep_tail_view_prior_args(tail_views::RelativisticValueatRiskView, w::VecNum)

Give the trailing arguments a prior(...) reference of this tail view resolves under.

ep_tail_view_prior_args is one of the two kernels ep_tail_views! takes a measure from. It names the statistic get_pr_value reads, and it carries the level, the prior probabilities, and whatever settings the search for that statistic needs. replace_prior_views forwards the tuple unchanged, so a measure is added by adding a method here rather than by copying the lowering.

Arguments

  • tail_views: Tail view group whose settings the tuple carries.
  • w: Prior probability weights.

Returns

  • args::Tuple: Trailing arguments of replace_prior_views, starting with the tag of the statistic.

Related

source
PortfolioOptimisers.ep_normalise_tail_view — Function
ep_normalise_tail_view(terms::NamedTuple, X::MatNum, w::VecNum, eqn::AbstractString,
                       name::AbstractString)

Normalise the coefficients of a tail view, read the loss series it is stated on, and say whether its coefficients carry both signs.

The steps below are shared by every tail view. A view of one asset is divided by its coefficient, so its target is the measure itself. A view of several assets whose coefficients share one sign is multiplied by that sign, so every coefficient is positive and the view is a positive combination of measures, whose lower level set is convex. A view whose coefficients carry both signs is a relative view, and is left as stated.

Algorithm

  1. Read mixed, whether the coefficients carry both signs.
  2. Where the view names one asset, divide it by that asset's coefficient with ep_normalise_view_term, which flips the operator where the coefficient is negative, and set the coefficient to one.
  3. Where it names several assets and mixed is false, multiply both sides by the sign of the first coefficient through the same function, so every coefficient is positive and the operator flips where the sign is negative.
  4. Read the loss series of each asset, x, as its negated returns column.
  5. Reject a target no reweighting of the sample under the support of w reaches with ep_assert_reachable_view.

Arguments

  • terms: Resolved terms of the view, as ep_view_terms returns them.
  • X: Matrix of asset returns.
  • w: Prior probability weights.
  • eqn: Equation of the view, used in the error messages.
  • name: Name of the risk measure, used in the error messages.

Returns

  • x::AbstractVector{<:VecNum}: Per asset the view names, its loss series.
  • coef::VecNum: Per asset, its normalised coefficient.
  • op::Symbol: Operator of the normalised view.
  • rhs::Number: Target of the normalised view.
  • mixed::Bool: Whether the coefficients carry both signs.

Related

source
PortfolioOptimisers.ep_add_tail_view! — Function
ep_add_tail_view!(epc::AbstractDict, tvs::AbstractVector,
                  tail_views::ConditionalValueatRiskView, alg, X::MatNum,
                  terms::NamedTuple, eqn::AbstractString, w::VecNum)
ep_add_tail_view!(epc::AbstractDict, tvs::AbstractVector,
                  tail_views::EntropicValueatRiskView, alg, X::MatNum,
                  terms::NamedTuple, eqn::AbstractString, w::VecNum)
ep_add_tail_view!(epc::AbstractDict, tvs::AbstractVector,
                  tail_views::RelativisticValueatRiskView, alg, X::MatNum,
                  terms::NamedTuple, eqn::AbstractString, w::VecNum)

Lower one resolved tail view into the constraints its measure and its formulation need.

ep_add_tail_view! is the second of the two kernels ep_tail_views! takes a measure from. ep_tail_views! parses the group, expands its groups, and resolves its prior references and its terms; this verb carries everything past that point, which is everything the measures do not share. A measure is added by adding a method here and to ep_tail_view_prior_args.

Every measure admits a view over several assets. Normalise it with ep_normalise_tail_view, which also says whether the coefficients carry both signs, and read pv, the prior value of the left hand side, as the coefficient-weighted sum of the per-asset measures under w. Then pick the formulation and lower the view:

  1. A ConditionalValueatRiskView reads each asset's prior CVaR through ConditionalValueatRisk, picks the formulation with ep_cvar_formulation, and appends with ep_add_cvar_view!.
  2. An EntropicValueatRiskView reads each asset's prior EVaR and the dual variable that attains it with ep_evar, picks the formulation with ep_evar_formulation, and appends with ep_add_evar_view!.
  3. A RelativisticValueatRiskView reads each asset's prior RLVaR and the primal pair that attains it with ep_rlvar, picks the formulation with ep_rlvar_formulation, and appends with ep_add_rlvar_view!.

Arguments

  • epc: Dictionary of entropy pooling constraints, mapping keys to (lhs, rhs) pairs.
  • tvs: Tail view constraints, appended to.
  • tail_views: Tail view group the view belongs to. It carries the level, the formulation setting, and the settings of the searches.
  • alg: Formulation of this view, as ep_view_formulations spread it.
  • X: Matrix of asset returns.
  • terms: Resolved terms of the view, as ep_view_terms returns them.
  • eqn: Equation of the view, used in the error messages.
  • w: Prior probability weights.

Returns

  • nothing: The function mutates epc and tvs in-place.

Related

References

  • [1] D. Cajas. Entropy Pooling with CVaR and EVaR Views. Available at SSRN 7120258 (2026).
  • [2] D. Cajas. Entropy Pooling with Relativistic Value at Risk Views. Available at SSRN 7329718 (2026).
source
PortfolioOptimisers.ep_tail_views! — Function
ep_tail_views!(tail_views::Nothing, args...; kwargs...)

No-op pass-through for tail view constraints when none are specified.

Arguments

  • tail_views::Nothing: Indicates that no tail view constraints are specified.
  • args...: Additional positional arguments (ignored).
  • kwargs...: Additional keyword arguments (ignored).

Returns

  • nothing.

Related

source
ep_tail_views!(tail_views::AbstractVector{<:AbstractEntropyPoolingTailViewEstimator},
               args...; kwargs...)

Lower each group of tail views under its own settings.

Every AbstractEntropyPoolingTailViewEstimator in the vector is lowered in turn, so the groups accumulate into the same constraint set and one entropy pooling solve answers all of them.

Algorithm

  1. Lower each group of tail_views in turn, forwarding args... and kwargs... to each call.
  2. Return nothing. Each call has already written its constraints into epc and tvs.

Arguments

  • tail_views: Groups of tail views.
  • args...: Additional positional arguments forwarded to ep_tail_views!.
  • kwargs...: Additional keyword arguments forwarded to ep_tail_views!.

Returns

  • nothing: The function mutates epc and tvs in-place.

Related

source
ep_tail_views!(tail_views::AbstractEntropyPoolingTailViewEstimator, epc::AbstractDict,
               tvs::AbstractVector, pr::AbstractPriorResult, sets::UniverseSets,
               w::VecNum; strict::Bool = false)

Parse a group of tail views and lower them into entropy pooling constraints.

ep_tail_views! is the one lowering of the tail view family. It parses the view equations of a LinearConstraintEstimator, replaces prior references with their values, resolves the asset names against the universe, picks a formulation for each view, and appends the constraints that formulation needs. Unlike the recursive algorithm of MeucciEntropyPoolingPrior, nothing is solved here: the views become part of the one entropy pooling problem entropy_pooling solves.

It accepts ==, >= and <=. A group name expands to its members, each carrying the coefficient the group carried, so a view on a group constrains the sum of the members' risk measures and not their average. A view whose coefficients share one sign is a positive combination of measures, and its lower-bound form is convex. A view whose coefficients carry both signs is a relative view, and is not.

The two kernels below carry everything that differs between the conditional, the entropic and the relativistic measure, so a fourth measure supplies two methods rather than a fourth copy of this verb:

  • ep_tail_view_prior_args names the statistic a prior(...) reference resolves to, and the settings its search takes.
  • ep_add_tail_view! checks the shape of the view, reads its prior value, picks its formulation, and appends its constraints.

Algorithm

  1. Parse the view equations of tail_views.views.val, giving one ParsingResult per view.
  2. Replace every group name by the assets it spans, giving one term per member.
  3. Replace every prior(...) reference by the prior value of the measure, through replace_prior_views under the tuple ep_tail_view_prior_args gives.
  4. Spread the formulation setting over the views with ep_view_formulations, giving algs.
  5. For each view in turn, resolve its terms with ep_view_terms, and drop the view where no name of it is placed in the universe.
  6. Lower the view with ep_add_tail_view!.

Arguments

  • tail_views: Tail view constraints.
  • epc: Dictionary of entropy pooling constraints, mapping keys to (lhs, rhs) pairs.
  • tvs: Tail view constraints, appended to.
  • pr: Prior result containing asset return information.
  • sets: Asset set mapping asset names to indices.
  • w: Prior probability weights.
  • strict: If true, throws error for missing assets; otherwise, issue warnings.

Returns

  • nothing: The function mutates epc and tvs in-place.

Related

References

  • [1] D. Cajas. Entropy Pooling with CVaR and EVaR Views. Available at SSRN 7120258 (2026).
  • [2] D. Cajas. Entropy Pooling with Relativistic Value at Risk Views. Available at SSRN 7329718 (2026).
source
PortfolioOptimisers.ep_check_tail_window — Method
ep_check_tail_window(tv::IntegerConditionalValueatRiskViewConstraint, w::VecNum)

Warn where the window of an integer conditional value-at-risk view can restrict the posterior.

The model of IntegerConditionalValueatRiskView admits the posteriors that put at least alpha of their mass on the sbar largest losses of each asset. Where that restriction binds, the window holds exactly alpha, and the method warns. A window that holds more is not active at the posterior, so a small change of the posterior does not meet it.

Algorithm

  1. For each asset of the view, skip a window that holds every observation, since it restricts nothing.
  2. Sum w over the window, and warn where the sum exceeds alpha by no more than alpha times the cube root of the machine epsilon of w. That margin is far above the feasibility tolerance of a solver and far below the mass of one observation.

Arguments

  • tv: Integer conditional value-at-risk view constraint.
  • w: Posterior probabilities of the last solve.

Returns

  • nothing.

Related

source

References

[1]
D. Cajas. Entropy Pooling with CVaR and EVaR Views. Available at SSRN 7120258 (2026).
[2]
D. Cajas. Entropy Pooling with Relativistic Value at Risk Views. Available at SSRN 7329718 (2026).