Meucci Entropy Pooling
PortfolioOptimisers.MeucciEntropyPoolingPrior — Type
struct MeucciEntropyPoolingPrior{__T_pe, __T_mu_views, __T_var_views, __T_cvar_views, __T_sigma_views, __T_sk_views, __T_kt_views, __T_cov_views, __T_rho_views, __T_sets, __T_ds_opt, __T_dm_opt, __T_opt, __T_w, __T_alg} <: AbstractLowOrderPriorEstimator_AFReweights the observations of a prior so that its moments meet a set of views, and root-finds a CVaR view.
MeucciEntropyPoolingPrior is a low order prior estimator that computes the mean and covariance of asset returns using entropy pooling. It supports views on the mean, the value at risk, the conditional value at risk, the variance, the covariance, the correlation, the skewness and the kurtosis, and it takes custom prior weights and solver configuration.
This is the earlier of the library's two entropy pooling estimators, and it is kept because its CVaR route is a different algorithm, not a different formulation of the same problem: a CVaR view is a target hunted by the recursive algorithm of Meucci, Ardia and Keel, where ConditionalValueatRiskEntropyPooling root-finds the value at risk level and re-solves the whole entropy pooling problem at each candidate. That route takes equality CVaR views alone, one asset per view.
Reach for EntropyPoolingPrior instead where a tail view has to be an inequality, name two assets, or land on the entropic value at risk: there each tail view is a constraint of the single entropy pooling problem, so one solve answers every view.
Fields
pe: Prior estimator.
mu_views: Expected returns views estimator or result.
var_views: Value-at-risk views estimator or result.
cvar_views: Conditional value-at-risk views estimator or result.
sigma_views: Variance views estimator or result.
sk_views: Skewness views estimator or result.
kt_views: Kurtosis views estimator or result.
cov_views: Covariance views estimator or result.
rho_views: Correlation views estimator or result.
sets: Sets used to map estimator values to assets.
ds_opt: Thin wrapper for arguments and keyword arguments used inRoots.findzerofor use with a single conditional value-at-risk view.
dm_opt: Optimiser for multiple conditional value at risk views.
opt: Entropy pooling optimisation estimator.
w: Prior observation probability weights. Ifnothing, uniform weights are used.
alg: Entropy pooling algorithm.
Constructors
MeucciEntropyPoolingPrior(; pe::AbstractLowOrderPriorEstimator_A_F_AF = EmpiricalPrior(), mu_views::Option{<:LinearConstraintEstimator} = nothing, var_views::Option{<:VV_VecVV} = nothing, cvar_views::Option{<:CVV_VecCVV} = nothing, sigma_views::Option{<:LinearConstraintEstimator} = nothing, sk_views::Option{<:LinearConstraintEstimator} = nothing, kt_views::Option{<:LinearConstraintEstimator} = nothing, cov_views::Option{<:LinearConstraintEstimator} = nothing, rho_views::Option{<:LinearConstraintEstimator} = nothing, sets::Option{<:UniverseSets} = nothing, ds_opt::Option{<:ConditionalValueatRiskEntropyPooling} = nothing, dm_opt::Option{<:OptimEntropyPooling} = nothing, opt::NonCVaREP = OptimEntropyPooling(), w::Option{<:StatsBase.ProbabilityWeights} = nothing, alg::AbstractEntropyPoolingAlgorithm = H1_EntropyPooling()) -> MeucciEntropyPoolingPriorKeywords correspond to the struct's fields.
Validation
- If any view constraint is not
nothing,setsmust not benothing. - If
var_viewsis a vector,!isempty(var_views). - If
wis notnothing, it must be non-empty and match the number of observations.
Propagated parameters
When factory is called on this type, the following @fprop-tagged fields are automatically propagated:
pe: Recursively updated viafactory.w: Replaced with the incomingObsWeights.
View parameters
When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:
pe: Recursively viewed viaport_opt_view.sets: Sliced to the selected indices viaport_opt_view.
Observation weight parameters
When obs_weights_view is called on this type, the following fields are automatically indexed to the selected observations:
pe: Recursively indexed viaobs_weights_view.w: Indexed to the selected observations viaobs_weights_view.
Details
- If
wis notnothing, it is normalised to sum to 1; otherwise, uniform weights are used whenprioris called.
View comparison operators
The comparison operators accepted in each view's constraint strings depend on the moment being constrained. An unsupported operator raises a ParseError listing the operators allowed for that view.
mu_views,sigma_views,sk_views,kt_views,cov_views,rho_viewsaccept==,>=and<=.var_views(Value at Risk) accepts only==and>=.cvar_views(Conditional Value at Risk) accepts only==.
Examples
julia> MeucciEntropyPoolingPrior(; sets = UniverseSets(; xkey = "nx", dict = Dict("nx" => ["A", "B", "C"])), mu_views = LinearConstraintEstimator(; val = ["A == 0.03", "B + C == 0.04"]))MeucciEntropyPoolingPrior pe ┼ EmpiricalPrior │ ce ┼ PortfolioOptimisersCovariance │ │ ce ┼ Covariance │ │ │ me ┼ SimpleExpectedReturns │ │ │ │ w ┴ nothing │ │ │ ce ┼ GeneralCovariance │ │ │ │ ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true) │ │ │ │ w ┴ nothing │ │ │ alg ┴ FullMoment() │ │ mp ┼ MatrixProcessing │ │ │ pdm ┼ Posdef │ │ │ │ alg ┼ UnionAll: NearestCorrelationMatrix.Newton │ │ │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ │ │ dn ┼ nothing │ │ │ dt ┼ nothing │ │ │ alg ┼ nothing │ │ │ order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg) │ me ┼ SimpleExpectedReturns │ │ w ┴ nothing │ horizon ┴ nothing mu_views ┼ LinearConstraintEstimator │ val ┼ Vector{String}: ["A == 0.03", "B + C == 0.04"] │ key ┴ nothing var_views ┼ nothing cvar_views ┼ nothing sigma_views ┼ nothing sk_views ┼ nothing kt_views ┼ nothing cov_views ┼ nothing rho_views ┼ nothing sets ┼ UniverseSets │ xkey ┼ String: "nx" │ uxkey ┼ String: "ux" │ fkey ┼ String: "nf" │ ufkey ┼ String: "uf" │ zkey ┼ String: "nz" │ dict ┴ Dict{String, Vector{String}}: Dict("nx" => ["A", "B", "C"]) ds_opt ┼ nothing dm_opt ┼ nothing opt ┼ OptimEntropyPooling │ args ┼ Tuple{}: () │ kwargs ┼ @NamedTuple{}: NamedTuple() │ sc1 ┼ Int64: 1 │ sc2 ┼ Float64: 1000.0 │ alg ┼ ExpEntropyPooling() │ err ┴ nothing w ┼ nothing alg ┴ H1_EntropyPooling()Related
AbstractLowOrderPriorEstimator_AFAbstractLowOrderPriorEstimator_A_F_AFEmpiricalPriorLinearConstraintEstimatorUniverseSetsConditionalValueatRiskEntropyPoolingOptimEntropyPoolingOptimEntropyPoolingJuMPEntropyPoolingAbstractEntropyPoolingAlgorithmEntropyPoolingPriorfactoryport_opt_viewobs_weights_view
References
PortfolioOptimisers.VecMeucciEP — Type
const VecMeucciEP = AbstractVector{<:MeucciEntropyPoolingPrior}Alias for an abstract vector of MeucciEntropyPoolingPrior elements.
Related
PortfolioOptimisers.ep_cvar_views_solve! — Function
ep_cvar_views_solve!(cvar_views::Nothing, epc::AbstractDict, ::Any, ::Any,
w::StatsBase.ProbabilityWeights, opt::AbstractEntropyPoolingOptimiser, ::Any, ::Any;
kwargs...)Solve the entropy pooling problem when no CVaR views are specified.
ep_cvar_views_solve! is an internal API compatibility method that solves the entropy pooling problem when no conditional value at risk (CVaR) view constraints are present (cvar_views = nothing). It delegates to the main entropy pooling solver using the provided prior weights, constraint dictionary, and optimiser.
Arguments
cvar_views: Indicates that no CVaR view constraints are specified.epc: Dictionary of entropy pooling constraints, mapping keys to(lhs, rhs)pairs.::Any: Prior result, ignored on this path.::Any: Asset set, ignored on this path.w: Prior probability weights.opt: Entropy pooling optimiser.::Any: CVaR-specific optimiser, ignored on this path.::Any: General optimiser, ignored on this path.kwargs...: Additional keyword arguments forwarded to the solver.
Returns
pw::StatsBase.ProbabilityWeights: Posterior probability weights satisfying the constraints.
Details
- This method is used for API compatibility when CVaR views are not present.
- Calls
entropy_poolingwith the provided arguments.
Related
ep_cvar_views_solve!(cvar_views::CVV_VecCVV, epc::AbstractDict,
pr::AbstractPriorResult, sets::UniverseSets,
w::StatsBase.ProbabilityWeights, opt::AbstractEntropyPoolingOptimiser,
ds_opt::Option{<:ConditionalValueatRiskEntropyPooling},
dm_opt::Option{<:OptimEntropyPooling}; strict::Bool = false)Solve the entropy pooling problem with Conditional Value-at-Risk (CVaR) view constraints.
ep_cvar_views_solve! parses and validates CVaR view constraints, replaces prior references, and constructs the corresponding entropy pooling constraint system. It then solves for posterior probability weights using either root-finding (for single CVaR view) or optimisation (for multiple views), depending on the number of constraints and the provided optimiser. Throws informative errors if views are infeasible or too extreme.
Arguments
cvar_views: CVaR view constraints.epc: Dictionary of entropy pooling constraints, mapping keys to(lhs, rhs)pairs.pr: Prior result containing asset return information.sets: Asset set mapping asset names to indices.w: Prior probability weights.opt: Main entropy pooling optimiser.ds_opt: CVaR-specific optimiser (for single view).dm_opt: General optimiser (for multiple views).strict: Iftrue, throws error for missing assets; otherwise, issue warnings.
Returns
pw::StatsBase.ProbabilityWeights: Posterior probability weights satisfying CVaR view constraints.
Details
- Parses CVaR view equations and replaces prior references.
- Validates that only equality constraints are present and that each view targets a single asset.
- Checks that views are not too extreme i.e. not greater than the worst realisation.
- The search runs over the value at risk levels
etas, one per view, each bounded by[0, B]. This is a continuous relaxation of the recursive algorithm, which searches over discrete tail sizes instead; it reaches the same target and it takes more than one view. - For a single CVaR view, uses root-finding via
ConditionalValueatRiskEntropyPooling. - For multiple CVaR views, uses optimisation via
OptimEntropyPooling. - Throws errors if optimisation fails or views are infeasible.
Related
References
- [82] A. Meucci, D. Ardia and S. Keel. Fully flexible extreme views. The Journal of Risk 14, 39–49 (2011).
PortfolioOptimisers.prior — Function
prior(pe::MeucciEntropyPoolingPrior, X::MatNum, F::Option{<:MatNum} = nothing;
dims::Int = 1, strict::Bool = false, kwargs...)Compute entropy pooling prior moments for asset returns.
prior orients the data with respect to dims and delegates to ep_prior, which dispatches on the entropy pooling algorithm pe.alg. H0_EntropyPooling enforces every view in a single optimisation. StagedEP, the union of H1_EntropyPooling and H2_EntropyPooling, enforces the views in stages, from lower to higher moments.
Arguments
pe: Entropy pooling prior estimator.X: Asset returns matrix (observations × assets).F: Optional factor matrix.dims: Dimension along which to perform the computation.strict: Iftrue, throws error for missing assets; otherwise, issues warnings.kwargs...: Additional keyword arguments passed to underlying estimators and solvers.
Validation
dims in (1, 2).
Returns
pr::LowOrderPrior: Result object containing asset returns, posterior mean vector, posterior covariance matrix, weights, effective number of scenarios, Kullback-Leibler divergence, and optional factor moments.
Related
PortfolioOptimisers.ep_prior — Method
ep_prior(alg::StagedEP, pe::MeucciEntropyPoolingPrior, X::MatNum, F::Option{<:MatNum};
strict::Bool = false, kwargs...)Compute entropy pooling prior moments for asset returns with iterative constraint enforcement.
ep_prior estimates the mean and covariance of asset returns using the entropy pooling framework, supporting iterative constraint enforcement via the H1_EntropyPooling and H2_EntropyPooling algorithms. It integrates moment and view constraints (mean, variance, CVaR, skewness, kurtosis, correlation), flexible confidence specification, and composable optimisation algorithms. The method iteratively applies constraints, updating prior weights and moments at each step, and ensures that higher moment views do not inadvertently alter lower moments.
Mathematical definition
Entropy pooling finds posterior weights $\boldsymbol{p}$ by minimising the Kullback-Leibler divergence from the prior $\boldsymbol{q}$:
\[\begin{align} \underset{\boldsymbol{p}}{\min} &\sum_{t=1}^{T} p_t \ln\!\frac{p_t}{q_t} \quad \text{s.t.} \quad \mathbf{A}_{\mathrm{eq}} \boldsymbol{p} = \boldsymbol{b}_{\mathrm{eq}}, \quad \mathbf{A}_{\mathrm{ineq}} \boldsymbol{p} \leq \boldsymbol{b}_{\mathrm{ineq}}, \quad \boldsymbol{p} \geq \boldsymbol{0}, \quad \boldsymbol{1}^\intercal \boldsymbol{p} = 1\,. \end{align}\]
Where:
- $\boldsymbol{p}$: $T \times 1$ posterior weight vector.
- $\boldsymbol{q}$: $T \times 1$ prior weight vector.
- $\mathbf{A}_{\mathrm{eq}}$, $\boldsymbol{b}_{\mathrm{eq}}$: Equality constraint matrix and vector.
- $\mathbf{A}_{\mathrm{ineq}}$, $\boldsymbol{b}_{\mathrm{ineq}}$: Inequality constraint matrix and vector.
- $T$: Number of observations.
Posterior moments are then computed as probability-weighted sample statistics using $\boldsymbol{p}^*$.
Arguments
alg: Staged entropy pooling algorithm, taken frompe.algbyprior.pe: Entropy pooling prior estimator.X: Asset returns matrix (observations × assets), oriented byprior.F: Optional factor matrix, oriented byprior.strict: Iftrue, throws error for missing assets; otherwise, issues warnings.kwargs...: Additional keyword arguments passed to underlying estimators and solvers.
Validation
- If any view constraint is not
nothing,!isnothing(sets). - If prior weights
pe.ware provided,length(pe.w) == T, whereTis the number of observations.
Returns
pr::LowOrderPrior: Result object containing asset returns, posterior mean vector, posterior covariance matrix, weights, effective number of scenarios, Kullback-Leibler divergence, and optional factor moments.
Details
- If
isnothing(pe.w), prior weights are initialised to1/TwhereTis the number of observations; otherwise, provided weights are normalised. - Constraints are enforced iteratively, from lower to higher moments.
- Moment and view constraints are parsed and added to the constraint dictionary.
- The initial weights for each stage is selected according to
pe.alg. - At each stage, the prior weights are updated by solving the entropy pooling optimisation with the current set of constraints. If present, the CVaR views are also enforced at every stage.
- Lower moments are fixed as needed to prevent distortion by higher moment views. If asset
ihas a view enforced on momentNthat uses momentsn < Nto compute, then all momentsnfor assetiare fixed. - The final result includes the effective number of scenarios and Kullback-Leibler divergence between prior and posterior weights.
Related
PortfolioOptimisers.ep_prior — Method
ep_prior(alg::H0_EntropyPooling, pe::MeucciEntropyPoolingPrior, X::MatNum,
F::Option{<:MatNum}; strict::Bool = false, kwargs...)Compute entropy pooling prior moments for asset returns with single-shot constraint enforcement.
ep_prior estimates the mean and covariance of asset returns using the entropy pooling framework, enforcing all moment and view constraints in a single optimisation step via the H0_EntropyPooling algorithm. This approach is fast but may distort lower moments when higher moment views are present, as all constraints are applied simultaneously.
Mathematical definition
Entropy pooling finds posterior weights $\boldsymbol{p}$ by minimising the Kullback-Leibler divergence from the prior $\boldsymbol{q}$ subject to all constraints simultaneously:
\[\begin{align} \underset{\boldsymbol{p}}{\min} &\sum_{t=1}^{T} p_t \ln\!\frac{p_t}{q_t} \quad \text{s.t.} \quad \mathbf{A}_{\mathrm{eq}} \boldsymbol{p} = \boldsymbol{b}_{\mathrm{eq}}, \quad \mathbf{A}_{\mathrm{ineq}} \boldsymbol{p} \leq \boldsymbol{b}_{\mathrm{ineq}}, \quad \boldsymbol{p} \geq \boldsymbol{0}, \quad \boldsymbol{1}^\intercal \boldsymbol{p} = 1\,. \end{align}\]
Where:
- $\boldsymbol{p}$: $T \times 1$ posterior weight vector.
- $\boldsymbol{q}$: $T \times 1$ prior weight vector.
- $\mathbf{A}_{\mathrm{eq}}$, $\boldsymbol{b}_{\mathrm{eq}}$: Equality constraint matrix and vector.
- $\mathbf{A}_{\mathrm{ineq}}$, $\boldsymbol{b}_{\mathrm{ineq}}$: Inequality constraint matrix and vector.
- $T$: Number of observations.
Arguments
alg: Single-shot entropy pooling algorithm, taken frompe.algbyprior.pe: Entropy pooling prior estimator.X: Asset returns matrix (observations × assets), oriented byprior.F: Optional factor matrix, oriented byprior.strict: Iftrue, throws error for missing assets; otherwise, issues warnings.kwargs...: Additional keyword arguments passed to underlying estimators and solvers.
Validation
- If any view constraint is not
nothing,!isnothing(pe.sets). - If prior weights
pe.ware provided,length(pe.w) == T, whereTis the number of observations
Returns
pr::LowOrderPrior: Result object containing asset returns, posterior mean vector, posterior covariance matrix, weights, effective number of scenarios, Kullback-Leibler divergence, and optional factor moments.
Details
- If
isnothing(pe.w), prior weights are initialised to1/TwhereTis the number of observations; otherwise, provided weights are normalised. - All constraints are parsed and added to the constraint dictionary at once. This means that lower moments may be distorted by higher moment views, since they cannot be fixed at any point.
- A single optimisation is performed to solve for the posterior weights, enforcing all constraints at once.
- The final result includes the effective number of scenarios and Kullback-Leibler divergence between prior and posterior weights.
Related
References
- [80]
- A. Meucci. Fully flexible views: theory and practice. Risk 21, 97–102 (2008).
- [81]
- A. Vorobets. Sequential entropy pooling heuristics. Available at SSRN 3936392 (2021).
- [82]
- A. Meucci, D. Ardia and S. Keel. Fully flexible extreme views. The Journal of Risk 14, 39–49 (2011).