Online (b)
Online wraps an estimator that has no exact incremental fit, and gives it a buffer of the observations it has seen.
PortfolioOptimisers.Online — Type
struct Online{__T_est, __T_max_history} <: AbstractEstimatorDeclares that an estimator takes the online step from a buffer of the observations it has seen.
An Online goes directly in the estimator field that it wraps, for example HighOrderPriorEstimator(; pe = Online(EmpiricalPrior())), or the pe of an optimiser, JuMPOptimiser(; pe = Online(EmpiricalPrior()), slv = …). It is transient, as TimeDependent is. update_online_estimator walks the fields that hold a wrapper, seeds the cache of each wrapped estimator with a SampleBufferState, and rebuilds the outer estimator through its keyword constructor. The result is an ordinary estimator that carries a state. No Online exists after that, so each verb downstream receives a plain estimator.
Only a field whose bound is Onl admits a wrapper. These are the pe field of a wrapping prior and of an optimiser. A moment field inside a prior, such as ce, me, ske or kte, admits none, so the bound of the field refuses EmpiricalPrior(; ce = Online(…)) before any warm-up. The prior owns the rows. It holds its observations once, at the bottom of its chain, and it refits from those rows each member that does not fold. A buffer under one of its moments would hold the same rows a second time, so wrap the prior. Wrap a moment estimator alone only when it is the estimator under study, as in update_online_estimator(Online(Coskewness())).
It differs from TimeDependent in when it resolves. A schedule resolves again at each fold, because its value changes at each fold. An Online resolves once, at warm-up. After warm-up, the step passes the state from fold to fold, and a second resolution would discard the buffer.
A wrapper replaces an exact fold, and it does not add to one. Each family that folds exactly narrows the cache type parameter of its own partial_fit! methods to the state of that fold, so a wrapped estimator never reaches them. It buffers its observations, and it answers each call with no data with the batch verb over the rows of the buffer. The type of the state selects the route, and the caller selects the type when it wraps the estimator or not.
Wrap an estimator in one of these cases:
- Its estimate has no exact incremental fold.
- It folds exactly, and it carries its observations for a consumer downstream.
- Its estimate must come from a window, not from every observation.
An estimator that folds exactly and carries nothing needs no wrapper. Unwrapped, it answers partial_fit! and seeds its own state at the first call, and it uses the memory of one state, not the memory of a buffer.
A wrapper and a TimeDependent schedule do not wrap each other, because they resolve at different times. Neither Online(TimeDependent(…)) nor a schedule whose entry or default is an Online is admissible. A wrapper inside a schedule entry would resolve at no fold, or it would seed again at each fold and discard the buffer that the step passes on. They compose the other way, in two ordinary forms. An estimator that an Online wraps can hold schedules of its own, which the seed does not change and which resolve at each fold after it. One outer estimator can hold a wrapper in one field and a schedule in another, and each resolves at its own time. The two field scans are disjoint by construction, because a field that holds one kind is not a candidate of the other scan. So neither resolution reaches the wrapper of the other.
On a scheme, the same word declares an Online Scheme. Online{<:WalkForwardEstimator} wraps a walk-forward whose folds the loop fits by the online step, not by a refit. The loop warms one estimator up on the first training window, folds the new observations of each fold into it, and reads it out where a refit would run. Only the function constructor of the scheme builds one, OnlineIndexWalkForward, OnlineDateWalkForward or OnlineHindsightSplit. Each takes the keywords of its scheme except the window knob, and it sets that knob true, because a fold cannot remove an observation. Online(cv) written by hand is refused with an error that names it. On a scheme the wrapper is not transient. Nothing resolves it, the loop reads it at each fold, and each function that takes the scheme decides on its type. It carries no max_history, because the estimator declares a window through the wrapper on the prior.
max_history caps the buffer, and the cap is the window. An uncapped buffer gives the batch fit over every observation folded so far. A capped buffer gives the batch fit over the last max_history observations. This holds for the estimate and for each consumer that reads the observations, such as the scenario risk measures CVaR, EVaR and CDaR. The rule has no special case. A buffer always means the batch verb over its rows. An unwrapped estimator is not affected. It folds exactly, and it stays fitted over every observation.
Fields
est: Estimator that the wrapper seeds a buffer into. The field takes this value after the wrapper resolves.
max_history: Optional cap on the number of observations the buffer keeps.nothingkeeps every observation folded so far. A capped buffer drops its oldest observations as new ones arrive and holds the lastmax_historyof them. The call with no data reads those rows only. The cap is the window of the fit. An estimator wrapped inOnlinereturns the batch fit over the lastmax_historyobservations, also when its statistic has an exact update.
Constructors
Online(est::Union{<:AbstractEstimator, <:StatsBase.CovarianceEstimator}; max_history::Option{<:Integer} = nothing)Online(; est::Union{<:AbstractEstimator, <:StatsBase.CovarianceEstimator}, max_history::Option{<:Integer} = nothing)Validation
estis not anOnline. AnArgumentErroris thrown otherwise.estis not a cross-validation scheme, because the function constructor of a scheme builds its Online Scheme. AnArgumentErrornaming the constructors is thrown otherwise.estis not anOnlinePortfolioSelectionhead, because a refit of a head is a batch walk-forward, and the library runs both settings of the wrapper in other forms. AnArgumentErrornaming those forms is thrown otherwise.esthas acachefield. AnArgumentErroris thrown otherwise. Every covariance estimator of the library has one. A covariance estimator with no such field, such as aStatsBase.CovarianceEstimatorof another package, takes the buffer of aPortfolioOptimisersCovariancethat holds it.- No field of the tree of
estholds a windowed estimator underSeedWindow, because the wrapper refits the tree at each step, and a refit has no first fit to remember.seed_window_pathfinds the field, and anArgumentErrorthat names it is thrown otherwise. max_history > 0when it is notnothing. ADomainErroris thrown otherwise.
Examples
julia> Online(Covariance(; alg = SemiMoment()); max_history = 250)Online est ┼ Covariance │ me ┼ SimpleExpectedReturns │ │ w ┴ nothing │ ce ┼ GeneralCovariance │ │ ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true) │ │ w ┴ nothing │ alg ┼ SemiMoment() │ w ┴ nothing max_history ┴ Int64: 250Related
A window rule says which observations the window of a windowed moment estimator keeps on the online step. A choice rule says how a choice that a fit makes over its whole sample behaves on the online step.
PortfolioOptimisers.AbstractWindowRule — Type
abstract type AbstractWindowRule <: AbstractAlgorithmAbstract supertype for the window rule of a windowed moment estimator, the rule that says which observations its window keeps on the online step.
A windowed estimator, such as WindowedCovariance, fits its inner estimator on a window of observations. In a batch fit every rule keeps the same window, the last window observations. The rules differ when the estimator receives its observations one block at a time.
Interfaces
A rule is a marker for dispatch, and it holds no data. The windowed estimators hold it in their rule field, and the methods that fold them dispatch on its type. A new rule needs its own fold methods for the five windowed estimators.
Related
PortfolioOptimisers.RollingWindow — Type
struct RollingWindow <: AbstractWindowRuleKeeps the last observations of the window at every fit, so the window rolls with each new observation. This is the default rule.
The estimator does not fold. On the online step, a prior that carries the observations, such as the carry of EmpiricalPrior, refits it over the carried rows at each read, and the window of each refit ends at the last row. So the call with no data after any stream of blocks equals the batch fit over every row received.
Constructors
RollingWindow() -> RollingWindowExamples
julia> RollingWindow()RollingWindow()Related
PortfolioOptimisers.SeedWindow — Type
struct SeedWindow <: AbstractWindowRuleKeeps the last observations of the window at the first fit alone. After the first fit, the inner estimator folds every new observation, and no observation leaves the estimate.
In a batch fit the rule keeps the same window as RollingWindow. On the online step the estimator folds. Its first fold cuts the first block to the window, folds the rows that remain into the inner estimator, and returns the estimator with window = nothing, so each later fold passes every row. The call with no data after a stream of blocks then gives the fit over the window of the first block, continued by the fold of every later row, and it equals no batch fit.
The rule needs an inner estimator that folds exactly, such as ExpWeightedCovariance, and a prior that folds, such as the carry of EmpiricalPrior. Online refuses it, because the wrapper refits its estimator at each step, and a refit has no first fit to remember.
Constructors
SeedWindow() -> SeedWindowExamples
julia> SeedWindow()SeedWindow()Related
PortfolioOptimisers.AbstractChoiceRule — Type
abstract type AbstractChoiceRule <: AbstractAlgorithmAbstract supertype for the Choice Rule of an estimator, the rule that says how a choice that a fit makes over its whole sample behaves on the online step.
Some fits make a choice that reads every observation, such as the dropped member of a Factor Family in CrossSectionalFactorPrior, the factor set of each asset in StepwiseRegression, or the components of DimensionReductionRegression. In a batch fit every rule makes the same choice. The rules differ when the estimator receives its observations one block at a time.
Interfaces
A rule is a marker for dispatch, and it holds no data. An estimator that makes such a choice holds the rule in its choice field. The step of its online fold dispatches on the type of the rule. A new rule needs its own method of that step for each estimator that holds it.
Related
PortfolioOptimisers.BatchChoice — Type
struct BatchChoice <: AbstractChoiceRuleMakes the choice again over every observation at each fit. This is the default rule.
On the online step a refit reads every row of its buffer, so the choice can move from one step to the next, and the call with no data after any stream of blocks equals the batch fit over the same rows. On the carry fold of a CrossSectionalFactorPrior, a step that moves the dropped member of a Factor Family solves no observation of full rank again. The raw factor returns of such an observation do not depend on the dropped member, so the step selects the columns that the new member keeps, and folds the factor prior again over them.
Constructors
BatchChoice() -> BatchChoiceExamples
julia> BatchChoice()BatchChoice()Related
PortfolioOptimisers.PinnedChoice — Type
struct PinnedChoice <: AbstractChoiceRuleKeeps the choice of the first fit. After the first fit, every later fit reads the same choice.
In a batch fit the rule makes the same choice as BatchChoice. An EntropyPoolingPrior and a MeucciEntropyPoolingPrior build their views on the fit under the prior probabilities, and refit under the posterior weights through scenario_factory, which holds the regression of that fit, so each refit reads the choice of the fit that the views read under either rule. On the online step the rule holds no state. After the first step whose rows the fit accepts, the step writes the choice into the configuration of the estimator that it returns, for example the name of the dropped member of each Factor Family into the families of a CrossSectionalFactorPrior, the factor set of each asset into included of a StepwiseRegression, or the components into proj of a DimensionReductionRegression. Each later step then reads that choice. The call with no data after a stream of blocks equals the batch fit over the same rows under the choice of the first fit, which differs from a batch fit when the choice of the whole sample moves.
Constructors
PinnedChoice() -> PinnedChoiceExamples
julia> PinnedChoice()PinnedChoice()Related
A family that folds states it through supports_partial_fit, and an outer estimator asks each of its members before it folds them.
PortfolioOptimisers.supports_partial_fit — Function
supports_partial_fit(est) -> BoolAnswers whether partial_fit! folds this estimator.
An outer estimator that carries the observations asks each of its members. This is the rule for an estimator with mixed members. The outer estimator folds each member that folds, and it runs the batch verb over its own rows for each member that does not. So a caller writes the same estimator as in batch, with no wrapper at the call site, and no member carries a second copy of the sample.
The default is the buffering route. An estimator folds when it carries a SampleBufferState, which Online seeds. A family with an exact fold of its own adds a method that returns true, beside that fold, under the same type bound without the cache parameter. An estimator of that family folds exactly when its bound matches, and by buffering when a wrapper seeded a buffer. A configuration that a family refuses adds no method, and it takes the default. The SemiMoment arms are such a configuration, because their clip moves when the mean moves. For them, the default is true only when a wrapper gave the estimator a buffer.
The predicate reads a type and a field, never a method table. A read of the dispatch would count a refusal as a fold, because a refusal is a method too, and the members that refuse are the members that must buffer.
Arguments
est: The estimator to ask about.
Returns
folds::Bool:truewhenpartial_fit!folds this estimator.
Related
supports_partial_fit(
ce::PortfolioOptimisersCovariance
) -> Any
PortfolioOptimisersCovariance method of supports_partial_fit.
The composite folds by composition, so it folds exactly when both of its halves allow it: the inner estimator must fold, and mp must run from the shape of the sample, as supports_shape_processing states. A MatrixProcessing passes when it carries no sample-reading alg, and a matrix processing estimator of a caller never passes. A composite a wrapper has given a buffer folds whatever those two say, which is the default and is what makes an mp.alg reachable online at all.
Arguments
ce: Covariance estimator.
Returns
folds::Bool:truewhenpartial_fit!folds this composite.
Related
supports_partial_fit(
_::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}}
) -> Bool
Answers that a windowed estimator under a SeedWindow folds.
A prior that carries the observations, such as the carry of EmpiricalPrior, folds each member that folds, and refits the others over its rows. A seed window must fold, because a refit keeps the rolling window. So the answer is true whatever the inner estimator, and the fold refuses an inner estimator that does not fold with an error that names it, not a silent refit.
Arguments
est: Windowed estimator under a seed window.
Returns
true.
Related
supports_partial_fit(ce::GeodesicShrinkageCovariance) -> Any
GeodesicShrinkageCovariance method of supports_partial_fit.
The estimator folds through ce.ce, so it folds when ce.ce folds. An estimator whose cache holds a SampleBufferState folds whatever ce.ce is, because it takes the buffering fold.
Arguments
ce: The geodesic shrinkage covariance estimator.
Returns
folds::Bool:truewhencecarries a buffer, or whenpartial_fit!foldsce.ce.
Related
The page also has the supertypes of the allocation sets. An allocation set is the set of allowed weights that an online portfolio selection rule projects its step onto.
PortfolioOptimisers.AbstractAllocationSet — Type
abstract type AbstractAllocationSet <: AbstractAlgorithmAbstract supertype for the Allocation Set of an online portfolio selection head, the set that contains each allocation of the recursion.
The head is OnlinePortfolioSelection, and it holds the set in its set field. The budget is one on each set, so ⟨w, x⟩ is the wealth factor that the formula of each rule assumes. Cash is an asset with price relative one, and the rule allocates it like any other asset.
Interfaces
In order to implement a new set kind, subtype AbstractAllocationSet with its constraint objects as part of the struct, and implement:
resolve_allocation_set(set::AbstractAllocationSet, N::Integer, strict::Bool, datatype::DataType) -> AbstractAllocationSet: The set with every estimator resolved to a value over theNassets, which the projection then reads.project(proj::AbstractProjectionGeometry, set::AbstractAllocationSet, q::AbstractVector, w::AbstractVector) -> AbstractVector: The projection onto the resolved set, for every geometry the set admits.rows_needed(set::AbstractAllocationSet) -> Union{Nothing, Integer}: The number of rows the set's constraints read at a step,0for a set that reads none.
Arguments
set: The set.N: The number of assets of the universe the set is resolved over.strict: Whether an unknown name in a set is an error.datatype: The element type a scalar bound is expanded in.
Returns
set::AbstractAllocationSet: The resolved set.
Related
PortfolioOptimisers.AbstractProgrammeAllocationSet — Type
abstract type AbstractProgrammeAllocationSet <: AbstractAllocationSetAbstract supertype for an Allocation Set whose projection is a programme, a bare JuMP model that holds the constraints of the set.
The programme lets the set own a risk constraint that the shared risk-measure builders write, as a RiskConstraintOwner beside the JuMP optimisers.
Interfaces
In order to implement a new programme set, subtype AbstractProgrammeAllocationSet, implement everything AbstractAllocationSet asks for, and implement:
risk_constraint_solver(set::AbstractProgrammeAllocationSet): The solver a Deferred Quantity of the set's risk measure is resolved against.
Related