Online (b): private API
PortfolioOptimisers.Online_Option — Type
const Online_Option{X} = Union{Nothing, <:Online, X}Alias for a field that accepts nothing, a static estimator of type X, or an Online declaration.
The fields whose constructor signatures use this alias are the fields that can take the online step from a sample buffer, as TD_Option marks the fields that can change over folds.
Related
PortfolioOptimisers.Onl — Type
const Onl{X} = Union{<:Online, X}Alias for a required field that accepts a static estimator of type X or an Online declaration.
This is the form of Online_Option for a required field, as TD is for TD_Option. A field that the outer estimator requires takes this alias. A caller can declare the online step there, and the signature refuses nothing.
Related
PortfolioOptimisers.CVE_Onl — Type
const CVE_Onl = Union{<:CrossValidationEstimator, <:Online{<:CrossValidationEstimator}}Alias for a cross-validation scheme, plain or an Online Scheme.
An Online Scheme is an Online around a walk-forward, built by the function constructor of the scheme, OnlineIndexWalkForward, OnlineDateWalkForward or OnlineHindsightSplit. Its supertype is AbstractEstimator and not CrossValidationEstimator, because a struct has one supertype. Each function that takes a scheme dispatches on this alias, or on an alias built from it, so the wrapped form reaches the same functions as the plain form. The fold loop then reads folds_are_stepped from its type.
Related
PortfolioOptimisers.assert_sample_buffer — Method
assert_sample_buffer(_::Online)
Refuses an Online that reached a fold without being resolved, naming the warm-up that resolves it.
update_online_estimator replaces each wrapper that it can reach at warm-up. So a wrapper that reaches a fold is one that the warm-up did not see. A callable TimeDependent makes one. The value of a schedule is computed at each fold, after the warm-up, so nothing seeds a wrapper that the callable returns. The constructor of a schedule refuses a wrapper in its vector and default forms. It cannot refuse the return value of a callable, because that value does not exist until the fold.
A callable that returns the estimator that the wrapper would make does not solve the problem. A schedule replaces the value of the field at each fold, and the step passes the buffer through that field. So a schedule that returns a captured estimator returns the buffer as it was when the closure was built, and it discards each step since then.
Arguments
::Online: The unresolved wrapper.
Validation
- Always throws an
ArgumentError.
Returns
- Never returns.
Related
PortfolioOptimisers.online_candidate_fields — Function
online_candidate_fields(x)Field names of x whose type admits an Online, the candidate set that online_fields narrows by value.
fieldtype alone decides whether a field can hold a wrapper, because a @concrete estimator records the type of the value in the type parameter of the field. The type of a field that holds a static estimator does not intersect Online. So a generated function computes the tuple once for each estimator type, and for an estimator with no wrapper the tuple is empty at compile time. The warm-up then walks no field.
Related
PortfolioOptimisers.online_fields — Function
online_fields(
est::Union{AbstractEstimator, CovarianceEstimator}
) -> Any
Returns the tuple of field names of est whose values are Online.
The scan reads the fields of the outer estimator, so the constructor signatures that admit a wrapper, through Online_Option and Onl, decide which estimators can take the step from a buffer. No list is kept by hand. The scan visits only the candidates of online_candidate_fields, and the compiler removes the other fields.
Arguments
est: Estimator whose fields are scanned.
Returns
fns::Tuple: The field names holding anOnline.
Related
PortfolioOptimisers.update_online_estimator — Function
update_online_estimator(est)Resolves the Online declarations of an estimator, seeding the sample buffer each one asks for.
The warm-up calls it once, before the first fold. It replaces each wrapper with the estimator that the wrapper holds, rebuilt through its keyword constructor with the state of online_state_seed in cache. That state is an empty SampleBufferState with the cap of the wrapper, unless the family has a seed of its own. The function then rebuilds the outer estimator through its keyword constructor, so each construction check runs again. The result holds no Online, and each estimator that was wrapped carries the state that its refit or its carry reads.
The function finds a wrapper in the fields of the estimator that it receives, and in the fields of an estimator inside a wrapper. An outer estimator that passes estimators across a boundary of its own, such as a meta-optimiser or a pipeline, has a method of its own that recurses, as it has for update_time_dependent_estimator.
The function takes no fold context, unlike update_time_dependent_estimator. The seed reads nothing from a fold, because the wrapper resolves once and not at each fold.
Algorithm
- For an
Online, rebuild the wrapped estimator withcacheset to the state ofonline_state_seed, and continue with that estimator. - Find the fields of the estimator that hold a wrapper, with
online_fields. Return the estimator when there is none. - Resolve the value of each of these fields with this function.
- Rebuild the estimator with the resolved values through
rebuild_estimator.
Arguments
est: Estimator, wrapper, ornothing.
Returns
- Estimator carrying a seeded buffer wherever a wrapper stood, and holding no
Online.
Related
update_online_estimator(pe::Union{<:HighOrderPriorEstimator, <:BlackLittermanPrior})Resolves the Online declarations under the prior that a wrapping prior embeds, at warm-up.
The generic method scans the fields of the wrapping prior alone, and a wrapping prior holds its embedded prior in its own pe field, so the wrapping prior defines the recursion itself. HighOrderPriorEstimator(; pe = BlackLittermanPrior(; pe = Online(EmpiricalPrior()), ...)) resolves through this method. The generic scan of the own fields of the wrapping prior finds no wrapper there, because pe holds a plain prior, so the generic method would leave the wrapper two levels down unseeded. A wrapper in the own pe of the wrapping prior, as in HighOrderPriorEstimator(; pe = Online(EmpiricalPrior())), is seeded the same way, because the recursion meets it at the first level. The generic method still scans the co-moments of a HighOrderPriorEstimator.
Algorithm
- Resolve every field that
online_fieldsnames withupdate_online_estimator, givingrepl. - Resolve
pe.pewithupdate_online_estimator, which recurses through a wrapping prior. - Rebuild the prior from
repland the resolvedpe.pe, the second taking precedence forpe, and return it.
Arguments
pe: The wrapping prior.
Returns
pe: The prior, with every wrapper under its embedded prior resolved.
Related
update_online_estimator(opt::JuMPOptimisationEstimator)
update_online_estimator(opt::Union{<:HierarchicalRiskParity, <:HierarchicalEqualRiskContribution, <:SchurComplementHierarchicalRiskParity})
update_online_estimator(opt::Union{<:JuMPOptimiser, <:HierarchicalOptimiser, <:InverseVolatility, <:NestedClustered, <:Stacking, <:SubsetResampling})Resolves the Online wrappers in the prior of an optimiser, at the warm-up.
The JuMP and hierarchical heads resolve the bundle they hold, and the bundle, the meta-optimisers and InverseVolatility resolve their pe. The step forwards observations to that prior alone, so this function resolves no other wrapper. A wrapper in an inner optimiser of a meta-optimiser, in a fallback, or in any other field stays unresolved, and the entry of the online arm of the fold loop refuses it with an error that names the field.
Arguments
opt: The optimiser.
Validation
- Everything
online_state_seedrefuses.
Returns
opt: The optimiser, with each wrapper in its prior resolved to an estimator that carries a seeded buffer.
Related
update_online_estimator(opt::Union{<:OnlinePortfolioSelection, <:PreviousWeights})Resolves the Online wrappers in the fallback of the head, at the warm-up.
The two heads step their fallback through step_fallback, so a wrapper in the prior of a fallback estimator declares the window that the fallback folds. The method resolves the fallback as the warm-up resolves an optimiser. A PreviousWeights that is the fallback of the head resolves its own fallback in turn. Any other fallback holds no wrapper to resolve, so the head passes unchanged. The recursion of the head holds no wrapper.
Related
update_online_estimator(p::Pipeline)Resolves the Online declarations in the steps of a Pipeline, at warm-up.
On the fold route update_online_step resolves every step. So an Online(EmpiricalPrior(); max_history = w) step becomes the prior with its buffer, and an optimisation step resolves the wrappers under its own prior. On the refit route the pipeline carries a PipelineBufferState, which Online(pipe) seeded, and the method returns the pipeline unchanged. No member folds under a refit, and assert_online_entry already refused any wrapper below the root with an error that names it.
Related
PortfolioOptimisers.estimator_fields — Function
estimator_fields(x)Field names of x whose type admits an estimator, the candidate set that online_wrapper_path and copy_states walk.
fieldtype alone decides whether a field can hold an estimator, because a @concrete estimator records the type of the value in the type parameter of the field. So a generated function computes the tuple once for each estimator type, as for online_candidate_fields. A field that holds a vector of estimators or a result is not a candidate. A vector is a batch configuration that the step never folds into, and a result carries no state field. A walk that must reach the estimators a vector holds reads every field instead, as online_entry_state and seed_window_path do. A field that holds a TimeDependent schedule is a candidate, because a schedule is an estimator. The TimeDependent methods of the two walks answer nothing for it, because the entries of a schedule resolve at each fold.
Related
PortfolioOptimisers.online_entry_state — Function
online_entry_state(est)
online_entry_state(v::AbstractVector)
online_entry_state(p::Pair)
online_entry_state(::TimeDependent)Names the first field of an estimator tree that carries a partial-fit state, or answers nothing.
The cold start of the fold loop uses this walk. The online arm of fold_loop reads its argument as configuration only, so it refuses by name an estimator that holds a state, and this walk finds the state. The answer is the path from the root, for example "opt.pe.me.cache" for the state of a mean estimator under a JuMP head. The walk reads every field, not only the fields of estimator_fields, because a state can stand in an estimator that a vector holds. A Descriptor that the caller folded before the call, in the factor list of a CrossSectionalFactorPrior, is such an estimator, and the first step of the carry fold reads its state. So the first partial_fit! of that prior refuses a state with this walk too, because a direct call does not pass through the fold loop. A vector answers with the index of its element in brackets, as element_path states, and a Pair answers through its value, so the path is "factors[2].descriptors[1].cache" for that Descriptor. A TimeDependent schedule answers nothing, because its entries are batch configuration that resolves at each fold, and the loop passes no state through them. A value that is not an estimator also answers nothing.
Algorithm
- Answer
"cache"whenesthas acachefield that is notnothing. - Walk every field of
estin order, and find the path in each field with this function. - Answer the first path found, with the field name before it, as
tree_pathjoins them, ornothingwhen no field gives one.
Arguments
est: The estimator, or any value a field holds.v: A vector that a field holds.p: A Pair that a vector holds, such as a member of a factor list.
Returns
path::Option{<:String}: The path of the first state found, ornothing.
Related
online_entry_state(o::Online)Name the state that a wrapped estimator carries at the entry of the online arm of the fold loop, or answer nothing.
This is the Online method of online_entry_state, for a wrapper at the root of covariance_forecast_evaluation. A wrapper holds no cache of its own, so the walk enters the estimator that it wraps and puts est. before the path that it finds there. For a covariance estimator that the caller folded before the call, the path is est.cache. The generic walk through estimator_fields would give the same answer. This method gives it without a request for a field that the wrapper does not have.
Related
online_entry_state(p::Pipeline)Names the first state that a Pipeline carries at the entry of the online arm of the fold loop, or answers nothing.
The answer is "cache" when the pipeline holds a state of its own. Otherwise the method walks the steps in order, and answers the path of the first state under a step, prefixed with the name of the step.
Related
PortfolioOptimisers.assert_cold_carry_entry — Function
assert_cold_carry_entry(est, ::Nothing, name::AbstractString) -> nothing
assert_cold_carry_entry(est, ::Any, name::AbstractString) -> nothingRefuses a partial-fit state in a member of a carry at its first step.
A carry reads every member as configuration at its first step: the carried rows start empty, and each member folds the new observations. A member that holds a state would fold them onto the observations of that state, so its moment would read rows that the carried rows and every refitted member do not read, and the prior would not equal the batch fit over the folded observations. The fold loop refuses such an estimator at its entry, and a direct partial_fit! does not pass through the fold loop, so each carry calls this function before its first step. The second argument marks the state of the carry itself: nothing at the first step, and any other value after it, when each member holds the state that the carry folded. A carry that keeps its state in a field passes that field. A carry that keeps its rows in a member, as HighOrderPriorEstimator keeps them in its embedded prior, passes the online_entry_state of that member.
Algorithm
The method that Julia selects is the algorithm.
cacheis notnothing: return, because the members hold the states that the carry folded.cacheisnothing: find the first state inestwithonline_entry_state, and refuse it.
Arguments
est: The estimator that starts its carry.cache: The state of the carry, or the path of the state of the member that carries the rows, andnothingat the first step.name: The name of the estimator in the message.
Validation
- At the first step, no member of
estholds a partial-fit state. AnArgumentErrorthat names the path of the state is thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.online_wrapper_path — Function
online_wrapper_path(est)
online_wrapper_path(::Online)
online_wrapper_path(::TimeDependent)Names the first field of an estimator tree that holds an Online declaration, or answers nothing.
assert_batch_entry uses this walk. Only the warm-up of the online arm of the fold loop resolves a wrapper, with update_online_estimator. Without the check, a batch fit that reaches a wrapper gets a MethodError at prior(pe, X), not a refusal. The walk reads the fields of estimator_fields, and the answer is the dotted path from the root. It is "pe" for a wrapped prior on a naive optimiser, and "opt.pe" for a wrapped prior under a JuMP head. The walk does not enter a field that holds a wrapper, because the warm-up resolves the wrappers below it. A wrapper at the root answers "", the empty path. A TimeDependent schedule answers nothing, because its constructor refuses a wrapper among its entries. A value that is not an estimator also answers nothing.
Algorithm
- Answer
""whenestis anOnline. - Walk the fields of
estimator_fieldsin order, and answer the name of the first field that holds a wrapper. - For a field that holds no wrapper, find the path in the field with this function, and answer it with the field name and a dot before it.
- Answer
nothingwhen no field gives a path.
Arguments
est: The estimator, or any value a field holds.
Returns
path::Option{<:String}: The dotted path of the first wrapper found,""whenestis itself one, ornothing.
Related
PortfolioOptimisers.seed_window_path — Function
seed_window_path(est)
seed_window_path(v::AbstractVector)
seed_window_path(p::Pair)
seed_window_path(::Any)Names the first field of an estimator tree that holds a windowed estimator under SeedWindow, or answers nothing.
The constructor of Online uses this walk to refuse a seed window, because the wrapper refits its estimator at each step. The answer is the path from the root to the rule field, such as "ce.rule" for the covariance member of a prior. A windowed estimator under a seed window answers "rule" through its own method. A value that is not an estimator answers nothing.
The walk reads every field, not only the fields of estimator_fields. A refit reaches the estimators that a vector holds, such as the factor list of a CrossSectionalFactorPrior, the Descriptors of a DescriptorScores and the priors of an OpinionPoolingPrior, so the refusal must reach them too. A vector answers with the index of its element in brackets, and a Pair answers through its value, so a Descriptor in a factor list gives a path such as "factors[2].descriptors[1].ce.rule". element_path walks the vector.
Algorithm
- Walk every field of
estin order, and find the path in each field with this function. - Answer the first path found, with the field name before it, as
tree_pathjoins them. - Answer
nothingwhen no field gives a path.
Arguments
est: The estimator, or any value a field holds.v: A vector that a field holds.p: A Pair that a vector holds, such as a member of a factor list.
Returns
path::Option{<:String}: The path of the first seed window found, ornothing.
Related
seed_window_path(
_::Union{WindowedCokurtosis{<:Any, <:Any, <:Any, <:SeedWindow}, WindowedCoskewness{<:Any, <:Any, <:Any, <:SeedWindow}, WindowedCovariance{<:Any, <:Any, <:Any, <:SeedWindow}, WindowedExpectedReturns{<:Any, <:Any, <:Any, <:SeedWindow}, WindowedVariance{<:Any, <:Any, <:Any, <:SeedWindow}}
) -> String
Names the rule field of a windowed estimator under a SeedWindow, the end of the walk of seed_window_path.
Arguments
est: Windowed estimator under a seed window.
Returns
path::String:"rule".
Related
PortfolioOptimisers.assert_batch_entry — Function
assert_batch_entry(est, entry::AbstractString)Refuses an estimator that holds an Online at the entry of a batch fit, with an error that names the path of the wrapper.
A wrapper is a declaration that the online arm of the fold loop resolves at its warm-up. A batch fit runs no warm-up. A batch fit is a plain optimise, or a fold of a scheme that is not an Online Scheme. So the wrapper would reach prior(pe, X) unresolved and get a MethodError that names the whole type. The refusal names the dotted path that online_wrapper_path finds, and the two exits. One exit is an Online Scheme, such as OnlineIndexWalkForward. The other exit is the estimator without the wrapper. Each caller passes an optimiser, which is never a wrapper, so the path at this entry is never the empty path.
Algorithm
- Find the path of the first wrapper in
estwithonline_wrapper_path. - Refuse
estwhen the path is notnothing, and name the path and the entry function.
Arguments
est: The estimator handed to the entry function.entry: The name of the entry function, as the message reads it.
Validation
- No field in the tree of
estholds anOnline. AnArgumentErrornaming the field is thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.online_state_seed — Method
online_state_seed(
_::Union{AbstractEstimator, CovarianceEstimator},
max_history::Union{Nothing, Integer}
) -> Union{ReturnsBufferState{Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, ReturnsBufferState{Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, __T_max_history} where __T_max_history<:Integer}
Builds the empty state an Online seeds into the estimator it wraps.
One sample buffer works for each estimator that refits, so the seed needs no knowledge of the type. A prior whose batch verb reads a factor matrix beside the returns records the factor rows in the same buffer, and needs_factor_returns decides whether its fold receives them. An estimator whose state is not a sample buffer has a method of its own that returns the state that its call with no data reads. A prior-less optimiser head is such an estimator, because its state is a fold context. Nothing else about the wrapper changes.
The function takes the estimator and not its type, so a family that sizes its seed from a field can read that field.
Arguments
est: The estimator the wrapper wraps, read for its type.max_history: The wrapper's cap, carried into the state.
Returns
state::AbstractPartialFitState: The empty state to seed, carrying the cap and no observations.
Related
PortfolioOptimisers.tree_path — Function
tree_path(
head::Union{AbstractString, Symbol},
path::AbstractString
) -> Any
Joins the name of a field, or the bracketed index of an element, to the path that a walk found below it.
A path that starts with a bracket follows the name with no dot, so a walk names a member of a vector field as "factors[2]" and not as "factors.[2]". An empty path answers the name alone, so a walk whose leaf answers "" names the field that holds the leaf, such as "tr". Every other path follows the name after a dot.
Arguments
head: The field name, or the bracketed index of an element, such as"[2]".path: The path belowhead.
Returns
path::String: The joined path.
Related
PortfolioOptimisers.element_path — Function
element_path(walk, v::AbstractVector) -> Any
Walks the elements of a vector in order with walk, and answers the path of the first element that gives one, or nothing.
The walks of an estimator tree that must see the estimators a vector holds call this function: seed_window_path, online_entry_state and returns_tracking_path. The answer starts with the index of the element in brackets, as tree_path joins it.
Arguments
walk: The walk, a function that answers a path ornothingfor one element.v: The vector.
Returns
path::Option{<:String}: The path of the first element that gives one, ornothing.
Related