Pipe routing: private API
PortfolioOptimisers.pipe_route — Function
pipe_route(x, ::Val{target}, v)Absorb a Routing Target's value into an optimiser, returning the rebuilt optimiser.
This is the optimiser-owned half of the Pipeline seam: inject_context fans a PipelineContext slot out into routing targets and delivers each one here, knowing nothing about where it lands.
Targets are named after the field they land in — :pe, :cle, :wb, :lcse, :ple — because those names are this package's shared vocabulary (see field_dict) rather than any one optimiser's private layout. The default method therefore is the routing rule: a target lands in the like-named field of any optimiser that has one. Nothing is declared per type, so nothing can drift.
Two targets are exceptions, because they carry validation policy and name no plain field: :mu_ucs (requires an ArithmeticReturn, lands in ret.ucs) and :sigma_ucs (lands in the UncertaintySetVariance measures of r, see @pipe_route_sigma_ucs).
Optimisers holding their configuration in a field rather than carrying the target fields themselves declare @pipe_delegates.
The lookup is hasfield rather than hasproperty, because routing rebuilds the object through the field: a name reachable only as a forwarded property could be read but not set.
A target with no home falls through to unroutable_target, which ignores the optional ones and throws for the rest.
Internal machinery — not part of the user-facing API.
Arguments
x: The optimiser or optimiser configuration.::Val{target}: One ofPIPELINE_ROUTING_TARGETS.v: The computed result to absorb.
Returns
x′: The rebuilt optimiser.
Related
pipe_route(cfg::JuMPOptimiser, _::Val{:mu_ucs}, v) -> Any
Route a mean uncertainty set into a JuMPOptimiser's return estimator.
One of the two Routing Targets that names no plain field: the set lands in ret.ucs, and only an ArithmeticReturn can bound expected returns, so any other return estimator is an error rather than a silent drop.
A vector of return terms is refused for the same reason, from the other side: one set is a neighbourhood of one quantity, so broadcasting it across k terms would apply a ball fitted on one fit to every other one. Name the set on the term it belongs to instead.
Internal machinery — not part of the user-facing API.
Related
PortfolioOptimisers.pipe_accepts — Function
pipe_accepts(x, ::Val{target}) -> BoolWhether a Routing Target has a home in x.
For the field-named targets this is exactly hasfield — the same fact pipe_route dispatches on, so acceptance and routing cannot disagree. The :mu_ucs/:sigma_ucs exceptions and the @pipe_delegates forwarders override it.
Internal machinery — not part of the user-facing API.
Related
PortfolioOptimisers.pipe_config_field — Function
pipe_config_field(x) -> Union{Nothing, Symbol}The field holding x's optimiser configuration, or nothing if it has none.
Declared by @pipe_delegates rather than probed, so an estimator whose opt field holds an inner estimator — SubsetResampling — is never mistaken for one holding a JuMPOptimiser configuration.
Internal machinery — not part of the user-facing API.
Related
PortfolioOptimisers.@pipe_delegates — Macro
@pipe_delegates T fieldDeclare that optimiser type T forwards every Routing Target to the configuration held in field.
Emits pipe_config_field plus forwarding pipe_route and pipe_accepts methods. Targets the configuration has no home for reach its own unroutable_target, so the resulting error names the configuration — matching the pre-inversion messages.
A type that absorbs a target itself rather than through its configuration declares that target on the concrete type (see @pipe_route_sigma_ucs), which out-specialises this forwarder.
Examples
@pipe_delegates MeanRisk optRelated
PortfolioOptimisers.route_sigma_ucs — Function
route_sigma_ucs(x, sig::AbstractUncertaintySetResult) -> Any
Route a covariance uncertainty set into the UncertaintySetVariance risk measure(s) held in an optimiser's r field.
Each UncertaintySetVariance found — directly or inside a vector — has its ucs replaced with sig. An r field carrying no such measure is an error rather than a silent no-op: a computed uncertainty set that reaches no risk measure would be dropped.
Internal machinery — not part of the user-facing API.
Arguments
x: The optimiser, which must carry anrfield.sig: The covariance uncertainty set result.
Returns
x′: The rebuilt optimiser.
Related
PortfolioOptimisers.@pipe_route_sigma_ucs — Macro
@pipe_route_sigma_ucs TDeclare that optimiser type T absorbs the :sigma_ucs Routing Target into its own r field via route_sigma_ucs.
Declared per concrete type rather than on a supertype: the covariance uncertainty set lands in the estimator's risk measures while every other target is forwarded to its configuration, so this method must out-specialise the @pipe_delegates forwarder on the same type. It is opt-in because carrying a configuration does not imply carrying risk measures — RelaxedRiskBudgeting has no r field.
Related
PortfolioOptimisers.@pipe_route_rkb — Macro
@pipe_route_rkb TDeclare that optimiser type T absorbs the :rkb Routing Target into the rkb field of its risk-budgeting algorithm.
:rkb is the one target named after a field an optimiser does not carry directly. A risk budget belongs to the algorithm — AssetRiskBudgeting budgets assets, FactorRiskBudgeting budgets factors — so it lands one level down, at rba.rkb, and the derived hasfield rule cannot reach it.
Acceptance is not a constant: it asks the algorithm the optimiser is actually carrying. A TimeDependent schedule in rba has no rkb to write, so such an optimiser declines the target and a pipeline computing a budget for it is refused at construction rather than failing in the fold loop.
Declared per concrete type, for the same reason as @pipe_route_sigma_ucs: it must out-specialise the @pipe_delegates forwarder on the same type.
Related