Base Constraint Generation

PortfolioOptimisers.AbstractConstraintResultType
abstract type AbstractConstraintResult <: AbstractResult

Abstract supertype for all constraint result types.

All concrete and/or abstract types representing the result of constraint generation or evaluation should be subtypes of AbstractConstraintResult.

Interfaces

In order to implement a new constraint result which will work seamlessly with the library, subtype AbstractConstraintResult and hold the assembled constraint in its fields. Both methods below carry a library-wide fallback, so a result the fallback already describes implements neither, and a result the fallback describes wrongly implements one or both.

Routing target

  • PortfolioOptimisers.implicit_constraint_target(res::AbstractConstraintResult) -> Option{Symbol}: The one routing target a result of this type can land in, or nothing when the type names none.

The fallback answers nothing, and add_constraint_result then pairs the value with the target its step declared, in a TargetedConstraint. Implement the method only when the type names exactly one field of a JuMPOptimiser, which is what lets the value be injected bare.

Arguments

  • res: The constraint result.

Returns

Asset view

  • PortfolioOptimisers.port_opt_view(res::AbstractConstraintResult, i, args...) -> AbstractConstraintResult: An asset-sliced copy of the result.

The generic fallback slices an array field along the asset axis, and @propagatable's @vprop tag derives the method for a struct whose fields are all asset-parallel. Write the method by hand when the fallback is wrong for the type. LinearConstraint is the case: its method reads neither the index nor the tail that follows it, and the reason the identity is the right answer there is stated on the method itself.

Arguments

  • res: The constraint result.
  • i: The asset index the view keeps.

Returns

  • res::AbstractConstraintResult: The constraint over the selected assets.

Related

source
PortfolioOptimisers.AbstractConstraintEstimatorType
abstract type AbstractConstraintEstimator <: AbstractEstimator

Abstract supertype for all constraint estimator types.

All concrete and/or abstract types implementing constraint generation or estimation algorithms should be subtypes of AbstractConstraintEstimator.

Interfaces

In order to implement a new constraint family which will work seamlessly with the library, subtype AbstractConstraintEstimator with all necessary parameters as part of the struct, and implement the following methods.

Constraint generation

  • <family>_constraints(ce::AbstractConstraintEstimator, sets::UniverseSets): Assemble the family's constraint over the declared universe.

The family owns the verb, and the library holds one verb per family rather than one shared name: linear_constraints, weight_bounds_constraints, threshold_constraints, risk_budget_constraints, asset_sets_matrix, phylogeny_constraints and centrality_constraints. A family that refits its structure from data takes a ReturnsResult in place of the sets. This is the method a caller reaches directly, and it is the one the pipeline step below delegates to.

Arguments

  • ce: The constraint estimator.
  • sets: The declared universe the names resolve against.

Returns

Pipeline step

Implement both methods, or neither. pipe_constraint_targets falls back to an empty tuple, which declares that the family computes no value for the constraints slot and is therefore not a Pipeline step, and resolve_constraint_target raises on that tuple before the value is ever reached. JuMPConstraintEstimator is the family that takes the fallback: it is configuration for the model rather than a computation over data.

  • PortfolioOptimisers.pipe_constraint_targets(ce::AbstractConstraintEstimator) -> Tuple: The routing targets the family's result can land in. One target places the value with no annotation, several make the PipelineStep wrapper name one.
  • PortfolioOptimisers.constraint_step_value(ce::AbstractConstraintEstimator, ctx::PipelineContext): The value the step contributes, computed by calling the family's own verb above.

pipe_reads and pipe_writes need no method. The family answers (:returns,) and :constraints for every subtype, and a family that reads a computed slot as well states so on its own type.

Arguments

  • ce: The constraint estimator.
  • ctx: The pipeline context.

Returns

  • res: The computed value, nothing, or a vector of either.

Related

source