Online (a): private API
PortfolioOptimisers.SampleBufferState — Type
struct SampleBufferState{__T_n, __T_off, __T_X, __T_A, __T_M, __T_F, __T_ne, __T_E, __T_iv, __T_ivpa, __T_P, __T_max_history} <: AbstractPartialFitStateCarries the observations an estimator keeps when its estimate has no exact incremental fold.
This is the buffer of the partial_fit! interface. It is a state like any other. It lives in the cache field of the estimator, it copies, it slices by asset, and obs_weights_view drops it. It holds the observations verbatim, NaN included. So the call with no data over the buffer gives the answer of a batch fit over the same rows, and the two have the same Coverage Universe by construction.
The buffer also holds the per-observation masks verbatim. A CoveragePolicy reads two facts from an active mask that the rows alone do not carry. A cell that is finite but inactive is excluded, and an asset that is active at one observation and inactive at the next is a delisting, not a holiday. A buffer that kept the rows and dropped the mask would give a different answer from the batch fit, with no warning. A is the active mask, and M is the estimation mask that the two regime-adjusted families read. Each is a backing matrix of the shape of X, or nothing. So a wrapped estimator folded under a policy gives the batch fit over the same window, as it does without a policy.
The buffer holds the factor observations on the same terms. A prior whose batch verb is prior(pe, X, F) regresses the asset returns on the factor returns, so its refit reads two matrices whose t-th rows are contemporaneous. F is the second matrix, a backing matrix of capacity × factors, or nothing. The same off and n index F and X, so the rows stay contemporaneous by construction. needs_factor_returns answers whether a fit reads F. That is a fact of the estimator tree, and the buffer records what the fold gives it. There is one buffer type, and a cap drops the factor rows with the other rows.
The buffer holds the Panel Fields of a time-varying AssetPanel on the same terms, for a prior whose estimator tree reads them. reads_panel_fields answers whether a tree reads them. Such a prior computes its factors from the Panel Fields at each row, so for it a Panel Field is sample and not fold context. P is the vector of the Panel Fields over the valid region alone. The same n and the same cap index P, and off does not. An append joins the rows with vcat of two Asset Panels, so it copies the rows that the buffer holds and costs O(n). A refit reads every row at each step, so this cost is smaller than the cost of its call with no data. A panel is a Result and nothing writes into its arrays, so the buffer holds the Panel Fields by reference, and a copy of the buffer shares them. A time-varying panel carries both masks, so a buffer that records P records A and M too.
The buffer holds the Exogenous Series on the same terms, for a prior whose estimator tree reads it. reads_exogenous_series answers whether a tree reads it. An observed factor reads its return from the series by name, so for such a prior the series is sample and not fold context. E is a backing matrix of capacity × series, and ne holds the name of each column. The buffer keeps every column, not only the columns that the tree names, so the Fold Context keeps no copy. The same off and n index E and X. So E means the Exogenous Series on the whole online step, as it does on a ReturnsResult.
The buffer holds the implied volatilities on the same terms as the masks, for every estimator. A row of iv belongs to the asset observation of the same row, so iv is a backing matrix of the shape of X, and ImpliedVolatility reads it beside the returns. Its regression reads windows that end at the last observation, so a new row moves every window, and no statistic of the regression folds. The call with no data refits it over the rows of the buffer. ivpa is one adjustment for each asset or one for all, so it has no observation axis, and the first append pins it.
The first append fixes whether the buffer records a mask, whether it records factor rows, whether it records the Exogenous Series, whether it records implied volatilities and whether it records Panel Fields, as it fixes the width and the element type. It also fixes the names of the series and the adjustment ivpa. A later fold that disagrees is refused with an error that names the disagreement, in both directions. A buffer that holds no observations records nothing about them, so the next fold seeds it again from its block.
The buffer marks the observations of a Shared Series gap in G, and keeps them. A Shared Series is a vector benchmark of a group that reads the Excess Frame, or the factor returns of a prior that reads them, and a batch fit drops an observation with a gap in one of them, see shared_series_view. An online step cannot drop the row, because the buffer of a prior and the Fold Context of its optimiser hold one row each for every observation, and the call with no data rebuilds the returns data from both. So the step keeps the row and marks it, and every fit through the buffer reads the rows of shared_series_buffer, which drops the marked rows. A cap counts every row, as the training window of a batch walk-forward counts the observations before the drop. A fold that marks no gap leaves G at nothing, so a buffer that never meets a gap records nothing.
An estimator whose cache holds this buffer is a refit. It has no recursion of its own, and its call with no data runs the batch verb over the rows of the buffer. Online seeds the buffer, and a wrapped estimator takes this route also when its statistic has an exact update. A fold-and-carry prior keeps its observations in one of these buffers too, inside a PriorCarryState. That prior folds its moments exactly. It keeps the rows because LowOrderPrior carries X for the scenario risk measures, and its buffer has no cap. max_history is the window of a refit. A capped buffer holds the last max_history observations, and the call with no data gives the batch fit over them.
The backing matrix has spare capacity, so an append costs amortised O(1). off is the number of rows before the valid region, and n is the length of the region. reserve_sample_buffer moves the region to the front of the backing matrix only when an append would go past its end. sample_buffer reads the valid region.
Fields
n: Number of observations folded into the state.
off: Number of rows ofXbefore the valid region. It rises when a capped buffer drops its oldest observation, and it returns to zero when the valid region moves to the front ofX.
X: Backing matrix of the buffer,capacity × assets. Rowsoff + 1tooff + nare the observations, in the order of the folds. The other rows are spare capacity, and their values have no meaning. The first append fixes the width and the element type.
A: Backing matrix of the active mask, of the shape ofX, ornothingwhen the buffer records no activity. Rowsoff + 1tooff + nare the mask of the observations, cell for cell with them. It is fixed by the first append, and it is what lets the call with no data tell a delisting from a holiday.
M: Backing matrix of the estimation mask, of the shape ofX, ornothingwhen the buffer records none. It is the second per-observation mask the batch verbs take, it is carried on the same terms asA, and only the two regime-adjusted families read it.
F: Backing matrix of the factor observations,capacity × factors, ornothingwhen the fold carries none. The sameoffandnindex it andX. The first append that carries it fixes its width and its element type.
ne: Names of the columns ofE, ornothingwhen the fold carries no Exogenous Series. The first append that carries the series fixes them.
E: Backing matrix of the Exogenous Series,capacity × series, ornothingwhen the fold carries none. The sameoffandnindex it andX. It holds every column of the series that the fold receives.
iv: Backing matrix of the implied volatilities,capacity × assets, ornothingwhen the fold carries none. The sameoffandnindex it andX.
ivpa: The implied volatility risk premium adjustment, one number or one entry per asset, ornothing. The first append pins it.
P: The Panel Fields of the observations, ornothingwhen the fold carries none. Each is a time-varying Panel Field over the valid region alone, sonand the cap index it andoffdoes not. The first append that carries them fixes their names and their kinds.
G: Backing vector of the Shared Series gaps,capacitylong, ornothingwhen no fold marked a gap. Entryoff + tistruewhen observationthas a gap in a Shared Series that the fit reads, so every fit through the buffer drops it, seeshared_series_buffer. The sameoffandnindex it andX. The field has a declared type and is not a type parameter, so the type of the buffer, and of every estimator that holds it, does not depend on whether a step met a gap. A step with no gap then compiles to the code it had before the marks existed.
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
SampleBufferState(; n::Integer = 0, off::Integer = 0, X::MatNum = Matrix{Float64}(undef, 0, 0), A::Option{<:AbstractMatrix{<:Bool}} = nothing, M::Option{<:AbstractMatrix{<:Bool}} = nothing, F::Option{<:MatNum} = nothing, ne::Option{<:VecStr} = nothing, E::Option{<:MatNum} = nothing, iv::Option{<:MatNum} = nothing, ivpa::Option{<:Num_VecNum} = nothing, P::Option{<:AbstractVector} = nothing, G::Option{<:AbstractVector{Bool}} = nothing, max_history::Option{<:Integer} = nothing) -> SampleBufferStateKeywords correspond to the struct's fields. The default is the empty seed that Online builds. It carries the cap and no observations. The first append replaces every backing matrix, so the width, the element type, the masks, the factor rows, the Exogenous Series, the implied volatilities and the Panel Fields come from the observations of that append.
Validation
n >= 0. ADomainErroris thrown otherwise.off >= 0. ADomainErroris thrown otherwise.off + n <= size(X, 1). ADimensionMismatchis thrown otherwise.max_history > 0when it is notnothing. ADomainErroris thrown otherwise.n <= max_historywhenmax_historyis notnothing. ADimensionMismatchis thrown otherwise.A,Mandiv, when they are notnothing, have the shape ofX. ADimensionMismatchis thrown otherwise.F, when it is notnothing, has as many rows asX. ADimensionMismatchis thrown otherwise.- The rules of
assert_buffer_series_shapehold forneandE. P, when it is notnothing, holds time-varying Panel Fields overnobservations and the assets ofX. The rules ofassert_buffer_panel_shapeapply.G, when it is notnothing, has one entry for each row ofX. ADimensionMismatchis thrown otherwise.
View parameters
When port_opt_view is called on this type, its fields are subset to the selected assets:
X: Sliced to the selected indices viaport_opt_view.A: Sliced to the selected indices viaport_opt_view.M: Sliced to the selected indices viaport_opt_view.F: Copied unchanged, because the selection indexes assets and this backing describes factors.ne,E: Copied unchanged, because the selection indexes assets and the Exogenous Series belongs to no asset.iv: Sliced to the selected indices viaport_opt_view.ivpa: Sliced to the selected indices when it is a vector, and kept when it is one number ornothing.P: Each Panel Field viewed over the selected assets withpanel_fields_view.G: Copied unchanged, because the selection indexes assets and a Shared Series gap belongs to the observation.
A buffer that holds no observations views to the empty seed with the same cap.
Examples
julia> PortfolioOptimisers.SampleBufferState(; max_history = 2)PortfolioOptimisers.SampleBufferState n ┼ Int64: 0 off ┼ Int64: 0 X ┼ 0×0 Matrix{Float64} A ┼ nothing M ┼ nothing F ┼ nothing ne ┼ nothing E ┼ nothing iv ┼ nothing ivpa ┼ nothing P ┼ nothing G ┼ nothing max_history ┴ Int64: 2Related
PortfolioOptimisers.assert_sample_buffer_state — Function
assert_sample_buffer_state(
n::Integer,
off::Integer,
X::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
max_history::Union{Nothing, Integer}
)
Refuses a sample buffer whose valid region does not sit inside its backing matrix.
Algorithm
- Refuse a negative
nand a negativeoff. - Refuse a valid region that runs past the last row of
X. - Return when
max_historyisnothing. - Refuse a non-positive
max_history, and refuse a valid region longer than it.
Arguments
n: Number of observations folded into the state.off: Number of rows ofXbefore the valid region.X: Backing matrix of the buffer.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.
Validation
n >= 0. ADomainErroris thrown otherwise.off >= 0. ADomainErroris thrown otherwise.off + n <= size(X, 1). ADimensionMismatchis thrown otherwise.max_history > 0when it is notnothing. ADomainErroris thrown otherwise.n <= max_historywhenmax_historyis notnothing. ADimensionMismatchis thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.assert_buffer_mask_shape — Function
assert_buffer_mask_shape(
X::AbstractMatrix,
A::Union{Nothing, AbstractMatrix{<:Bool}},
M::Union{Nothing, AbstractMatrix{<:Bool}}
)
assert_buffer_mask_shape(
X::AbstractMatrix,
A::Union{Nothing, AbstractMatrix{<:Bool}},
M::Union{Nothing, AbstractMatrix{<:Bool}},
iv::Union{Nothing, AbstractMatrix}
)
Refuses a per-observation mask, or a matrix of implied volatilities, whose shape is not the shape of the observations it belongs to.
A mask that a buffer holds matches its observations cell for cell, and a mask that a fold receives matches its block cell for cell. So one rule covers both. A mask is absent, or it has the shape of the matrix beside it. The implied volatilities follow the same rule, because each cell belongs to the asset observation of the same cell. The batch verbs run the same check on their own arguments.
Algorithm
- Skip a mask that is
nothing. With no policy, both masks arenothing. - Refuse a mask whose size is not
size(X), and name the mask. Apply the same rule toiv.
Arguments
X: The observations the masks belong to.A: The active mask, ornothing.M: The estimation mask, ornothing.iv: The implied volatilities, ornothing.
Validation
A,Mandiv, when they are notnothing, have the shape ofX. ADimensionMismatchis thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.assert_buffer_factor_shape — Function
assert_buffer_factor_shape(
X::AbstractMatrix,
F::Union{Nothing, AbstractMatrix}
)
Refuses a factor block whose rows are not the rows of the observations it belongs to.
A factor observation is contemporaneous with the asset observation of the same row. So a factor block that a fold receives has one row for each row of the block beside it, and the factor backing of a buffer has one row for each row of X. The check does not compare the two widths, because an asset count and a factor count are unrelated.
Algorithm
- Skip a factor block that is
nothing. With no factors, the block isnothing. - Refuse a factor block whose row count is not
size(X, 1).
Arguments
X: The observations the factor rows belong to.F: The factor rows, ornothing.
Validation
F, when it is notnothing, has as many rows asX. ADimensionMismatchis thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.assert_buffer_gap_shape — Function
assert_buffer_gap_shape(
X::AbstractMatrix,
G::Union{Nothing, AbstractVector{Bool}}
)
Refuses marks of the Shared Series gaps that are not one mark for each row of the observations.
A mark belongs to the observation of the same row, so the marks that a fold receives have one entry for each row of its block, and the backing vector of a buffer has one entry for each row of X.
Algorithm
- Skip marks that are
nothing. - Refuse marks whose length is not
size(X, 1).
Arguments
X: The observations that the marks belong to.G: The marks,trueat an observation with a Shared Series gap, ornothing.
Validation
G, when it is notnothing, has one entry for each row ofX. ADimensionMismatchis thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.assert_buffer_series_shape — Function
assert_buffer_series_shape(
X::AbstractMatrix,
ne::Union{Nothing, AbstractVector{<:AbstractString}},
E::Union{Nothing, AbstractMatrix}
)
Refuses an Exogenous Series whose rows are not the rows of the observations it belongs to, or whose names do not name its columns.
A row of the series is contemporaneous with the asset observation of the same row, as a factor row is. The names travel with the series, so the two are both absent or both present, and there is one name for each column.
Algorithm
- Refuse names without a series, and a series without names.
- Skip a series that is
nothing. - Refuse a series whose row count is not
size(X, 1), and names whose count is not the column count of the series.
Arguments
X: The observations the series belongs to.ne: The names of the series, ornothing.E: The series,observations × series, ornothing.
Validation
neandEare bothnothing, or neither is. AnArgumentErroris thrown otherwise.E, when it is notnothing, has as many rows asX, andlength(ne) == size(E, 2). ADimensionMismatchis thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.buffer_rows_view — Function
buffer_rows_view(M::Nothing, rows) -> Nothing
buffer_rows_view(M::AbstractMatrix, rows) -> SubArray
buffer_rows_view(G::AbstractVector, rows) -> SubArrayReads a row range out of a per-observation backing, and passes a backing that is not there through.
The buffer slices a mask or the factor rows on the observation axis only through this function, so the nothing case has one method. sample_buffer_kwargs, factor_buffer and merge_states read the valid region of a stored backing with it, and partial_fit! truncates an incoming block with it.
Arguments
M: The backing to slice, ornothing. A vector is the backing of the marks of the Shared Series gaps, one entry per row.rows: The rows to keep.
Returns
M: The rows of the backing, ornothing.
Related
PortfolioOptimisers.sample_buffer — Function
sample_buffer(state::SampleBufferState)
sample_buffer(est)Reads the observations a sample buffer holds, observations × assets.
This function reads the rows out of a SampleBufferState. It is a view of the valid region of the backing matrix, in the order of the folds, so a refit reads it with no copy. The estimator form reads the state from the cache field, and it refuses an estimator that carries no buffer.
Arguments
state: The buffer to read.est: Estimator whosecachefield carries the buffer.
Validation
est.cacheholds aSampleBufferState. AnArgumentErroris thrown otherwise.
Returns
X::SubArray: The observations the buffer holds,observations × assets.
Related
sample_buffer(state::PriorCarryState) -> Any
Reads the observations that a PriorCarryState carries, observations × assets.
Arguments
state: The carry state to read.
Returns
X::SubArray: The observations that the state carries, in the order of the fold.
Related
PortfolioOptimisers.sample_buffer_kwargs — Function
sample_buffer_kwargs(state::SampleBufferState) -> NamedTuple
Reads the per-observation masks a sample buffer holds, as the keywords a batch verb takes.
sample_buffer gives the rows, and this function gives the masks of those rows. The call with no data runs the batch verb on the rows and splats these keywords into the call, so the wrapped answer is the unwrapped answer over the same window. A buffer that records no mask gives an empty set of keywords, and the arm then makes the same call as with no policy. The branch reads fields of concrete type, so the compiler resolves it.
Algorithm
- Slice each stored mask to the valid region with
buffer_rows_view. - Name the masks that are there, and omit the ones that are not.
Arguments
state: The buffer to read.
Returns
kwargs::NamedTuple: Theactive_maskandestimation_maskkeywords the buffer holds, of which either or both may be absent.
Related
PortfolioOptimisers.factor_buffer — Function
factor_buffer(state::SampleBufferState) -> Any
Reads the factor observations a sample buffer holds, observations × factors, or nothing when it holds none.
This is the third function that reads the buffer out, with sample_buffer and sample_buffer_kwargs. A refit whose batch verb reads a factor matrix takes it from here, as the second positional argument of that verb. Its t-th row is contemporaneous with the t-th row of sample_buffer, because the same off and n index the two backings. A buffer that records no factor rows gives nothing, which is the value that the batch verb of a prior with no factors receives. The branch reads a field of concrete type, so the compiler resolves it.
Arguments
state: The buffer to read.
Returns
F: The factor observations the buffer holds, as a view of the valid region, ornothing.
Related
PortfolioOptimisers.exogenous_buffer_kwargs — Function
exogenous_buffer_kwargs(
state::SampleBufferState
) -> Union{@NamedTuple{}, NamedTuple{(:ne, :E), <:Tuple{Any, Any}}}
Reads the Exogenous Series a sample buffer holds, as the keywords a batch verb takes.
This is the fourth function that reads the buffer out. The call with no data of a refit splats these keywords into the batch verb, as prior(pe, rd) passes rd.ne and rd.E. The Fold Context reads them too, when the prior owns the series. Each row of E is contemporaneous with the row of sample_buffer of the same index, because the same off and n index the two backings. A buffer that records no series gives an empty set of keywords. The branch reads a field of concrete type, so the compiler resolves it.
Arguments
state: The buffer to read.
Returns
kwargs::NamedTuple:neandE, the names and a view of the valid region of the series, or an emptyNamedTuple.
Related
PortfolioOptimisers.implied_volatility_buffer_kwargs — Function
implied_volatility_buffer_kwargs(
state::SampleBufferState
) -> Union{@NamedTuple{}, NamedTuple{(:iv, :ivpa), <:Tuple{Any, Any}}}
Reads the implied volatilities a sample buffer holds, and the pinned adjustment, as the keywords a batch verb takes.
This is the fifth function that reads the buffer out. The call with no data of a refit splats these keywords into the batch verb, as prior(pe, rd) passes rd.iv and rd.ivpa, and the Fold Context reads them back into the ReturnsResult that it rebuilds. Each row of iv belongs to the row of sample_buffer of the same index, because the same off and n index the two backings. A buffer that records neither gives an empty set of keywords.
Arguments
state: The buffer to read.
Returns
kwargs::NamedTuple:iv, a view of the valid region of the implied volatilities ornothing, andivpa, or an emptyNamedTuple.
Related
PortfolioOptimisers.buffer_gap_marks — Function
buffer_gap_marks(state::SampleBufferState) -> Any
Reads the marks of the Shared Series gaps of the valid region of a SampleBufferState.
A buffer with no marks has no gap, so it gives false for each of its observations. That answer allocates a vector, so a reader on the path of every step tests isnothing(state.G) first, as buffer_fit_count, buffer_fits_none and shared_series_buffer do. merge_buffer_gaps reads it only when one of the two buffers has marks, and the merge copies every row anyway.
Arguments
state: The buffer to read.
Returns
marks::AbstractVector{Bool}: One mark for each observation of the buffer,trueat an observation with a Shared Series gap.
Related
PortfolioOptimisers.buffer_fit_count — Function
buffer_fit_count(state::SampleBufferState) -> Any
Count the observations of a SampleBufferState that a fit keeps, the rows that shared_series_buffer returns.
A reader that holds a history of the fitted observations beside the buffer, as the carry of a CrossSectionalFactorPrior does, indexes that history by this count and not by n, because the history never holds an observation with a Shared Series gap.
Arguments
state: The buffer to read.
Returns
n::Int: The number of observations of the buffer with no Shared Series gap.
Related
PortfolioOptimisers.buffer_kept_rows — Function
buffer_kept_rows(
state::SampleBufferState
) -> Union{Nothing, Vector{Int64}}
Return the observations of a SampleBufferState that a fit keeps, or nothing when it keeps every observation.
A fit through the buffer drops each observation with a Shared Series gap, see shared_series_buffer, so it counts the position of a row among the kept observations. Kept row k is observation rows[k] of the buffer. A reader that records the position of a fitted row maps it through rows, as shared_series_record does. A buffer with no gap answers nothing and allocates nothing.
Arguments
state: The buffer to read.
Returns
rows::Option{Vector{Int}}: The observations of the buffer with no Shared Series gap, ornothingwhen no observation has a gap.
Related
PortfolioOptimisers.buffer_fits_none — Function
buffer_fits_none(state::SampleBufferState) -> Bool
Answer true when every observation of a SampleBufferState has a Shared Series gap, so a fit through the buffer keeps no observation.
A reader that fits on the buffer after each step, as the Choice Rule of a refit does, asks this first, because shared_series_buffer refuses such a buffer and the first steps of a run can hold only gaps. A buffer with no marks answers false at once and allocates nothing, so the step of a buffer that never meets a gap costs what it cost before the marks existed. A buffer that holds no observation and no mark answers false too, as it did before.
Arguments
state: The buffer to read.
Returns
ans::Bool: Whether the buffer has marks and keeps no observation.
Related
PortfolioOptimisers.shared_series_buffer — Function
shared_series_buffer(
state::SampleBufferState
) -> SampleBufferState
Return the buffer that a fit reads, with the observations of a Shared Series gap dropped.
This is the buffer form of shared_series_view. An online step keeps an observation with a Shared Series gap in the buffer and marks it in G, because the buffer of a prior and the Fold Context of its optimiser hold one row each for every observation, see SampleBufferState. A fit drops the observation, as the batch fit over the same rows drops it at its entry. So every reader that fits on the rows of the buffer of a prior reads this buffer, and the call with no data gives the batch fit over the same observations. A reader that rebuilds the returns data, returns_result, reads the buffer itself, because the batch fit that it hands the data to drops the same observations again.
The rows are copied. The masks, the factor rows, the Exogenous Series, the implied volatilities and the Panel Fields keep the same rows. The result has no marks, so the function is idempotent.
Algorithm
- Return
statewhen it has no marks, which allocates nothing, or when no observation of its valid region is marked. - Find the observations that are not marked, and refuse a buffer that has none.
- Copy the rows of the observations into a buffer of their own, with the same cap.
Arguments
state: The buffer to read.
Validation
- At least one observation of the buffer has no Shared Series gap. An
IsEmptyErroris thrown otherwise.
Returns
state::SampleBufferState:stateitself when it has no gap, and otherwise a buffer of its observations with no gap.
Related
PortfolioOptimisers.assert_sample_buffer — Method
assert_sample_buffer(
est::Union{AbstractEstimator, CovarianceEstimator}
)
Returns the sample buffer an estimator carries, and refuses an estimator that carries none.
The buffering arm of partial_fit! reads its state through this function. So an estimator that was never wrapped in Online gets a message that names the wrapper, not a MethodError. An estimator with no cache field gets the same message. An unresolved Online has a method of its own, because it does not lack a buffer. It lacks the warm-up that seeds one.
Arguments
est: Estimator whosecachefield carries the buffer.
Validation
esthas acachefield holding aSampleBufferState. AnArgumentErroris thrown otherwise.
Returns
state::SampleBufferState: The buffer the estimator carries.
Related
PortfolioOptimisers.sample_buffer_seed — Function
sample_buffer_seed(
cache::Union{Nothing, SampleBufferState}
) -> SampleBufferState
Returns the SampleBufferState a carry folds into, seeding an empty one when the estimator carries none.
The seed has its own function, so the fold is one line and the branch on the cache field has one method. A family that carries its observations calls fold_buffer, which is this seed followed by the fold. The seed has no cap, because a cap is configuration, and Online carries it.
Arguments
cache: The buffer the estimator carries, ornothing.
Returns
state::SampleBufferState: The buffercacheholds, or an empty uncapped buffer.
Related
PortfolioOptimisers.fold_buffer — Function
fold_buffer(cache::Option{<:SampleBufferState}, x::VecNum, f::Option{<:VecNum} = nothing; kwargs...)
fold_buffer(cache::Option{<:SampleBufferState}, X::MatNum, F::Option{<:MatNum} = nothing; dims::Int = 1, kwargs...)Folds observations into a sample buffer, seeding an empty one when the estimator carries none.
A carry calls this function inside its own partial_fit! method. The carry folds its estimate exactly through its members, and it gives its observations to this function. The function is sample_buffer_seed followed by partial_fit!. The carry gives the masks and the factor rows of the fold with the observations, and the buffer records them beside their rows.
Arguments
cache: The buffer the estimator carries, ornothing.x: One observation, whose entries are the assets.f: The contemporaneous factor observation, whose entries are the factors, ornothing.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.F: Factor observations to fold, oriented asXis, ornothing.dims: Dimension along which to perform the computation.kwargs...: Theactive_mask, theestimation_mask, the Exogenous SeriesneandE, and the implied volatilitiesivandivpaof the fold, forwarded topartial_fit!.
Returns
state::SampleBufferState: The buffer after the last observation.
Related
PortfolioOptimisers.assert_buffer_factor_width — Function
assert_buffer_factor_width(B::Nothing, Fo) -> Nothing
assert_buffer_factor_width(B::AbstractMatrix, Fo::AbstractMatrix) -> NothingRefuses a factor block whose width is not the width the first factor append fixed.
This is the width check of X, for the factor backing, which can be absent. A buffer that records no factor rows has no width to compare with. assert_buffer_presence_agreement runs first and refuses a block that gives factor rows to such a buffer, so the nothing method runs only when Fo is absent too.
Arguments
B: The factor backing the buffer holds, ornothing.Fo: The oriented factor block, ornothing.
Validation
size(B, 2) == size(Fo, 2)when the buffer records factor rows. ADimensionMismatchis thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.assert_buffer_series_names — Function
assert_buffer_series_names(ne::Nothing, neo) -> Nothing
assert_buffer_series_names(ne::VecStr, neo::VecStr) -> NothingRefuses an Exogenous Series whose names are not the names the first append fixed.
A consumer reads a column of the series by its name, so a buffer whose columns change their names between two rows gives a column with two meanings. The first append that carries the series fixes the names, as ReturnsBufferState pins them. assert_buffer_presence_agreement runs first, so the nothing method runs only when the block carries no series either.
Arguments
ne: The names the buffer records, ornothing.neo: The names of the incoming block, ornothing.
Validation
neo == newhen the buffer records a series. AnArgumentErroris thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.assert_buffer_presence_agreement — Function
assert_buffer_presence_agreement(
M::Union{Nothing, AbstractArray},
Mo::Union{Nothing, AbstractArray},
name::AbstractString
)
Refuses a fold whose masks, factor rows, Exogenous Series or Panel Fields disagree with what the buffer records.
This is the mixture rule of the buffer. It refuses the fold, because neither way to resolve the mixture gives a correct answer. A buffer that dropped an incoming mask would fit a held gap that the policy excludes, and it would read each delisting as a holiday. The mask exists to prevent that wrong answer. A buffer that made up a mask for its earlier rows would state an activity that it never saw. The same rule holds for the factor rows. A buffer with factor rows for some observations and not for others describes no regression, and the buffer cannot make up the missing rows. A prior that reads the Panel Fields computes its factors from them at every row, so a buffer that holds them for some rows and not for others gives it no complete panel. The same holds for the Exogenous Series that an observed factor reads at every fitted row. So the first append fixes what a buffer records, and a caller that wants a change starts a new buffer.
Arguments
M: The backing the buffer records, ornothing.Mo: The same backing of the incoming block, ornothing.name: Name of the backing, for the message.
Validation
MandMoare bothnothing, or neither is. AnArgumentErroris thrown otherwise.
Returns
nothing.
Related
PortfolioOptimisers.seed_sample_buffer — Function
seed_sample_buffer(
state::SampleBufferState,
Xo::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
Ao::Union{Nothing, AbstractMatrix{<:Bool}},
Mo::Union{Nothing, AbstractMatrix{<:Bool}},
Fo::Union{Nothing, AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}},
ne::Union{Nothing, AbstractVector{<:AbstractString}},
Eo::Union{Nothing, AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}},
Po::Union{Nothing, AbstractVector}
) -> Any
Fills a buffer that holds no observations from a block, which fixes the width, the element type, the masks, the factor rows, the Exogenous Series and the Panel Fields.
partial_fit! calls it for the first append, and for each append to a buffer that holds no observations. Each backing matrix is an exact fit for the block, so a buffer that is folded once and read once allocates no spare row. Each array comes from similar on the argument that it holds, so the function chooses no element type. The Panel Fields are not copied, because nothing writes into the arrays of a panel.
Algorithm
- Replace
X,A,M,FandEwith copies of the block, its masks, its factor rows and its series, made byseed_buffer_array. - Replace
newith the names of the series, andPwith the Panel Fields of the block. - Set
offto zero andnto the row count of the block.
Arguments
state: The buffer to fill. It holds no observations.Xo: The oriented block.Ao: The oriented active mask of the block, ornothing.Mo: The oriented estimation mask of the block, ornothing.Fo: The oriented factor rows of the block, ornothing.ne: The names of the series of the block, ornothing.Eo: The oriented Exogenous Series of the block, ornothing.Po: The Panel Fields of the block, ornothing.
Returns
state::SampleBufferState: The buffer holding the block, its masks, its factor rows, its series and its Panel Fields.
Related
PortfolioOptimisers.seed_buffer_array — Function
seed_buffer_array(Mo::Nothing) -> Nothing
seed_buffer_array(Mo::AbstractMatrix) -> AbstractMatrixCopies an incoming block into a backing matrix of its own, and passes a backing that is not there through.
The block of a fold is an array of the caller, and the buffer lives after the call. A later fold writes into the backing matrix, so the buffer takes a copy, as Base.copy and port_opt_view do. Without the copy, the fold would change the array of the caller. similar reads the element type from the block, so an observation, a mask and a factor row each keep their own element type.
Arguments
Mo: The oriented block, mask or factor rows, ornothing.
Returns
M: A backing matrix holding the block, ornothing.
Related
PortfolioOptimisers.copy_buffer_rows! — Function
copy_buffer_rows!(M::Nothing, rows, Mo) -> Nothing
copy_buffer_rows!(M::AbstractMatrix, rows, Mo::AbstractMatrix) -> AbstractMatrixCopies an incoming backing into the rows of the buffer's backing matrix that were just made room for.
This is the optional part of the append. The two masks and the factor rows each take one line of the fold, and the nothing case has one method. assert_buffer_presence_agreement runs first, so the two arguments are both nothing or both matrices.
Arguments
M: The buffer's backing matrix for this mask or the factor rows, ornothing.rows: The rows ofMto write.Mo: The oriented mask or factor rows of the block, ornothing.
Returns
M: The rows written, ornothing.
Related
PortfolioOptimisers.seed_buffer_gaps — Function
seed_buffer_gaps(Go::Nothing) -> Nothing
seed_buffer_gaps(Go::AbstractVector{Bool}) -> Option{Vector{Bool}}Seeds the marks of the Shared Series gaps of a SampleBufferState from the first block that it holds.
A block with no gap seeds no marks, so a buffer that never meets a gap keeps G at nothing. A block with a gap seeds a copy of its marks, because a later fold writes into the backing vector.
Arguments
Go: The marks of the block,trueat an observation with a Shared Series gap, ornothing.
Returns
G::Option{Vector{Bool}}: The backing vector of the marks, ornothingwhen the block has no gap.
Related
PortfolioOptimisers.append_buffer_gaps — Function
append_buffer_gaps(state::SampleBufferState, rows, Go::Nothing) -> SampleBufferState
append_buffer_gaps(state::SampleBufferState, rows, Go::AbstractVector{Bool}) -> SampleBufferStateWrites the marks of the Shared Series gaps of a block into the rows of a SampleBufferState that were just made room for.
The marks have no presence rule, because a buffer with no marks has no gap. A buffer with no marks and a block with no gap keep no marks. The first block with a gap gives the buffer a backing vector of false marks for the rows before it, and a block with no marks writes false into a buffer that has them.
Arguments
state: The buffer, afterreserve_sample_buffermade room for the block.rows: The rows of the backing to write.Go: The marks of the block, ornothing.
Returns
state::SampleBufferState: The buffer with the marks of the block written.
Related
PortfolioOptimisers.reserve_sample_buffer — Function
reserve_sample_buffer(
state::SampleBufferState,
t::Integer
) -> Any
Makes room for t further observations in a SampleBufferState, and returns the buffer that has it.
This is the growth part of the fold of the buffer. It writes no observation. It drops the rows that the cap pushes out, moves the valid region to the front of the backing matrices, and allocates larger matrices when the front does not have enough room.
These steps make an append cost amortised O(1). A drop moves off and copies no row, so a capped buffer pays nothing for the observation that it drops. The masks, the factor rows and the series of that observation drop with it, because the same off and n index them. A compaction in place happens only when the valid region and the block fill at most half of the backing matrix. So it copies at most half of the matrix, and at least half of the matrix is free after the append. A growth at least doubles the capacity until the clamp at twice the cap stops it, and it copies fewer rows than the old capacity. So all the growths of a buffer copy fewer rows than its last capacity. A block longer than twice the capacity grows the matrix to fit the valid region and the block, and the next growth doubles it. A capped buffer never holds more than twice its cap, so a cap of w costs at most 2w rows.
Algorithm
- Drop the oldest observations the cap pushes out, by moving
offforward andnback. - Return when the valid region and the block already fit inside the backing matrix.
- Take a capacity of twice the current one, or of the room needed if that is larger, when the valid region and the block would fill more than half of the current one. Clamp it to twice the cap when a cap is set.
- Compact the observations, each mask, the factor rows, the series and the marks of the Shared Series gaps that the buffer records to that capacity with
compact_buffer_array, which allocates only when the capacity changes, and setoffto zero.
Arguments
state: The buffer to make room in.t: Number of observations about to be appended.
Returns
state::SampleBufferState: The buffer whose backing matrices have room fortrows after their valid region.
Related
PortfolioOptimisers.compact_buffer_array — Function
compact_buffer_array(B::Nothing, off, n, newcap) -> Nothing
compact_buffer_array(B::AbstractMatrix, off::Integer, n::Integer, newcap::Integer) -> AbstractMatrix
compact_buffer_array(G::AbstractVector, off::Integer, n::Integer, newcap::Integer) -> AbstractVectorMoves the valid region of one backing matrix to the front, allocating a matrix of newcap rows when the capacity changes. The backing vector of the marks of the Shared Series gaps has one entry per row, and compacts in the same way.
This is the array part of reserve_sample_buffer. The buffer carries five backing matrices with one index, and this function compacts each of them. A copy in place with an increasing row index is safe, because the destination row i is never after the source row off + i. So the loop reads each source row before a write can reach it.
Algorithm
- Take
DasBwhenBhasnewcaprows, and as a new matrix ofnewcaprows otherwise. - Copy row
off + iofBto rowiofD, forifrom 1 ton, one column at a time.
Arguments
B: The backing matrix to compact, ornothing.off: Number of rows before the valid region.n: Length of the valid region.newcap: Number of rows the compacted matrix has.
Returns
D: The compacted matrix, ornothing.
Related
PortfolioOptimisers.observation_row — Function
observation_row(m::Nothing) -> Nothing
observation_row(m::AbstractVector) -> AbstractMatrixReshapes one observation, its mask or its factor observation into a one-row block, and passes one that is not there through.
This is the vector part of the single-observation arm of partial_fit!. reshape makes no copy, so one observation with a policy or with factors allocates no more than one observation without them.
Arguments
m: One observation, one mask or one factor observation, ornothing.
Returns
M: The vector as a one-row block, ornothing.
Related
PortfolioOptimisers.merge_buffer_array — Function
merge_buffer_array(Ma::Nothing, Mb::Nothing) -> Nothing
merge_buffer_array(Ma::AbstractMatrix, Mb::AbstractMatrix) -> AbstractMatrixConcatenates the same mask, or the factor rows, of two buffers, and passes a backing neither records through.
This is the optional part of merge_states. assert_buffer_presence_agreement runs first, so the two arguments are both nothing or both matrices.
Arguments
Ma: The backing of the first buffer, ornothing.Mb: The backing of the second buffer, ornothing.
Returns
M: The two backings stacked, ornothing.
Related
PortfolioOptimisers.merge_buffer_gaps — Function
merge_buffer_gaps(
a::SampleBufferState,
b::SampleBufferState
) -> Any
Concatenates the marks of the Shared Series gaps of two buffers over their valid regions.
The marks have no presence rule, because a buffer with no marks has no gap. So two buffers with no marks give no marks, and a buffer with no marks gives false for each of its observations beside a buffer that has them.
Arguments
a: The buffer of the first block of observations.b: The buffer of the second block of observations.
Returns
G::Option{Vector{Bool}}: The marks of the rows ofafollowed by the marks of the rows ofb, ornothingwhen neither buffer has marks.
Related
PortfolioOptimisers.trim_merged_array — Function
trim_merged_array(M::Nothing, rows) -> Nothing
trim_merged_array(M::AbstractMatrix, rows) -> AbstractMatrix
trim_merged_array(G::AbstractVector, rows) -> AbstractVectorKeeps the rows a cap admits of a merged mask or of the merged factor rows, by index copy, and passes a backing that is not there through.
This is the cap part of merge_states. It copies the rows and does not take a view. A view would keep the whole concatenation in memory, with the rows that the cap drops, and the merged buffer would carry a backing of a different type from the backing that a fold makes.
Arguments
M: The merged backing, ornothing. A vector is the backing of the marks of the Shared Series gaps.rows: The rows the cap admits.
Returns
M: The admitted rows, ornothing.
Related
Base.copy — Method
copy(x::SampleBufferState) -> SampleBufferState
Copies a SampleBufferState, so the copy shares no array with the original.
This is the copy method of the AbstractPartialFitState interface, which partial_fit calls before it folds. It copies each backing matrix whole, spare capacity included. So the copy appends on the same terms as the original, and the same off and n index the masks, the factor rows, the series and the observations. The copy shares the Panel Fields and the names of the series with the original. Nothing writes into the arrays of a panel or into the names, and an append makes new arrays.
Arguments
x: The buffer to copy.
Returns
state::SampleBufferState: A fresh buffer, equal tox, whose backing matrices are fresh matrices and whose Panel Fields are the Panel Fields ofx.
Related
PortfolioOptimisers.copy_buffer_array — Function
copy_buffer_array(M::Nothing) -> Nothing
copy_buffer_array(M::AbstractArray) -> AbstractArrayCopies one backing matrix of a buffer, and passes a matrix that is not there through.
This is the nothing case of copy for the two masks, the factor rows, the series and the backing vector of the marks of the Shared Series gaps. Base.copy and port_opt_view use it to copy each optional field in one line.
Arguments
M: The backing matrix to copy, ornothing.
Returns
M: A fresh matrix equal to it, ornothing.
Related
PortfolioOptimisers.slice_buffer_mask — Function
slice_buffer_mask(M::Nothing, i) -> Nothing
slice_buffer_mask(M::AbstractMatrix, i) -> AbstractMatrixSlices one backing matrix of a buffer that has an asset axis to the selected assets, and passes a matrix that is not there through.
This is the per-asset part of port_opt_view for this state, so the slice is one line for each field. It slices the two masks and the implied volatilities. It copies by index, for the reason that the method states.
Arguments
M: The backing mask or implied volatilities to slice, ornothing.i: Index or indices of the assets to keep.
Returns
M: The matrix over the selected assets, ornothing.
Related