Phylogeny Constraints
PortfolioOptimisers.SemiDefinitePhylogenyEstimator — Type
struct SemiDefinitePhylogenyEstimator{__T_pl, __T_p} <: AbstractPhylogenyConstraintEstimatorForbids co-movement between related assets through a semidefinite relaxation, refitting the structure from returns.
The estimator holds the source that builds the relatedness matrix and the penalty factor p. phylogeny_constraints refits the source against a returns matrix and returns a SemiDefinitePhylogeny, which carries the equations this constraint solves.
Which pairs a network source relates — and therefore how strong the constraint is — comes from its AbstractSeparationAlgorithm, not from anything set here. The constraint is weight-inert: A ⊙ W == 0 is the same constraint at any magnitude, so the separation changes the cardinality of the forbidden set and nothing else.
NetworkEstimator(; sep = PathLength()) relates every reachable pair. A bare PathLength leaves dmax = nothing, which resolves to the observed diameter, so nothing is outside the budget — measured, 190 of 190 pairs — and this estimator then forbids all pairwise co-movement. It is the opposite end of the dial from HopCount's default n = 1. State a numeric dmax to select anything narrower.
Fields
pl: Network estimator or clustering estimator. A precomputedPhylogenyResultorClustersis not accepted: this slot says how to build the phylogeny for whatever universe the estimator is given, and a precomputed one answers for a fixed universe instead. Pass the constraint result if you already have the structure.
p: Non-negative penalty factor on the trace of the semidefinite matrix variable. It is read only when the model does not already minimise a variance: a variance objective is itself a trace against that variable, so it pulls the relaxation down on its own and no second term is added.
Constructors
SemiDefinitePhylogenyEstimator(; pl::NwE_ClE = NetworkEstimator(), p::Number = 0.05) -> SemiDefinitePhylogenyEstimatorKeywords correspond to the struct's fields. The default p = 0.05 is the value the source's own worked example uses.
Validation
p >= 0.plis bounded byNwE_ClE: a precomputedPhylogenyResultorClustersis rejected by the type, not by a check, so the keyword constructor raisesTypeErrorrather than deferring the problem to a solve. BuildSemiDefinitePhylogenyinstead, which is whatphylogeny_constraints(estimator, X)returns.
Examples
julia> SemiDefinitePhylogenyEstimator()SemiDefinitePhylogenyEstimator pl ┼ NetworkEstimator │ 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) │ de ┼ Distance │ │ power ┼ nothing │ │ alg ┴ CanonicalDistance() │ alg ┼ KruskalTree │ │ args ┼ Tuple{}: () │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ sep ┼ HopCount │ │ n ┴ Int64: 1 p ┴ Float64: 0.05Related
References
- [72] D. Cajas. A Graph Theory Approach to Portfolio Optimization. Available at SSRN 4602019 (2023).
- [73] D. Cajas. A Graph Theory Approach to Portfolio Optimization Part II. Available at SSRN 4667426 (2023).
- [4] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Sections 13.1.7.2 and 13.2.4.2.
PortfolioOptimisers.SemiDefinitePhylogeny — Type
struct SemiDefinitePhylogeny{__T_A, __T_p} <: AbstractPhylogenyConstraintResultDrives the product of weights of every related pair of assets to zero through a semidefinite relaxation.
Relatedness is whatever the source that built A calls related: a neighbourhood over a network, or membership of one cluster.
Mathematical definition
The relaxation replaces the outer product of the weights with a symmetric matrix variable and bounds it below through a Schur complement. Where the objective is already a trace against that variable — a variance — the constraint form applies:
\[\begin{align} \underset{\boldsymbol{w},\, \mathbf{W}}{\min}\quad & \mathrm{tr}(\mathbf{\Sigma} \mathbf{W})\\ \textrm{s.t.}\quad & \begin{bmatrix} \mathbf{W} & \boldsymbol{w} \\ \boldsymbol{w}^\intercal & k \end{bmatrix} \succeq 0\,,\\ & \mathbf{A} \odot \mathbf{W} = 0\,,\\ & \mathbf{W} \in \mathbb{S}^{N}\,,\quad \boldsymbol{w} \in \mathcal{W}\,. \end{align}\]
For every other risk measure nothing in the objective pulls the relaxation down, so a penalty term does it instead:
\[\begin{align} \underset{\boldsymbol{w},\, \mathbf{W}}{\min}\quad & \phi(\boldsymbol{w}) + p\, \mathrm{tr}(\mathbf{W})\,. \end{align}\]
Where:
- $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
- $\mathbf{W}$: Symmetric $N \times N$ matrix variable that relaxes $\boldsymbol{w}\boldsymbol{w}^\intercal / k$.
- $\mathbf{A}$: Relatedness matrix, the
Afield. - $p$: Penalty factor, the
pfield. - $k$: Budget scaling / homogenisation variable.
- $\mathbf{\Sigma}$: Covariance matrix.
- $\phi$: Risk measure of the optimiser.
- $\odot$: Hadamard product.
- $\mathbb{S}^{N}$: Set of real symmetric $N \times N$ matrices.
- $\mathcal{W}$: Rest of the feasible set.
The two branches are what the code does: set_sdp_phylogeny_constraints! always writes A ⊙ W == 0 and adds p * tr(W) to the objective penalty only when the model carries no variance. On a 250×6 sample the Hadamard constraint holds to 2.1e-18 under a variance objective and to 3.1e-21 under a conditional-value-at-risk objective.
p therefore sets the size of the relaxation gap, not the strength of the constraint. A ⊙ W == 0 is weight-inert: it is the same constraint at any magnitude of A. What p buys is how closely W tracks the outer product it stands for. On the same sample the largest entry of $\mathbf{W} - \boldsymbol{w}\boldsymbol{w}^\intercal$ is 2.7e-5 under the variance objective, where the objective itself closes the gap, against 0.0274 under conditional value at risk at the default p = 0.05 — three orders of magnitude wider. A wider gap lets a pair of related assets both hold weight while their entry of W absorbs the product.
Fields
A: Symmetric relatedness matrix with a zero diagonal. A network source gives the range connection matrix, a clustering source the adjacency label matrix. Stored as given.
p: Non-negative penalty factor on the trace of the semidefinite matrix variable. It is read only when the model does not already minimise a variance: a variance objective is itself a trace against that variable, so it pulls the relaxation down on its own and no second term is added.
Constructors
SemiDefinitePhylogeny( A::MatNum_PhRMatNum, p::Number) -> SemiDefinitePhylogenySemiDefinitePhylogeny(; A::MatNum_PhRMatNum, p::Number = 0.05) -> SemiDefinitePhylogenyKeywords correspond to the struct's fields. The default p = 0.05 is the value the source's own worked example uses.
Validation
LinearAlgebra.issymmetric(A)andall(iszero, LinearAlgebra.diag(A)).p >= 0.
Examples
julia> SemiDefinitePhylogeny([0.0 1.0; 1.0 0.0], 0.05)SemiDefinitePhylogeny A ┼ 2×2 Matrix{Float64} p ┴ Float64: 0.05Related
set_sdp_constraints!set_sdp_frc_constraints!set_sdp_phylogeny_constraints!SemiDefinitePhylogenyEstimatorAbstractPhylogenyConstraintResultphylogeny_constraints
References
- [72] D. Cajas. A Graph Theory Approach to Portfolio Optimization. Available at SSRN 4602019 (2023).
- [73] D. Cajas. A Graph Theory Approach to Portfolio Optimization Part II. Available at SSRN 4667426 (2023).
- [4] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Sections 13.1.7.2 and 13.2.4.2.
PortfolioOptimisers.IntegerPhylogenyEstimator — Type
struct IntegerPhylogenyEstimator{__T_pl, __T_B} <: AbstractPhylogenyConstraintEstimatorCaps how many related assets may be held at once, refitting the structure from returns.
The estimator holds the source that builds the relatedness matrix and the cap B. phylogeny_constraints refits the source against a returns matrix and returns an IntegerPhylogeny, which carries the equations this constraint solves.
Which pairs a network source relates comes from its AbstractSeparationAlgorithm, and B is an integer cardinality counted over them. The relatedness itself stays binary under either separation: PhylogenyResult's matrix is Int, and a graded one would not be countable here.
NetworkEstimator(; sep = PathLength()) relates every reachable pair. A bare PathLength leaves dmax = nothing, which resolves to the observed diameter, so nothing is outside the budget — measured, 190 of 190 pairs. It is the opposite end of the dial from HopCount's default n = 1. State a numeric dmax to select anything narrower.
Fields
pl: Network estimator or clustering estimator. A precomputedPhylogenyResultorClustersis not accepted: this slot says how to build the phylogeny for whatever universe the estimator is given, and a precomputed one answers for a fixed universe instead. Pass the constraint result if you already have the structure.
B: Right-hand side ofA * z <= B, wherezis the held indicator: the largest number of assets that may be held out of each row ofA. A scalar applies to every row. A vector states one bound per row, so its length must match the row count of the storedAand not the number of assets. On an estimator the rows do not exist yet, so a vector is only checked against the largest number of clusters the clustering estimator can return.
Constructors
IntegerPhylogenyEstimator(; pl::NwE_ClE = NetworkEstimator(), B::Int_VecInt = 1) -> IntegerPhylogenyEstimatorKeywords correspond to the struct's fields.
Validation
Bis validated withassert_nonempty_nonneg_finite_val.AbstractVector: It is additionally validated withvalidate_length_integer_phylogeny_constraint_B.
plis bounded byNwE_ClE: a precomputedPhylogenyResultorClustersis rejected by the type, not by a check, so the keyword constructor raisesTypeErrorrather than deferring the problem to a solve. BuildIntegerPhylogenyinstead, which is whatphylogeny_constraints(estimator, X)returns.
Examples
julia> IntegerPhylogenyEstimator()IntegerPhylogenyEstimator pl ┼ NetworkEstimator │ 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) │ de ┼ Distance │ │ power ┼ nothing │ │ alg ┴ CanonicalDistance() │ alg ┼ KruskalTree │ │ args ┼ Tuple{}: () │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ sep ┼ HopCount │ │ n ┴ Int64: 1 B ┴ Int64: 1Related
References
- [74] F. Ricca and A. Scozzari. Portfolio optimization through a network approach: network assortative mixing and portfolio diversification. European Journal of Operational Research 312, 700–717 (2024).
- [72] D. Cajas. A Graph Theory Approach to Portfolio Optimization. Available at SSRN 4602019 (2023).
- [73] D. Cajas. A Graph Theory Approach to Portfolio Optimization Part II. Available at SSRN 4667426 (2023).
- [4] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Sections 13.1.7.1 and 13.2.4.1.
PortfolioOptimisers.IntegerPhylogeny — Type
struct IntegerPhylogeny{__T_A, __T_B} <: AbstractPhylogenyConstraintResultCaps at B the number of related assets a mixed-integer model may hold at once.
Relatedness is whatever the source that built A calls related: a neighbourhood over a network, or membership of one cluster.
Mathematical definition
The cap is a mutually exclusive investment constraint on the held binary:
\[\begin{align} \underset{\boldsymbol{w}}{\mathrm{opt}}\quad & \phi(\boldsymbol{w})\\ \textrm{s.t.}\quad & \mathbf{A} \boldsymbol{z} \leq \boldsymbol{B}\,,\\ & \boldsymbol{\ell} \odot \boldsymbol{z} \leq \boldsymbol{w} \leq \boldsymbol{u} \odot \boldsymbol{z}\,,\\ & \boldsymbol{z} \in \{0, 1\}^{N}\,,\quad \boldsymbol{w} \in \mathcal{W}\,. \end{align}\]
Where:
- $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
- $\boldsymbol{z}$: Held binary, one entry per asset.
- $\mathbf{A}$: Stored relatedness rows, the
Afield. - $\boldsymbol{B}$: Cap, the
Bfield. - $\boldsymbol{\ell}$, $\boldsymbol{u}$: Lower and upper weight bounds.
- $\phi$: Objective function of the optimiser.
- $\odot$: Hadamard product.
- $\mathcal{W}$: Rest of the feasible set.
The constructor stores unique(A + I; dims = 1), not the matrix it is given. The identity adds each asset to its own row, and the deduplication drops repeated rows, so one row survives per distinct neighbourhood or cluster. This is why the stored A is usually shorter than it is wide, and why a vector B is checked against the stored row count rather than against the number of assets. A network source with B = 1 then forbids holding two assets that are neighbours; a clustering source with B = 1 holds at most one asset per cluster.
Fields
A: Row set of the relatedness matrix, stored asunique(A + I; dims = 1)and not as the matrix passed in. The identity puts each asset in its own row, and the deduplication drops rows that repeat. One row per distinct neighbourhood or cluster survives, which is why the stored matrix is usually shorter than it is wide.
B: Right-hand side ofA * z <= B, wherezis the held indicator: the largest number of assets that may be held out of each row ofA. A scalar applies to every row. A vector states one bound per row, so its length must match the row count of the storedAand not the number of assets. On an estimator the rows do not exist yet, so a vector is only checked against the largest number of clusters the clustering estimator can return.
Constructors
IntegerPhylogeny( A::MatNum_PhRMatNum, B::Int_VecInt) -> IntegerPhylogenyIntegerPhylogeny(; A::MatNum_PhRMatNum, B::Int_VecInt = 1) -> IntegerPhylogenyKeywords correspond to the struct's fields.
Validation
LinearAlgebra.issymmetric(A)andall(iszero, LinearAlgebra.diag(A)).Bis validated withassert_nonempty_nonneg_finite_val.AbstractVector:size(unique(A + LinearAlgebra.I; dims = 1), 1) == length(B).
Examples
julia> IntegerPhylogeny(; A = [0.0 1.0; 1.0 0.0], B = 2)IntegerPhylogeny A ┼ 1×2 Matrix{Float64} B ┴ Int64: 2Related
set_iplg_constraints!mip_constraintsIntegerPhylogenyEstimatorAbstractPhylogenyConstraintResultphylogeny_constraints
References
- [74] F. Ricca and A. Scozzari. Portfolio optimization through a network approach: network assortative mixing and portfolio diversification. European Journal of Operational Research 312, 700–717 (2024).
- [72] D. Cajas. A Graph Theory Approach to Portfolio Optimization. Available at SSRN 4602019 (2023).
- [73] D. Cajas. A Graph Theory Approach to Portfolio Optimization Part II. Available at SSRN 4667426 (2023).
- [4] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Sections 13.1.7.1 and 13.2.4.1.
PortfolioOptimisers.phylogeny_constraints — Function
phylogeny_constraints(plc::Option{<:PlCE_PlC}, X::MatNum; dims::Int = 1, kwargs...)
phylogeny_constraints(plcs::VecPlCE_PlC, args...; kwargs...)Generate phylogeny-based portfolio constraints from an estimator or result.
phylogeny_constraints constructs constraint objects based on phylogenetic, res, or network structures among assets. It supports both semi-definite and integer constraint forms, accepting either an estimator (which wraps a phylogeny or clustering model and penalty parameters) or a precomputed result. If plc is nothing, returns nothing.
If plcs is a vector, this method broadcasts over each element, returning a vector of constraint results.
Arguments
plc: A phylogeny constraint estimator, result, ornothing.X: Data matrix (observations × assets) (ignored whenplcis not an estimator).dims: Dimension along which to perform the computation.kwargs...: Additional keyword arguments passed to the underlying phylogeny matrix routine (ignored whenestis not an estimator).
Returns
res: Constraint result.SemiDefinitePhylogeny: For semi-definite constraint estimators/results.IntegerPhylogeny: For integer constraint estimators/results.nothing: Ifestisnothing.
Related
phylogeny_constraints(
plc::AbstractPhylogenyConstraintEstimator,
pr::Union{AbstractPriorResult, ReturnsResult};
rd,
x_src,
z_src,
kwargs...
) -> Union{IntegerPhylogeny, SemiDefinitePhylogeny{<:AbstractMatrix{var"#s90"}, <:Number} where var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar})}
Compute phylogeny constraints from asset returns in a prior result using a phylogeny constraint estimator.
phylogeny_constraints delegates to the asset-returns variant by extracting X from pr (or rd if provided and x_src is :data).
Arguments
plc: Phylogeny constraint estimator.pr: Prior result or returns result object.rd: Optional returns result (used whenx_src = :dataorz_src = :data).x_src: If:prior, use asset returns frompr; if:data, userd. Default is:prior.z_src: Which carrier supplies the feature matrix aFeatureDistancereads::datatakesrd.Z,:priortakespr.Z. Default is:data. Ignored when noFeatureDistanceis in the estimator.kwargs...: Additional keyword arguments passed to the estimator.
Returns
- Phylogeny constraint result.
Related
PortfolioOptimisers.AbstractCentralityConstraint — Type
abstract type AbstractCentralityConstraint <: AbstractConstraintEstimatorAbstract supertype for all centrality-based constraint types.
All concrete types implementing centrality-based portfolio constraints should be subtypes of AbstractCentralityConstraint.
A subtype states a bound on a linear function of the weights whose coefficients come from a graph, so centrality_constraints reduces it to a LinearConstraint before the model sees it.
Related
PortfolioOptimisers.CentralityConstraint — Type
struct CentralityConstraint{__T_A, __T_B, __T_comp} <: AbstractCentralityConstraintBounds the average centrality of the portfolio against a threshold read off the centrality vector itself.
The constraint diversifies by the influence an asset has in the network, rather than by its weight. centrality_constraints turns it into one row of a LinearConstraint.
Mathematical definition
\[\begin{align} \underset{\boldsymbol{w}}{\mathrm{opt}}\quad & \phi(\boldsymbol{w})\\ \textrm{s.t.}\quad & \boldsymbol{c}^\intercal \boldsymbol{w} \mathbin{\square} \bar{c}\,,\\ & \boldsymbol{w} \in \mathcal{W}\,. \end{align}\]
Where:
- $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
- $\boldsymbol{c}$: Centrality vector the estimator in
Acomputes. - $\bar{c}$: Threshold, the
Bfield. - $\square$: Comparison operator, the
compfield. - $\phi$: Objective function of the optimiser.
- $\mathcal{W}$: Rest of the feasible set.
The source states this constraint as an equality against a desired average centrality. comp widens that: == builds an equality row and every other operator an inequality row.
When B is a VectorToScalarMeasure, $\bar{c}$ is that measure of $\boldsymbol{c}$, so the threshold moves with the graph and the constraint always has a feasible point. The measure reads the centrality vector, never the row after comp has flipped its sign: MinValue() gives the smallest entry under <= and under >= alike. On an eight-asset degree vector both give 0.14285714285714285, and MaxValue() gives 0.42857142857142855.
Fields
A: Centrality estimator. Its centrality vector is the row of the generated linear constraint.
B: Right-hand side of the constraint. A number is the threshold itself. AVectorToScalarMeasurederives the threshold from the centrality vectorAproduces, so the constraint always has a feasible point.
comp: Comparison operator for the centrality constraint.==builds an equality row, every other operator an inequality row.
Constructors
CentralityConstraint(; A::CentralityEstimator = CentralityEstimator(), B::Num_VecToScaM = MinValue(), comp::ComparisonOperator = <=) -> CentralityConstraintKeywords correspond to the struct's fields.
Examples
julia> CentralityConstraint()CentralityConstraint A ┼ CentralityEstimator │ pl ┼ NetworkEstimator │ │ 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) │ │ de ┼ Distance │ │ │ power ┼ nothing │ │ │ alg ┴ CanonicalDistance() │ │ alg ┼ KruskalTree │ │ │ args ┼ Tuple{}: () │ │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ │ sep ┼ HopCount │ │ │ n ┴ Int64: 1 │ ct ┼ DegreeCentrality │ │ kind ┼ Int64: 0 │ │ kwargs ┴ @NamedTuple{}: NamedTuple() B ┼ MinValue() comp ┴ typeof(<=): <=Related
References
PortfolioOptimisers.VecCC — Type
const VecCC = AbstractVector{<:CentralityConstraint}Alias for a vector of CentralityConstraint objects.
Represents a collection of centrality-based portfolio constraints.
Related
PortfolioOptimisers.CC_VecCC — Type
const CC_VecCC = Union{<:CentralityConstraint, <:VecCC}Alias for a single or vector of CentralityConstraint objects.
Matches either a single CentralityConstraint or a vector of them (VecCC).
Related
PortfolioOptimisers.centrality_constraints — Function
centrality_constraints(ccs::CC_VecCC,
X::MatNum; dims::Int = 1, kwargs...)Generate centrality-based linear constraints from one or more CentralityConstraint estimators.
centrality_constraints constructs linear constraints for portfolio optimisation based on asset centrality measures within a phylogeny or network structure. It accepts one or more CentralityConstraint estimators, computes centrality vectors for the given data matrix X, applies the specified reduction measure or threshold, and assembles the resulting constraints into a LinearConstraint object.
Arguments
ccs: A singleCentralityConstraintor a vector of such estimators.X: Data matrix (observations × assets).dims: Dimension along which to perform the computation.kwargs...: Additional keyword arguments passed to the centrality estimator.
Returns
lc::Option{<:LinearConstraint}: An object containing the assembled inequality and equality constraints, ornothingif no constraints are present.
Details
- For each constraint, computes the centrality vector using the estimator in
cc.A. - Derives the threshold from
cc.B. A number is the threshold itself; aVectorToScalarMeasureis applied to the centrality vector. - Negates the row and the threshold together for an operator that points the other way, so every inequality is stored in the
A w <= Bform. - Skips a constraint whose centrality vector is empty or all zero.
- Aggregates constraints into equality and inequality forms.
- Returns
nothingif no valid constraints are generated.
The threshold is derived before the negation, and negated once with the row. Deriving it from the negated row instead negates it a second time, which cancels the flip and turns a MinValue() into a MaxValue() with the wrong sign.
Related
centrality_constraints(ccs::Option{<:LinearConstraint}, args...; kwargs...)No-op fallback for centrality-based constraint propagation.
This method returns the input LinearConstraint object or nothing unchanged. It is used to pass through an already constructed centrality-based constraint object, enabling composability and uniform interface handling in constraint generation workflows.
Arguments
ccs: An existingLinearConstraintobject ornothing.args...: Additional positional arguments (ignored).kwargs...: Additional keyword arguments (ignored).
Returns
ccs::Option{<:LinearConstraint}: The input constraint object ornothing, unchanged.
Related
centrality_constraints(
ccs::Union{CentralityConstraint, AbstractVector{<:CentralityConstraint}},
pr::Union{AbstractPriorResult, ReturnsResult};
rd,
x_src,
z_src,
kwargs...
) -> Union{Nothing, LinearConstraint}
Compute centrality constraints from asset returns in a prior result using a centrality constraint estimator.
centrality_constraints delegates to the asset-returns variant by extracting X from pr (or rd if provided and x_src is :data).
Arguments
ccs: Centrality constraint estimator or vector thereof.pr: Prior result or returns result object.rd: Optional returns result (used whenx_src = :dataorz_src = :data).x_src: If:prior, use asset returns frompr; if:data, userd. Default is:prior.z_src: Which carrier supplies the feature matrix aFeatureDistancereads::datatakesrd.Z,:priortakespr.Z. Default is:data. Ignored when noFeatureDistanceis in the estimator.kwargs...: Additional keyword arguments passed to the estimator.
Returns
- Centrality constraint result.
Related
PortfolioOptimisers.AbstractPhylogenyConstraintEstimator — Type
abstract type AbstractPhylogenyConstraintEstimator <: AbstractConstraintEstimatorAbstract supertype for all phylogeny-based constraint estimators.
All concrete and/or abstract types representing phylogeny-based constraint estimators should be subtypes of AbstractPhylogenyConstraintEstimator.
Related
PortfolioOptimisers.AbstractPhylogenyConstraintResult — Type
abstract type AbstractPhylogenyConstraintResult <: AbstractConstraintResultAbstract supertype for all phylogeny-based constraint result types.
All concrete and/or abstract types representing the results of phylogeny-based constraint generation should be subtypes of AbstractPhylogenyConstraintResult.
Related
PortfolioOptimisers.PlCE_PlC — Type
const PlCE_PlC = Union{<:AbstractPhylogenyConstraintEstimator,
<:AbstractPhylogenyConstraintResult}Alias for a phylogeny constraint estimator or result.
Matches either a AbstractPhylogenyConstraintEstimator or a AbstractPhylogenyConstraintResult. Used internally for dispatch in phylogeny-based constraint generation.
Related
PortfolioOptimisers.VecPlC — Type
const VecPlC = AbstractVector{<:AbstractPhylogenyConstraintResult}Alias for a vector of phylogeny constraint results.
Represents a collection of AbstractPhylogenyConstraintResult objects.
Related
PortfolioOptimisers.PlC_VecPlC — Type
const PlC_VecPlC = Union{<:AbstractPhylogenyConstraintResult, <:VecPlC}Alias for a single or vector of phylogeny constraint results.
Matches either a single AbstractPhylogenyConstraintResult or a vector of them (VecPlC).
Related
PortfolioOptimisers.VecPlCE_PlC — Type
const VecPlCE_PlC = AbstractVector{<:PlCE_PlC}Alias for a vector of phylogeny constraint estimators or results.
Represents a collection of PlCE_PlC objects, enabling batch processing of multiple phylogeny-based constraint estimators or results.
Related
PortfolioOptimisers.PlCE_PhC_VecPlCE_PlC — Type
const PlCE_PhC_VecPlCE_PlC = Union{<:PlCE_PlC, <:VecPlCE_PlC}Alias for a single or vector of phylogeny constraint estimators or results.
Matches either a single PlCE_PlC or a vector of them (VecPlCE_PlC). Used internally for dispatch on phylogeny-based constraint generation that accepts one or many constraints.
Related
PortfolioOptimisers.MatNum_PhRMatNum — Type
const MatNum_PhRMatNum = Union{<:PhylogenyResult{<:MatNum}, <:MatNum}Alias for a phylogeny result wrapping a numeric matrix or a numeric matrix directly.
Used internally to accept either a PhylogenyResult containing a numeric matrix or a plain numeric matrix as a constraint matrix input.
Related
PortfolioOptimisers.Lc_CC_VecCC — Type
const Lc_CC_VecCC = Union{<:CC_VecCC, <:LinearConstraint}Alias for a centrality constraint or linear constraint.
Matches either a CentralityConstraint, a vector of them, or a LinearConstraint. Used for dispatch in centrality-based constraint generation that also accepts linear constraints.
Related
PortfolioOptimisers._validate_length_integer_phylogeny_constraint_B — Function
_validate_length_integer_phylogeny_constraint_B(alg::Option{<:Integer},
B::VecNum)Validate that the length of the vector B does not exceed the integer value alg.
This function is used internally to ensure that the number of groups or allocations specified by B does not exceed the allowed maximum defined by alg. If the validation fails, a DomainError is thrown.
Arguments
alg:Nothing: No validation is performed.Integer: Specifying the maximum allowed length forB.
B: Vector of integers representing group sizes or allocations.
Validation
- Throws
DomainErroriflength(B) > alg.
Returns
nothing.
Details
- Checks that
length(B) <= alg. - Used in the construction and validation of integer phylogeny constraints.
Related
PortfolioOptimisers.validate_length_integer_phylogeny_constraint_B — Function
validate_length_integer_phylogeny_constraint_B(cle::ClustersEstimator, B::VecNum)
validate_length_integer_phylogeny_constraint_B(args...)Validate that the length of the vector B does not exceed the maximum allowed by the clustering estimator cle.
Arguments
cle: Clustering estimator containing algorithm and maximum group information.B: Vector of integers representing group sizes or allocations.args...: No validation is performed.
Validation
- Throws
DomainErroriflength(B) > cle.onc.max_k(whenmax_kis set). - Calls internal
_validate_length_integer_phylogeny_constraint_Bfor further checks.
Returns
nothing.
Details
- Checks if
cle.onc.max_kis set and validateslength(B)accordingly. - Delegates to
_validate_length_integer_phylogeny_constraint_Bfor algorithm-specific validation. - Used in the construction and validation of integer phylogeny constraints.
Related
References
- [4]
- D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025).
- [72]
- D. Cajas. A Graph Theory Approach to Portfolio Optimization. Available at SSRN 4602019 (2023).
- [73]
- D. Cajas. A Graph Theory Approach to Portfolio Optimization Part II. Available at SSRN 4667426 (2023).
- [74]
- F. Ricca and A. Scozzari. Portfolio optimization through a network approach: network assortative mixing and portfolio diversification. European Journal of Operational Research 312, 700–717 (2024).