Exposure Constraints: private API
PortfolioOptimisers.EcE_LcE_Lc — Type
const EcE_LcE_Lc = Union{<:ExposureConstraintEstimator, <:LcE_Lc}Alias for a union of an ExposureConstraintEstimator and the types it decorates.
Related
PortfolioOptimisers.VecEcE_LcE_Lc — Type
abstract type AbstractArray{var"#s1773"<:(Union{var"#s1773", var"#s1772"} where {var"#s1773"<:ExposureConstraintEstimator, var"#s1772"<:(Union{var"#s1773", var"#s1772"} where {var"#s1773"<:LinearConstraintEstimator, var"#s1772"<:LinearConstraint})}), 1}Alias for an abstract vector of EcE_LcE_Lc elements.
Related
PortfolioOptimisers.EcE_LcE_Lc_VecEcE_LcE_Lc — Type
const EcE_LcE_Lc_VecEcE_LcE_Lc = Union{<:EcE_LcE_Lc, <:VecEcE_LcE_Lc}Alias for a union of EcE_LcE_Lc or a vector of them.
This is the widened bound for lcse — the one slot that admits a re-basis. gcarde and sgcarde keep the narrower LcE_Lc-based aliases, which is the enforcement described in ExposureConstraintEstimator.
Related
PortfolioOptimisers.factor_space_regression — Function
factor_space_regression(re::Option{<:RegE_Reg}, rr::Option{<:AbstractLoadingsRegressionResult},
rd::Option{<:ReturnsResult})
-> Option{<:AbstractLoadingsRegressionResult}Apply resolve_factor_regression's precedence to the three carriers a FactorSpace can read its loadings from, and return nothing when none of them holds any.
The precedence is the one FactorRiskContribution already uses — a stated result, then the prior's own rr, then a refit — and the refit arm delegates to resolve_factor_regression rather than repeating it. What differs is the carriers: constraint generation is handed the loadings as rr, already read off the prior, so the prior arm is a plain argument rather than a field read, and both re and rd are optional here because a space that names no source and a route that carries no returns are both ordinary.
Returning nothing rather than throwing is deliberate: the diagnosis for "no basis anywhere" belongs to constraint_space_basis, which knows it is assembling a constraint.
Algorithm
- Return
rewhen it is a precomputedRegression. The caller has stated the basis, and no data is needed. - Otherwise return
rrwhen the prior carries one. This is what are === nothingalways resolves to, and it is the behaviour of everyFactorSpacewritten before the field existed. - Otherwise return
nothingwhenreisnothingtoo. No carrier holds a basis, andconstraint_space_basiswrites the diagnosis. - Otherwise
reis an estimator. Raise whenrdisnothing, and returnresolve_factor_regression(re, rd)when it is not, which refits the loadings from the returns.
Step 4 is a capability the field adds rather than a fallback: FactorSpace(; re = StepwiseRegression()) is a factor mandate on a prior that carries no loadings, which previously threw.
Arguments
re::Option{<:RegE_Reg}: The space's stated basis source, ornothingto readrr.rr::Option{<:AbstractLoadingsRegressionResult}: The prior's loadings, ornothing.rd::Option{<:ReturnsResult}: Returns to refit from, ornothingon the standalone route.
Validation
- An estimator in
rewith nordthrows anIsNothingErrornaming both fixes. The refit needs the returns, so it is available at aJuMPOptimiserand as aPipelinestep, and refused on the standalonelinear_constraintsroute, which receives none.
Returns
rr::Option{<:AbstractLoadingsRegressionResult}: The loadings the highest-ranked carrier holds, ornothingwhen none of the three holds any.
Related
PortfolioOptimisers.project_linear_constraint — Function
project_linear_constraint(lc::LinearConstraint, M::MatNum) -> LinearConstraint
project_linear_constraint(plc::PartialLinearConstraint, M::MatNum) -> PartialLinearConstraintRe-base an already assembled constraint by projecting its coefficient matrix, A * transpose(M).
This is the precomputed-constraint half of the estimator path's per-term projection, and it is the one place linear_constraints stops being a pass-through for a LinearConstraint: a precomputed constraint reaching the optimiser through an ExposureConstraintEstimator was written in the wrapped basis and must still be re-based. The right-hand side is untouched — a change of basis acts on the row, not on the bound.
size(A, 2) == size(M, 2) is checked rather than assumed, because a precomputed constraint carries no names and nothing else would catch an asset-space matrix handed to a FactorSpace wrapper whose asset and factor counts happen to differ.
Algorithm
The PartialLinearConstraint method is the one that computes, and the LinearConstraint method is its fan-out over the two halves.
- Check that
plc.Ahas one column per factor,size(plc.A, 2) == size(M, 2). - Return a
PartialLinearConstraintwhoseAis the re-based coefficient matrix and whoseBisplc.B, taken over unchanged. - For a whole
LinearConstraint, apply steps 1 and 2 toineqand toeq, skipping a half that isnothing, and rebuild the constraint from the two.
Arguments
lc: The assembledLinearConstraint, written over the factors.plc: One half of it, aPartialLinearConstraint.M: The loadings,Na × Nf.
Validation
size(plc.A, 2) == size(M, 2). Otherwise aDimensionMismatchnames both counts.
Returns
lc::LinearConstraintorplc::PartialLinearConstraint: The same shape, over the assets.Ais re-based andBis the input's own.
Related
PortfolioOptimisers.rebase_linear_constraints — Function
rebase_linear_constraints(lce, sets::UniverseSets, basis, key; datatype, strict, bl_flag)Re-base one wrapped shape. Dispatches on what ExposureConstraintEstimator is decorating:
- A
LinearConstraintEstimatorparses and assembles againstkey, projecting each term as it goes. Akey === nothingon the wrapped estimator resolves to the space's key — the factor axis ofrrforFactorSpace— rather than tosets.xkey. - A precomputed
LinearConstraintis projected wholesale byproject_linear_constraint. - A vector is mapped elementwise, matching what
linear_constraintsreturns for a vector of estimators.
Algorithm
The two single-shape methods reach the same row by two routes. The estimator route builds the row term by term, and the precomputed route projects a finished row.
- For a
LinearConstraintEstimator, pick the key:lce.keywhen the wrapped estimator states one, andkeyotherwise. - Call
linear_constraintsonlce.valagainst that key, withbasispassed asrr.constraint_row_termthen sums the selected columns ofbasis.Mfor each named term, which is the projection done one term at a time. - For a precomputed
LinearConstraint, callproject_linear_constrainton it withbasis.M, which projects the assembled coefficient matrix in one product.basis.Mis the only field of the basis either route reads, so the regression's intercept never enters. - For a vector, apply steps 1 to 3 to each element in turn and return the results in the order of the input.
Arguments
lce: The wrapped shape — aLinearConstraintEstimator, aLinearConstraint, or a vector of either.sets: The declared universe the names resolve against.basis: The loadings, asconstraint_space_basisresolved them.key: The key the names resolve against, when the wrapped estimator states none of its own.datatype: Data type of the assembled row.strict: Iftrue, a name the universe does not resolve throws; iffalse, it warns and the term is dropped.bl_flag: Iftrue, enables Black-Litterman-style group expansion.
Returns
lc: An asset-spaceLinearConstraint,nothingwhen every row was dropped, or a vector of either in the order oflce.
Related
ExposureConstraintEstimatorproject_linear_constraintconstraint_row_term: the per-term half of the projection, which the estimator route reaches throughlinear_constraints.