Base Prior

PortfolioOptimisers.LowOrderPriorType
struct LowOrderPrior{__T_X, __T_o_X, __T_mu, __T_sigma, __T_chol, __T_w, __T_ens, __T_kld, __T_ow, __T_rr, __T_fpr, __T_Z} <: AbstractPriorResult

Carries the returns, mean and covariance a low order prior estimator produced.

LowOrderPrior stores the output of low order prior estimation routines, including asset returns, mean vector, covariance matrix, Cholesky factor, weights, entropy, Kullback-Leibler divergence, outlier weights, regression results, and optional factor moments. It is used throughout the package to represent validated prior information for portfolio optimisation and analytics.

Fields

  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • o_X: The returns matrix the caller supplied, kept only when the carrier's own X is not it, and nothing otherwise. The three estimators that lift a factor-axis prior onto the asset axis overwrite X with the reconstruction F * transpose(M) .+ transpose(b); o_X is the asset returns they were handed, over the same observations and the same assets. Read it as original_X, which is always a matrix, rather than as this field.
  • mu: Expected returns vector assets × 1.
  • sigma: Covariance matrix assets × assets.
  • chol: Cholesky factorisation of the covariance matrix.
  • w: Observation weights the prior was computed under observations × 1 (see ObsWeights), or nothing if it was computed unweighted. Binds ens, kld and ow, which are diagnostics of it (see forward_prior).
  • ens: Effective sample size.
  • kld: Kullback-Leibler divergence of w from the weights it was derived from: a scalar against the prior observation weights for a single reweighting, or one entry per opinion when w came from pooling several.
  • ow: Opinion pooling weights.
  • rr: Regression result.
  • fpr: Prior result over the factor axis, or nothing. Its X is the factor returns matrix, so its mu, sigma and w describe factors rather than assets, over the same observations as the asset block.
  • Z: Derived feature matrix, canonically assets-major: assets × features when static, observations × assets × features when time-varying. Nameless — feature names live on the ReturnsResult or come from a UniverseSets. Populated only by a producer that declares the matrix to be features; a user's rd.Z never reaches a prior result.

Constructors

LowOrderPrior(;    X::MatNum,    o_X::Option{<:MatNum} = nothing,    mu::VecNum,    sigma::MatNum,    chol::Option{<:MatNum} = nothing,    w::Option{<:ObsWeights} = nothing,    ens::Option{<:Number} = nothing,    kld::Option{<:Num_VecNum} = nothing,    ow::Option{<:VecNum} = nothing,    rr::Option{<:Regression} = nothing,    fpr::Option{<:LowOrderPrior} = nothing,    Z::Option{<:MatNum_Arr3Num} = nothing) -> LowOrderPrior

Keywords correspond to the struct's fields.

The factor block

A prior fit through a factor model carries two distributions: one over the assets, in the carrier's own fields, and one over the factors. The factor one is a nested LowOrderPrior in fpr rather than a set of f_-prefixed flat fields, so it gains every field the carrier has — w, ens, kld and ow as well as mu and sigma — and gains any field added in future without a second edit. Its X is the factor returns matrix, over the same observations as the asset X; fpr.Z is therefore factors × features, which is why an asset-axis Z never comes from it.

fpr travels with rr: the two are the factor block, and the constructor requires them together or not at all. rr is what projects the block onto the assets (mu ≈ rr.M * fpr.mu + rr.b), so a factor distribution with no loadings could not be read against this asset axis.

The flat names are virtual reads of the nested block, so code written against the old shape is unaffected: pr.f_mu, pr.f_sigma and pr.f_w return fpr.mu, fpr.sigma and fpr.w, or nothing when there is no factor block, and pr.f_ens, pr.f_kld and pr.f_ow come with them. They are properties, not fields — forward_prior and prior_field_values see only fpr.

Which read is idiomatic

pr.fpr.mu is the public read; the flat f_-prefixed names are a compatibility surface, kept so that code written against the pre-nesting shape keeps working, and useful where a value-or-nothing read without branching is wanted.

The reason is not taste. The flat surface is partial and frozen: there are six flat names over twelve fields, so fpr.X — the factor returns matrix — and fpr.Z, fpr.chol and fpr.rr have no flat spelling at all and never will. A surface that cannot express the whole block cannot be the way to read it. The set is fixed at the six here and the seven on HighOrderPrior; a field added to a carrier in future is reachable as pr.fpr.<name> and gains no f_ counterpart, so nothing has to be added in two places to stay complete.

The two reads also differ where the block is absent, which is the one case worth checking before choosing: pr.f_mu returns nothing, while pr.fpr.mu throws, because fpr is nothing. Guard with assert_prior_regressionrr and fpr are supplied together or not at all, so checking rr establishes the whole block — and then read through fpr.

Composition: what a wrapping estimator forwards

Most prior estimators wrap another and return a carrier built from the one they were handed. Which fields survive that hop is governed by a single rule, recorded in ADR 0046 and enforced by forward_prior:

Forward when forwarding is correct; drop only where forwarding would state something false; document every drop in the estimator's docstring.

Consistency of the returned result is the criterion, and destroying a value the caller explicitly computed is not an acceptable way to buy it — so forwarding is the default, and each estimator's docstring lists the fields it drops and why. Two fields are bound to another and therefore never forwarded alone: chol is bound to sigma (it takes precedence over sigma at every consumer, so a stale factor is silently used in place of the updated covariance), and ens, kld and ow are bound to w (they are diagnostics of those weights). forward_prior refuses a forward that would break either binding.

The feature matrix

Z is derived only: it is populated by a producer that declares a matrix to be features — FeaturePrior — and never by pass-through of a user's ReturnsResult.Z. That is what keeps the two carriers from disagreeing: they cannot both hold the same matrix, so z_src selects a provenance rather than one of two copies.

It carries no feature names. A producer runs inside prior(pe, X, F; …) with raw matrices, so names are structurally unavailable there — and it carries no squareness flag either: the prior carrier has no vocabulary for "the features are the assets", because every producer that builds a square feature matrix refits on the subproblem's own universe rather than having a full-universe matrix sliced. Exogenous square structure travels on the data carrier, where squareness is derived from nz against nx and therefore cannot be stated wrongly.

Every prior estimator that wraps another forwards it, so nesting order does not matter: BlackLittermanPrior(; pe = FeaturePrior(…)) and FeaturePrior(; pe = BlackLittermanPrior(…)) both arrive with Z set. This is unconditionally safe because no prior estimator changes the asset set or the observation count. The exceptions are the estimators whose wrapped prior is fit on factors rather than assets — FactorPrior, FactorBlackLittermanPrior, and the factor half of AugmentedBlackLittermanPrior — which drop it, because a factor-space feature matrix does not describe the asset axis.

FactorPrior, FactorBlackLittermanPrior and AugmentedBlackLittermanPrior reconstruct X as F * transpose(M) .+ transpose(b), so a Z forwarded through them is dimension-correct but was derived from the pre-reconstruction returns.

The original returns matrix

Those same three estimators are the reason o_X exists. They overwrite X, so on their carriers X is a posterior matrix — the asset distribution this prior asserts — and not the returns the caller supplied. o_X holds the returns the caller supplied. It is nothing everywhere else, where X already is them.

The two matrices are not interchangeable. The reconstruction spans only the factors: it has rank size(F, 2), and the residual is absent. A consumer that refits a moment on the sample must therefore read the original, or it gets a singular matrix whenever there are more assets than factors.

Read it as original_X, never as o_X. The property is always a matrix — the field where there is one, X where there is not — so a consumer needs no fallback and cannot forget one. The field is storage, and it answers a different question: isnothing(pr.o_X) is how to ask whether this carrier reconstructed X. The field carries the state rather than the property carrying it, because forward_prior rebuilds through the keyword constructor with every field named, and a nothing is inert there where an always-populated matrix would go stale past a change to X.

o_X requires rr. Every estimator that overwrites X today does so by projecting a factor prior through regression loadings, so a carrier claiming a reconstruction it cannot explain is a bug. This is a present-tense constraint rather than a law of the domain: see the amendment to ADR 0046.

Validation

  • X, mu, and sigma must be non-empty.
  • size(sigma, 1) == size(sigma, 2).
  • size(X, 2) == length(mu) == size(sigma, 1).
  • If w is not nothing, !isempty(w) and length(w) == size(X, 1).
  • If kld is an AbstractVector, !isempty(kld).
  • If ow is not nothing, !isempty(ow).
  • rr and fpr must be provided together or not at all.
  • If the factor block is present, size(rr.M, 2) == length(fpr.mu) == size(fpr.sigma, 1), size(rr.M, 1) == length(mu), and size(fpr.X, 1) == size(X, 1) — the two blocks describe the same observations. Everything internal to the factor block, including its own w against its own X, is validated by its own constructor.
  • If o_X is not nothing, o_X !== X, size(o_X) == size(X), and rr is not nothing.
  • If chol is not nothing, !isempty(chol) and length(mu) == size(chol, 2).
  • If Z is not nothing, it is non-empty, all-finite, and assets-major against X: size(Z, 1) == size(X, 2) when static, size(Z, 1) == size(X, 1) and size(Z, 2) == size(X, 2) when time-varying (see check_feature_matrix).

Examples

julia> LowOrderPrior(; X = [0.01 0.02; 0.03 0.04], mu = [0.02, 0.03],                     sigma = [0.0001 0.0002; 0.0002 0.0003])LowOrderPrior      X ┼ 2×2 Matrix{Float64}    o_X ┼ nothing     mu ┼ Vector{Float64}: [0.02, 0.03]  sigma ┼ 2×2 Matrix{Float64}   chol ┼ nothing      w ┼ nothing    ens ┼ nothing    kld ┼ nothing     ow ┼ nothing     rr ┼ nothing    fpr ┼ nothing      Z ┴ nothing

Related

source
PortfolioOptimisers.HighOrderPriorType
struct HighOrderPrior{__T_pr, __T_kt, __T_D2, __T_L2, __T_S2, __T_sk, __T_V, __T_skmp, __T_fpr} <: AbstractPriorResult

Carries the coskewness and cokurtosis a high order prior estimator produced, over the low order prior it wraps.

HighOrderPrior stores the output of high order prior estimation routines, including low order prior results, cokurtosis tensor, elimination and summation matrices, coskewness tensor, quadratic skewness matrix, and matrix processing estimator. It is used throughout the package to represent validated prior information for portfolio optimisation and analytics involving higher moments.

Fields

  • pr: Prior result.
  • kt: Cokurtosis matrix assets^2 × assets^2.
  • D2: Duplication matrix.
  • L2: Elimination matrix.
  • S2: Summation matrix.
  • sk: Coskewness matrix assets × assets^2.
  • V: Sum of the negative spectral slices of the coskewness matrix assets × assets.
  • skmp: Coskewness matrix processing estimator.
  • fpr: Prior result over the factor axis, or nothing. Its X is the factor returns matrix, so its mu, sigma and w describe factors rather than assets, over the same observations as the asset block.

Constructors

HighOrderPrior(;    pr::AbstractPriorResult,    kt::Option{<:MatNum} = nothing,    D2::Option{<:MatNum} = nothing,    L2::Option{<:MatNum} = nothing,    S2::Option{<:MatNum} = nothing,    sk::Option{<:MatNum} = nothing,    V::Option{<:MatNum} = nothing,    skmp::Option{<:AbstractMatrixProcessingEstimator} = nothing,    fpr::Option{<:HighOrderPrior} = nothing) -> HighOrderPrior

Keywords correspond to the struct's fields.

The factor block

A high order prior fit through a factor model carries factor co-moments alongside the asset ones. They are a nested HighOrderPrior in fpr rather than the f_-prefixed flat fields f_kt, f_sk and f_V, so the factor block gains every field the carrier has — D2, L2, S2 and skmp as well as kt, sk and V — and gains any field added in future without a second edit. The flat names remain readable as virtual reads of it: pr.f_kt, pr.f_sk and pr.f_V return fpr.kt, fpr.sk and fpr.V, or nothing when there is no factor block, and pr.f_D2, pr.f_L2, pr.f_S2 and pr.f_skmp come with them.

fpr.pr is the factor block one order down: the LowOrderPrior over the factors. The same distribution is also reachable as pr.pr.fpr, the low order carrier's own factor block, and the constructor enforces that the two are the same object — see the validation below.

fpr is this carrier's own field, so it resolves ahead of the forward(pr) block and names the high order factor block, where before nesting it resolved through to the low order one. Reads through it are unaffected by that shift: the nested carrier forwards to its own pr, which the invariant pins to pr.fpr, so hop.fpr.mu is the factor mean either way and hop.fpr is simply "the factor prior at this order".

Which read is idiomatic

pr.fpr.kt is the public read, on the same terms as on LowOrderPrior — see the fuller reasoning there. The seven flat names here are a frozen compatibility surface: f_kt, f_sk, f_V, f_D2, f_L2, f_S2 and f_skmp, and no more will be added. A field added to this carrier in future is reachable as pr.fpr.<name> and gains no f_ counterpart.

As there, the two reads differ where the block is absent — pr.f_kt returns nothing, pr.fpr.kt throws — so guard first and then read through fpr.

Validation

Defining N = length(pr.mu).

  • If any of kt, L2, or S2 are provided, all must be provided, non-empty, and size(kt) == (N^2, N^2), size(L2) == size(S2) == (div(N * (N + 1), 2), N^2).
  • If sk or V are provided, both must be provided, non-empty, and size(sk) == (N, N^2), size(V) == (N, N).
  • If that first triple is provided and sk is too, D2 must be provided, non-empty, and size(D2) == size(transpose(L2)). D2 carries no other rule: it is the one moment field the constructor accepts on its own, and a carrier holding it alone is legal.
  • If fpr is provided, pr.fpr must be provided and fpr.pr === pr.fpr — the factor distribution the factor co-moments were computed against is the low order carrier's own factor block, not a second copy of it. The converse does not hold: a low order factor block with no factor co-moments is ordinary, so fpr === nothing is always allowed. Everything internal to the factor block, including its own shapes against its own N, is validated by its own constructor.

Examples

julia> HighOrderPrior(;                      pr = LowOrderPrior(; X = [0.01 0.02; 0.03 0.04], mu = [0.02, 0.03],                                         sigma = [0.0001 0.0002; 0.0002 0.0003]), kt = rand(4, 4),                      D2 = PortfolioOptimisers.duplication_matrix(2),                      L2 = PortfolioOptimisers.elimination_matrix(2),                      S2 = PortfolioOptimisers.summation_matrix(2), sk = rand(2, 4),                      V = rand(2, 2))HighOrderPrior    pr ┼ LowOrderPrior       │       X ┼ 2×2 Matrix{Float64}       │     o_X ┼ nothing       │      mu ┼ Vector{Float64}: [0.02, 0.03]       │   sigma ┼ 2×2 Matrix{Float64}       │    chol ┼ nothing       │       w ┼ nothing       │     ens ┼ nothing       │     kld ┼ nothing       │      ow ┼ nothing       │      rr ┼ nothing       │     fpr ┼ nothing       │       Z ┴ nothing    kt ┼ 4×4 Matrix{Float64}    D2 ┼ 4×3 SparseArrays.SparseMatrixCSC{Int64, Int64}    L2 ┼ 3×4 SparseArrays.SparseMatrixCSC{Int64, Int64}    S2 ┼ 3×4 SparseArrays.SparseMatrixCSC{Int64, Int64}    sk ┼ 2×4 Matrix{Float64}     V ┼ 2×2 Matrix{Float64}  skmp ┼ nothing   fpr ┴ nothing

Related

source
PortfolioOptimisers.priorMethod
prior(pr::AbstractPriorEstimator, rd::ReturnsResult; kwargs...)

Compute prior information from asset and/or factor returns using a prior estimator.

prior applies the specified prior estimator to a ReturnsResult object, extracting asset and factor returns and passing them, along with any additional information, to the estimator. Returns a prior result containing computed moments and other prior information for use in portfolio optimisation workflows.

Arguments

  • pr: Prior estimator.
  • rd: Asset and/or factor returns result.
  • kwargs...: Additional keyword arguments passed to the estimator.

Returns

  • pr::AbstractPriorResult: Result object containing computed prior information.

Related

source
PortfolioOptimisers.priorMethod
prior(pr::AbstractPriorResult, args...; kwargs...)

Propagate or pass through prior result objects.

prior returns the input prior result object unchanged. This method is used to propagate already constructed prior results or enable uniform interface handling in workflows that accept either estimators or results.

Arguments

  • pr: Prior result object.
  • args...: Additional positional arguments (ignored).
  • kwargs...: Additional keyword arguments (ignored).

Returns

  • pr::AbstractPriorResult: The input prior result object, unchanged.

Related

source
PortfolioOptimisers.assert_prior_regressionFunction
assert_prior_regression(pr::AbstractPriorResult; ...)
assert_prior_regression(
    pr::AbstractPriorResult,
    sym::Union{AbstractString, Symbol};
    lead
)

Assert that a prior result carries a factor block, so its loadings can be read.

Estimators whose pe field is typed AbstractLowOrderPriorEstimator_F_AF accept the AbstractLowOrderPriorEstimator_AF half of that union, whose members use factor returns only optionally. The type therefore constrains which returns an estimator consumes, not whether the result it produces carries a regression. An estimator that projects factor moments through the loadings needs the latter, and must check for it.

There is one way to arrive with pr.rr === nothing: nothing in the chain ever computed a regression (EntropyPoolingPrior(; pe = EmpiricalPrior())). Discarding one is no longer possible — every wrapping estimator forwards rr and the factor block fpr under ADR 0046, so nesting order does not matter. Checking rr covers the whole factor block, because LowOrderPrior already requires rr and fpr to be provided together or not at all — which is why the plotting entry points that want fpr.mu or fpr.sigma check rr here rather than testing the virtual read they are about to take.

Estimators are not the only consumer: the factor-space plotting entry points need the same block, and get the same diagnosis. Only the opening sentence differs, so lead carries it and prior_regression_remedy carries the rest.

Arguments

  • pr: Prior result handed to the consumer.
  • sym: Name of the field or argument the result arrived through, used in the error message.
  • lead: Opening sentence naming what needed the loadings and what it found instead. Defaults to the wrapping-estimator case; a consumer that is not an estimator must supply its own, because the default's claim about the type not guaranteeing a regression is an estimator-field claim.

Validation

  • !isnothing(pr.rr).

Related

source
PortfolioOptimisers.prior_regression_remedyConstant
prior_regression_remedy

The cause-and-remedy half of every "this prior carries no factor block" message, written once so the two kinds of consumer cannot drift apart on it.

Consumers differ in what they wanted the loadings for — projecting factor moments through them, or drawing them — so each supplies its own opening sentence via assert_prior_regression's lead. What none of them may restate is the diagnosis: there is exactly one way to arrive with rr === nothing, and exactly one remedy, and both are consequences of ADR 0046 rather than of the consumer.

Related

source
PortfolioOptimisers.forward_priorFunction
forward_prior(
    pr::AbstractPriorResult;
    overrides...
) -> AbstractPriorResult

Forward a wrapped prior result, spelling out only what the wrapping estimator changes or drops.

This is the mechanical half of the composition rule recorded in ADR 0046:

Forward when forwarding is correct; drop only where forwarding would state something false; document every drop in the estimator's docstring.

Forwarding is the default and costs nothing to write, so a wrapper cannot accidentally return a narrower result than the one it wraps. Every deviation is spelled at the call site — a new value as field = value, a drop as field = nothing — which makes the set of drops greppable and reviewable instead of implicit in a hand-written constructor call listing all thirteen fields.

Reconstruction goes through the carrier's ordinary keyword constructor (see reconstruct_prior), so every @argcheck runs: a forward that leaves the carrier internally inconsistent throws exactly as a hand-written constructor call would. Only the carrier's own fields may be named — a forwarded or computed property is a view of a nested value, so setting it could only ever mean setting the field that value came from.

The three enforced bindings

Three fields are bound to another field's value rather than being independent, so forwarding them past a change to the field they describe is what the rule calls stating something false. Because the binding is mechanical, the helper enforces it rather than leaving it to reviewer memory — naming the field on the left obliges the caller to name the fields on the right, either with a rebuilt value or with nothing:

  • sigma binds chol. chol takes precedence over sigma at every consumer, so a stale chol makes the optimisation silently ignore the posterior covariance.
  • w binds ens, kld and ow. Those are diagnostics of w; weights carrying another weighting's provenance cannot be interrogated.
  • rr binds o_X. o_X says X is a reconstruction, and rr is what records the projection that produced it, so the carrier refuses one without the other. Dropping the factor block therefore drops the original with it.

A binding is inert when the bound field is already nothing (there is nothing stale to carry) or absent from the carrier.

Everything else the constructor already covers: rr and fpr must be supplied together or not at all, and w, chol and Z are re-checked against the shape of X and mu.

What does not fit

The estimators that lift a factor-axis prior into an asset-axis result (FactorPrior, FactorBlackLittermanPrior) and the one that merges two priors (AugmentedBlackLittermanPrior) are not forwarding a single wrapped result along its own axis, so they construct their carrier directly and should not be forced through this helper. forward_prior still applies to the factor block they build, which is an ordinary forward of the factor prior.

Arguments

  • pr: Prior result produced by the wrapped estimator.
  • overrides...: Field overrides; a value to replace, or nothing to drop.

Validation

  • Naming sigma requires naming chol, unless pr.chol is already nothing.
  • Naming w requires naming each of ens, kld and ow that is not already nothing.
  • Naming rr requires naming o_X, unless pr.o_X is already nothing.
  • Every name in overrides is a field of typeof(pr).
  • Every @argcheck of the constructor of typeof(pr).

Returns

  • pr::AbstractPriorResult: The wrapped result with overrides applied, or pr itself when there are none.

Examples

julia> pr = LowOrderPrior(; X = [0.01 0.02; 0.03 0.04], mu = [0.02, 0.03],                          sigma = [0.0004 0.0002; 0.0002 0.0003], chol = [0.02 0.01; 0.0 0.01415]);julia> PortfolioOptimisers.forward_prior(pr) === prtruejulia> pr2 = PortfolioOptimisers.forward_prior(pr; mu = [0.05, 0.06], chol = nothing);julia> (pr2.mu, pr2.chol, pr2.sigma === pr.sigma)([0.05, 0.06], nothing, true)julia> PortfolioOptimisers.forward_prior(pr; sigma = [0.0009 0.0001; 0.0001 0.0004])ERROR: ConflictingArgumentError: forwarding `chol` past a change to `sigma` would state something false: `chol` takes precedence over `sigma` at every consumer, so a stale factor makes the optimisation silently ignore the updated covariance. Pass `chol = nothing` to drop it, or a factor rebuilt from the new `sigma`.[...]

Related

source
PortfolioOptimisers.reconstruct_priorFunction
reconstruct_prior(
    pr::LowOrderPrior,
    patch::NamedTuple
) -> LowOrderPrior{var"#s179", _A, var"#s1791", <:AbstractMatrix{var"#s90"}} where {var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar}), var"#s179"<:AbstractMatrix{var"#s90"}, _A, var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar}), var"#s1791"<:AbstractVector{var"#s90"}, var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar})}

Rebuild a prior result through its ordinary keyword constructor, patching the fields named in patch.

One method per carrier, because the carrier's constructor is named here rather than recovered by reflection. Recovering it generically would mean either Base.typename(T).wrapper or a dependency on ConstructionBase, and neither buys anything: the field list is already derived, via prior_field_values, so a carrier that gains a field needs no edit here. Only a new carrier type needs a method — and until it has one it gets a MethodError naming this function, rather than being reconstructed by machinery that has never seen it.

Reconstruction runs the carrier's full validation, which is the point of routing through the constructor at all: a patch that leaves the carrier internally inconsistent throws exactly as a hand-written constructor call would. Keyword arguments are order-independent, so patch may name fields in any order.

These methods are defined here, after both carriers, because they dispatch on the concrete types.

Arguments

  • pr: Prior result to rebuild.
  • patch: Named tuple of field overrides. Every name must be a field of typeof(pr)forward_prior checks that before calling, so a bad name is reported against the rule rather than as an unsupported keyword.

Returns

  • pr::AbstractPriorResult: Reconstructed result of the same carrier type.

Related

source
PortfolioOptimisers.prior_field_valuesFunction
prior_field_values(pr::AbstractPriorResult) -> NamedTuple

Return a prior result's own fields as a named tuple, keyed in declaration order.

Reads through getfield, so it sees only what the carrier stores — never a name a @forward_properties block exposes on top. That is the distinction forward_prior needs: HighOrderPrior forwards the whole of its pr, so mu and sigma are properties of it without being fields, and only a field can be patched. The field list is derived rather than written out, so adding a field to a carrier does not need an edit here.

Related

source
PortfolioOptimisers.prior_result_property_poolFunction
prior_result_property_pool() -> Vector{Symbol}

Return every property name a prior result can answer, unioned over the carriers.

This is the candidate pool propagatable_contract_violations checks an @pprop field name against: the generated factory(x, pr::AbstractPriorResult, args...) reads getproperty(pr, :field), and the carrier that arrives is not known at the declaration.

The names of the two carriers are written out, as in reconstruct_prior; their fields are derived, so a carrier that gains a field needs no edit here. HighOrderPrior forwards the whole of the pr it wraps, so the low-order names are properties of it too without being fields — that forwarding is the reason a plain fieldnames of one carrier is not the pool.

These methods are defined here, after both carriers, because they name the concrete types.

Related

source
PortfolioOptimisers.bound_field_is_staleFunction
bound_field_is_stale(
    pr::AbstractPriorResult,
    sym::Symbol
) -> Bool

Return true when field sym of pr holds a value that would go stale if the field it is bound to changed without it.

A field that the carrier does not have, or holds as nothing, has nothing to go stale. Reads through getfield so a forwarded property of the same name cannot answer for a field the carrier does not own.

Related

source
PortfolioOptimisers.returns_matrix_pickerFunction
returns_matrix_picker(
    pr::Union{AbstractPriorResult, ReturnsResult},
    rd::Union{Nothing, ReturnsResult},
    x_src::Symbol
) -> Any

Pick the returns matrix the clustering, phylogeny and centrality estimators read.

Two carriers can supply asset returns: the prior result and the raw returns result. x_src names which one wins — :prior takes pr.X, :data takes rd.X. When no returns result is available there is nothing to select between, so pr.X is used and x_src is inert.

Arguments

  • pr: Prior result or returns result object.
  • rd: Optional returns result.
  • x_src: Source selector, :prior or :data.

Validation

  • x_src in (:prior, :data).

Returns

  • X::MatNum: Asset returns matrix from the selected carrier.

Related

source
PortfolioOptimisers.clusteriseMethod
clusterise(cle::AbstractClustersEstimator, pr::AbstractPriorResult; kwargs...)

Clusterise asset or factor returns from a prior result using a clustering estimator.

clusterise applies the specified clustering estimator to the asset returns matrix contained in the prior result object, producing a clustering result for use in phylogeny analysis, constraint generation, or portfolio construction.

Arguments

  • cle: Clustering estimator.
  • pr: Prior result object.
  • kwargs...: Additional keyword arguments passed to the clustering estimator.

Returns

  • clr::AbstractClusteringResult: Result object containing clustering information.

Related

source
PortfolioOptimisers.AbstractPriorEstimatorType
abstract type AbstractPriorEstimator <: AbstractEstimator

Abstract supertype for all prior estimators.

AbstractPriorEstimator is the base type for all estimators that compute prior information from asset and/or factor returns. All concrete prior estimators should subtype this type to ensure a consistent interface for prior computation and integration with portfolio optimisation workflows.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimatorType
abstract type AbstractLowOrderPriorEstimator <: AbstractPriorEstimator

Abstract supertype for low order prior estimators.

AbstractLowOrderPriorEstimator is the base type for estimators that compute low order moments (mean and covariance) from asset and/or factor returns. All concrete low order prior estimators should subtype this type for consistent moment estimation and integration.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimator_AType
abstract type AbstractLowOrderPriorEstimator_A <: AbstractLowOrderPriorEstimator

Low order prior estimator using only asset returns.

AbstractLowOrderPriorEstimator_A is the base type for estimators that compute low order moments (mean and covariance) using only asset returns data. All concrete asset-only prior estimators should subtype this type.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimator_FType
abstract type AbstractLowOrderPriorEstimator_F <: AbstractLowOrderPriorEstimator

Low order prior estimator using factor returns.

AbstractLowOrderPriorEstimator_F is the base type for estimators that compute low order moments (mean and covariance) requiring the use of both asset and factor returns data. All concrete factor-adjusted prior estimators should subtype this type.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimator_AFType
abstract type AbstractLowOrderPriorEstimator_AF <: AbstractLowOrderPriorEstimator

Low order prior estimator using both asset and factor returns.

AbstractLowOrderPriorEstimator_AF is the base type for estimators that compute low order moments (mean and covariance) using both asset and optionally factor returns data. All concrete prior estimators which may optionally use factor returns should subtype this type.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimator_A_AFType
const AbstractLowOrderPriorEstimator_A_AF = Union{<:AbstractLowOrderPriorEstimator_A,
                                                  <:AbstractLowOrderPriorEstimator_AF}

Union type for asset-only and asset-and-factor low order prior estimators.

AbstractLowOrderPriorEstimator_A_AF is a union type that allows dispatch on both asset-only and asset-and-factor prior estimators. This is useful for generic algorithms that operate on estimators using asset returns, with or without factor returns.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimator_F_AFType
const AbstractLowOrderPriorEstimator_F_AF = Union{<:AbstractLowOrderPriorEstimator_F,
                                                  <:AbstractLowOrderPriorEstimator_AF}

Union type for factor-only and asset-and-factor low order prior estimators.

AbstractLowOrderPriorEstimator_F_AF is a union type that allows dispatch on both factor-only and asset-and-factor prior estimators. This is useful for generic algorithms that operate on estimators using factor returns, with or without asset returns.

Related

source
PortfolioOptimisers.AbstractLowOrderPriorEstimator_A_F_AFType
const AbstractLowOrderPriorEstimator_A_F_AF = Union{<:AbstractLowOrderPriorEstimator_A,
                                                    <:AbstractLowOrderPriorEstimator_F,
                                                    <:AbstractLowOrderPriorEstimator_AF}

Union type for asset-only, factor-only, and asset-and-factor low order prior estimators.

AbstractLowOrderPriorEstimator_A_F_AF is a union type that allows dispatch on asset-only, factor-only, and asset-and-factor prior estimators. This is useful for generic algorithms that operate on estimators using any combination of asset and factor returns.

Related

source
PortfolioOptimisers.AbstractHighOrderPriorEstimatorType
abstract type AbstractHighOrderPriorEstimator <: AbstractPriorEstimator

Abstract supertype for high order prior estimators.

AbstractHighOrderPriorEstimator is the base type for estimators that compute high order moments (such as coskewness and cokurtosis) from asset and/or factor returns. All concrete high order prior estimators should subtype this type to ensure a consistent interface for higher moment estimation and integration with portfolio optimisation workflows.

Related

source
PortfolioOptimisers.AbstractPriorResultType
abstract type AbstractPriorResult <: AbstractResult

Abstract supertype for all prior result types.

AbstractPriorResult is the base type for all result objects produced by prior estimators, containing computed prior information such as moments, asset returns, and factor returns. All concrete prior result types should subtype this to ensure a consistent interface for integration with portfolio optimisation workflows.

Related

source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(pr, args...; kwargs...)

Get a view or subset of a prior estimator or result for slicing.

Returns the prior unchanged for estimators (they are not sliceable), or returns a sliced prior result for a given cluster or asset index. Used in hierarchical optimisation to provide cluster-specific priors.

Arguments

  • pr: Prior estimator or result.
  • args...: Additional arguments (index, etc.).
  • kwargs...: Additional keyword arguments.

Returns

  • Sliced prior result or unchanged estimator.

Related

source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(
    pr::LowOrderPrior,
    i,
    args...
) -> LowOrderPrior{var"#s179", _A, var"#s1791", <:AbstractMatrix{var"#s90"}} where {var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar}), var"#s179"<:AbstractMatrix{var"#s90"}, _A, var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar}), var"#s1791"<:AbstractVector{var"#s90"}, var"#s90"<:(Union{var"#s89", var"#s88"} where {var"#s89"<:Number, var"#s88"<:AbstractJuMPScalar})}

Return a view of a LowOrderPrior restricted to assets at index i.

The feature matrix is subselected on its asset axis only. Its feature axis is never sliced: a prior-side Z is derived, and every producer that builds a square one refits on the subproblem's own universe, so there is no full-universe square matrix here to cut down. Observations are taken whole (Colon): folds slice observations before the prior is fit, so a derived Z is already fold-local by the time it reaches here.

The factor block is forwarded unsliced: i indexes assets, and fpr is a distribution over factors. Only rr is cut down, on its asset axis.

Related

source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(
    pr::HighOrderPrior,
    i,
    args...
) -> HighOrderPrior{<:AbstractPriorResult}

Return a view of a HighOrderPrior restricted to assets at index i, slicing all relevant moment tensors accordingly.

The factor block is forwarded unsliced, as it is on LowOrderPrior: i indexes assets, and fpr holds co-moments over factors. Forwarding it by identity is also what keeps fpr.pr === pr.fpr true of the view, since the low order view forwards its own factor block the same way.

Related

source
PortfolioOptimisers.feature_matrix_pickerFunction
feature_matrix_picker(
    pr::Union{AbstractPriorResult, ReturnsResult},
    rd::Union{Nothing, ReturnsResult},
    z_src::Symbol
) -> Tuple{Any, Symbol}

Pick the feature matrix a FeatureDistance inside the clustering, phylogeny or centrality estimator reads, and diagnose its absence.

The counterpart of returns_matrix_picker, with the opposite default: z_src = :data prefers the user's own ReturnsResult over a derived one, because an explicit feature matrix outranks a produced one. (x_src = :prior prefers the prior, because a posterior returns matrix is the improvement being asked for. The differing defaults are the argument for naming the source rather than flagging it.)

A missing feature matrix is not an error here: Z is only required when a FeatureDistance is actually in the estimator tree, which this layer cannot see. Resolution therefore returns nothing and defers the throw to assert_feature_matrix_supplied, passing a second return value that names why nothing was found — :neither when no carrier holds one, and the selector itself when it picked the empty carrier while the other held one.

Arguments

  • pr: Prior result or returns result object.
  • rd: Optional returns result.
  • z_src: Source selector, :prior or :data.

Validation

  • z_src in (:prior, :data).

Returns

  • Z::Option{<:MatNum_Arr3Num}: Feature matrix from the selected carrier, or nothing.
  • z_diag::Symbol: The diagnostic to forward as z_src; the selector itself, or :neither.

Related

source