The prior family on the partial-fit seam: private API
PortfolioOptimisers.PriorCarryState — Type
struct PriorCarryState{__T_buf, __T_named} <: AbstractPartialFitStateCarries the observations a prior keeps when it folds its estimate exactly, and the assets whose scenario fill it has already named.
The state of a fold-and-carry prior, and what separates that route from a refit. A SampleBufferState means refit, everywhere in the library: an estimator carrying one has no recursion of its own, and its read-out is the batch verb over the rows the buffer kept. A prior carrying this state has folded its moments exactly, member by member, and keeps the rows for one reason only — LowOrderPrior carries X for the scenario risk measures, so the observations are memory, not arithmetic. Its read-out reads two folded moments and a matrix it already holds, and touches none of the rows.
A prior a wrapper seeds therefore falls to the refit route rather than to this one, which is what makes Online's cap the window of the whole fit.
The second field, and why a read-out writes to it
named is the set of assets a scenario_fill has told the caller about. strict_diagnostic has no memory of its own, so a batch fit names an asset once and a walk-forward reading out at every step names it at every step: two thousand notices about one listing, and a caller who learns to ignore the channel. The set is that memory, and a read-out reports only the assets outside it.
It is a Set, and a read-out writes into it in place, because a read-out returns a Prior Result rather than the estimator and there is no other channel by which the memory could survive the call. Base.copy copies it, so a state copied before a fold carries a memory of its own, and merge_states unions two.
Fields
buf: Buffer of the observations the prior carries,observations × assets, held verbatim andNaNincluded.
named: Indices of the assets whose scenario fill has already been named, written in place by a read-out that names one.
Constructors
PriorCarryState(; buf::SampleBufferState = SampleBufferState(), named::Set{Int} = Set{Int}()) -> PriorCarryStateKeywords correspond to the struct's fields. The default is the empty seed a first fold builds.
View parameters
When port_opt_view is called on this type, its fields are subset to the selected assets:
buf: Sliced to the selected indices viaport_opt_view.named: Remapped onto the selected indices, so an asset named before the slice is still named after it.
Related
PortfolioOptimisers.sample_buffer — Method
sample_buffer(state::PriorCarryState) -> Any
Reads the observations a PriorCarryState carries, observations × assets.
Arguments
state: The carry state to read.
Returns
X::SubArray: The observations the state carries, in the order they were folded.
Related
PortfolioOptimisers.fold_carry — Function
fold_carry(cache::Option{<:PriorCarryState}, x::VecNum)
fold_carry(cache::Option{<:PriorCarryState}, X::MatNum; dims::Int = 1)Folds observations into a PriorCarryState, seeding an empty one where the prior carries none.
The one line a fold-and-carry prior writes for its rows, beside the two that fold its moments. It is fold_buffer with the second field carried along, and the seed it builds is uncapped: a cap on the carry is EmpiricalPrior's max_scenarios, which is applied at the read-out, and a cap on the fit is Online's, which puts the prior on the refit route instead.
Arguments
cache: The state the prior carries, ornothing.x: One observation, whose entries are the assets.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.dims: Dimension along which to perform the computation.
Returns
state::PriorCarryState: The state after the last observation.
Related
Base.copy — Method
copy(x::PriorCarryState) -> PriorCarryState
Copies a PriorCarryState, so the copy shares no array and no set with the original.
The set is copied for the same reason the backing matrix is: a read-out writes into it, so a copy that shared it would report through the original's memory.
Arguments
x: The state to copy.
Returns
state::PriorCarryState: A fresh state, equal tox.
Related
PortfolioOptimisers.needs_factor_returns — Function
needs_factor_returns(pe::AbstractHiLoOrderPriorEstimator_F) -> true
needs_factor_returns(pe::AbstractLowOrderPriorEstimator_A) -> false
needs_factor_returns(pe::AbstractLowOrderPriorEstimator_AF) -> nothing
needs_factor_returns(pe::Online)
needs_factor_returns(pe::HighOrderPriorEstimator)
needs_factor_returns(pe::BlackLittermanPrior)
needs_factor_returns(pe::EntropyPoolingPrior)
needs_factor_returns(pe::MeucciEntropyPoolingPrior)
needs_factor_returns(pe::OpinionPoolingPrior)Answers whether a prior's fit reads a factor matrix, from its estimator tree.
Whether a fit reads F is a fact of the tree an estimator embeds, not of the host's own type: no prior whose factor argument is optional reads it — each hands it to the prior it embeds — and only a member that requires it does. So the answer is three-valued, and it is read off the source shape the family names:
truefor a member that requires factor returns,AbstractHiLoOrderPriorEstimator_F: its batch verb declaresF::MatNumwith no default, and a fit without one is refused.falsefor a member that never reads them,AbstractLowOrderPriorEstimator_A: its batch verb declares the argument and ignores it, so a fold drops it as the batch verb drops it.nothingfor a member whose factor argument is optional,AbstractLowOrderPriorEstimator_AF: the type does not say; take what the fold is given, which is what its batch verb does.
Each of the library's optional-argument members recurses into the prior it embeds and answers the leaf's value, so EntropyPoolingPrior(; pe = FactorPrior()) answers true and EntropyPoolingPrior() answers false. OpinionPoolingPrior holds several: it answers true when any of them does, false when all of them do, and nothing otherwise. An Online answers for the estimator it wraps. A caller's own optional-argument subtype that embeds a prior defines the recursion; one that reads F itself may leave the default, which takes what it is given.
The predicate is the one test for this fit cannot run without factor returns at the doors that check for a missing factor matrix — the prior's ReturnsResult door, the optimiser's step, and the three uncertainty-set doors — where it replaces a shallow isa test that could not see a factor leaf under an optional-argument host. It also decides what the refit route of partial_fit! does with the factor observation it is given.
Arguments
pe: The prior estimator, or the wrapper around one.
Returns
needs::Union{Bool, Nothing}:true,falseornothing, as above.
Related
PortfolioOptimisers.combine_factor_answers — Function
combine_factor_answers(answers) -> Union{Nothing, Bool}
Combines the answers of several embedded priors into one, for a host that holds more than one.
The three-valued conjunction needs_factor_returns states for OpinionPoolingPrior: true when any member requires factor returns, because a fit that reaches that member without them is refused; false when every member never reads them, because the fit then drops them as each member does; and nothing otherwise, because at least one member takes what it is given and none requires it.
Arguments
answers: The answers of the members, eachtrue,falseornothing.
Returns
needs::Union{Bool, Nothing}: The combined answer.
Related
PortfolioOptimisers.assert_factor_returns — Function
assert_factor_returns(
pe::Union{AbstractPriorEstimator, Online},
F::Union{Nothing, AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}, AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}}
)
Refuses a missing factor matrix at a door whose prior's tree requires one.
The one refusal the five doors share — the prior's ReturnsResult method, the optimiser's step, and the three uncertainty-set doors — written once so that its message and its test cannot drift apart. The test is needs_factor_returns answering true, which walks the estimator tree, so a factor leaf nested under a host whose own factor argument is optional is refused here by name rather than by the leaf's MethodError one call later.
A pe of nothing is an uncertainty set with no prior of its own. It reads no factor matrix, so nothing is checked here; the returns-data form it is on its way to refuses it by name through ucs_prior.
Arguments
pe: The prior estimator the door hands the matrix to, ornothing.F: The factor matrix the carrier holds, or the factor observation a fold is given, ornothing.
Validation
!isnothing(F), whenneeds_factor_returns(pe) === true. AnIsNothingErroris thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.fold_factor_argument — Function
fold_factor_argument(needs::Bool, pe::AbstractPriorEstimator, F::Option{<:VecNum_MatNum})
fold_factor_argument(::Nothing, ::AbstractPriorEstimator, F::Option{<:VecNum_MatNum})Applies the estimator tree's answer to the factor argument of a fold.
The three arms of needs_factor_returns as the refit route reads them: true refuses a missing F by name and passes a present one through, false drops it, and nothing passes it through as it is. Written by dispatch on the answer so that a tree whose answer is a compile-time constant — every one of the library's — costs the fold no branch.
Arguments
needs: The answer ofneeds_factor_returns.pe: The prior, for the refusal's message.F: The factor argument the fold was given, ornothing.
Returns
F: The factor argument the buffer records, ornothing.
Related
PortfolioOptimisers.fold_member — Function
fold_member(est, args...; kwargs...)
Folds an observation into a member of a carrying host, where that member folds.
The fold half of the mixed-host rule. A host that carries the observations folds every member that folds and leaves the rest untouched, because it can run their batch verb over its own rows at the read-out. supports_partial_fit is the question, and it is answered from the member's type and its cache field, so a host of concrete members resolves the branch at compile time and folds nothing it should not.
A member the host does not hold is nothing, and folding it is a no-op.
Arguments
est: The member to fold, ornothing.args...: The observations, forwarded topartial_fit!.kwargs...: Additional keyword arguments, forwarded topartial_fit!.
Returns
est: The member carrying the state after the last observation, or the member unchanged where it does not fold.
Related
PortfolioOptimisers.read_member — Function
read_member(
f,
est,
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}};
kwargs...
) -> Any
Reads a member's estimate out of its fold, or refits it over the host's own rows.
The read-out half of the mixed-host rule, and the twin of fold_member: a member the host folded answers from its state, and a member it did not fold answers from the matrix the host carries. f is the member's batch verb — Statistics.mean, Statistics.cov, coskewness, cokurtosis — and the one-argument form of that same verb is its read-out, which is a convention every family of the seam already follows.
No AssetPanel reaches this verb. A panel is fold context rather than sample, and a buffer holds no activity mask, so a member refitted here is refitted over the rows alone; that is #999's to change.
Arguments
f: The member's batch verb.est: The member, ornothing.X: The rows the host carries, as the member was folded on them.kwargs...: Additional keyword arguments, forwarded to the batch verb alone. A folded member is read with no keyword argument at all, because its state is already the answer and there is no sample left for a keyword to describe.
Returns
- The member's estimate.
Related
PortfolioOptimisers.update_online_estimator — Method
update_online_estimator(pe::Union{<:HighOrderPriorEstimator, <:BlackLittermanPrior})Resolves the Online declarations under the prior a wrapping prior embeds, at warm-up.
A wrapping prior hands its embedded prior across a boundary of its own, so it writes the recursion the generic method does not: HighOrderPriorEstimator(; pe = BlackLittermanPrior(; pe = Online(EmpiricalPrior()), …)) is resolved through this method, where the generic scan of the host's own fields would find no wrapper — pe holds a plain prior — and leave the one two levels down unseeded. A wrapper stored in the host's own pe, HighOrderPriorEstimator(; pe = Online(EmpiricalPrior())), is seeded the same way, because the recursion meets it at the first level. The co-moments of a HighOrderPriorEstimator are scanned by the generic method as they always were.
Arguments
pe: The wrapping prior.
Returns
pe: The prior, with every wrapper under its embedded prior resolved.
Related