Simple variance and standard deviation
The variance is used throughout the library, it can be used as part of the expected return, covariance estimation, performance analysis, and constraint generation. It is trivial to compute the standard deviation from the variance, so we provide those too.
PortfolioOptimisers.SimpleVariance — Type
struct SimpleVariance{__T_me, __T_w, __T_corrected, __T_cvg, __T_cache} <: AbstractVarianceEstimatorComputes the marginal variance and standard deviation, optionally weighted and optionally bias-corrected.
me centres the data when no mean is supplied, w weights the observations, and corrected selects the bias correction. me reaches the matrix methods only: the vector methods leave the centring to Statistics.
w weights the whole estimate, so it reaches the centre as well as the deviations. The matrix methods send me through factory, which replaces the weights of me with w, and Statistics centres a weighted vector on its weighted mean. Both paths therefore answer the same number over the same data, and w wins over the weights that me carries. Pass mean for a centre that w does not describe.
Fields
me: Optional expected returns estimator. It is not needed when used on a vector. Ifnothingand used on a matrix, defaults toSimpleExpectedReturns.
w: Observation weights vectorobservations × 1.
corrected: Whether to apply Bessel's correction.
cvg: OptionalCoveragePolicy.nothingis the reduce-and-expand path of the Coverage Universe, in which an asset that is non-finite or inactive at any observation of the window isNaNthroughout the answer. A policy replaces it by available-case estimation: every cell is fitted on the observations at which the assets of that cell are all finite and active, each cell carries its own denominator, and an asset reaches the answer whereadmitssays so.
cache: Optional partial-fit state. It isnothinguntilpartial_fit!writes one, and the estimator's read-out verb reads it when the caller gives no data matrix. Each propagation channel does one thing with it:factorycarries it unchanged, because a factory call resolves configuration rather than the sample;port_opt_viewslices it to the selected assets by index copy, so the viewed estimator answers over those assets alone; andobs_weights_viewdrops it, because no slice of a state exists on the observation axis. A family whose state has no exact asset slice drops it on both axes and names the reason.
Constructors
SimpleVariance(; me::Option{<:AbstractExpectedReturnsEstimator} = SimpleExpectedReturns(), w::Option{<:ObsWeights} = nothing, corrected::Bool = true, cvg::Option{<:CoveragePolicy} = nothing, cache::Option{<:AbstractPartialFitState} = nothing) -> SimpleVarianceKeywords correspond to the struct's fields.
Validation
- If
wis notnothing,!isempty(w). corrected = trueneeds a weight type that carries a bias correction. See the bias-correction bullet ofvar(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...).
Propagated parameters
When factory is called on this type, the following @fprop-tagged fields are automatically propagated:
me: Recursively updated viafactory.w: Replaced with the incomingObsWeights.cache: Carried unchanged viafactory.
View parameters
When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:
me: Recursively viewed viaport_opt_view.cache: Sliced to the selected assets viaport_opt_view.
Observation weight parameters
When obs_weights_view is called on this type, the following fields are automatically indexed to the selected observations:
me: Recursively indexed viaobs_weights_view.w: Indexed to the selected observations viaobs_weights_view.cache: Dropped viaobs_weights_view, because no slice of a state exists on the observation axis.
Examples
julia> SimpleVariance()SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ nothing corrected ┴ Bool: truejulia> SimpleVariance(; w = StatsBase.Weights([0.2, 0.3, 0.5]), corrected = false)SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ StatsBase.Weights{Float64, Float64, Vector{Float64}}: [0.2, 0.3, 0.5] corrected ┴ Bool: falseRelated
AbstractVarianceEstimatorAbstractExpectedReturnsEstimatorSimpleExpectedReturnsStatsBase.AbstractWeightsstd(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...)std(ve::SimpleVariance, X::VecNum; mean = nothing, kwargs...)var(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...)var(ve::SimpleVariance, X::VecNum; mean = nothing)SimpleVarianceStatepartial_fit!factoryport_opt_viewobs_weights_view
Statistics.std — Method
Statistics.std(
ve::SimpleVariance,
X::MatNum;
dims::Int = 1,
mean = nothing,
kwargs...,
) -> ArrNumCompute the standard deviation using a SimpleVariance estimator for a matrix.
This method computes the standard deviation of the input matrix X using the configuration specified in ve.
Mathematical definition
\[\begin{align} \hat{\sigma}_j &= \sqrt{\hat{\sigma}^2_j}\,. \end{align}\]
Where:
- $\hat{\sigma}_j$: Estimated standard deviation of asset $j$.
- $\hat{\sigma}^2_j$: Estimated variance of asset $j$.
var(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...) defines $\hat{\sigma}^2_j$ in each of the four cases that ve.w and ve.corrected select.
Algorithm
- Check that
dimsis1or2. - When
meanisnothing, compute the centring vectormuwithve.me, afterfactorywritesve.winto it; otherwise takemufrommean. - Resolve the observation weights from
ve.wagainstX, givingw. - When
wisnothing, take the unweighted standard deviation ofXalongdims, centred onmu. - Otherwise take the standard deviation of
Xweighted bywalongdims, centred onmu.
$\hat{\mu}_j$ comes from ve.me, and ve.w reaches ve.me through factory. A SimpleVariance whose w is set therefore weights the centre and the squared deviations alike, so a vector and its one-column matrix answer the same number. Pass mean for any other centre.
Arguments
ve: Variance estimator.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.dims: Dimension along which to perform the computation.mean: Optional mean value to use for centering.kwargs...: Additional keyword arguments passed to the mean estimator.
Validation
dims in (1, 2).corrected = trueneeds a weight type that carries a bias correction. A plainStatsBase.Weightscarries none, andStatsBaseraises anArgumentError.
Returns
sd::ArrNum: Standard deviation vector ofX, reshaped to be consistent with the dimension along which the value is computed.
Examples
julia> sv = SimpleVariance()SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ nothing corrected ┴ Bool: truejulia> Xmat = [1.0 2.0; 3.0 4.0];julia> std(sv, Xmat; dims = 1)1×2 Matrix{Float64}: 1.41421 1.41421Related
Statistics.std — Method
std(
ve::SimpleVariance{Nothing},
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}};
dims,
mean,
kwargs...
) -> Any
SimpleVariance{Nothing} overload of std(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...). Uses SimpleExpectedReturns to compute the mean when none is provided, ignoring the me field.
Statistics.std — Method
Statistics.std(
ve::SimpleVariance,
X::VecNum;
mean = nothing
) -> NumberCompute the standard deviation using a SimpleVariance estimator for a vector.
This method computes the standard deviation of the input vector X using the configuration specified in ve.
Mathematical definition
var(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...) defines the variance in each of the four cases that ve.w and ve.corrected select, and this method returns its square root.
Algorithm
- Resolve the observation weights from
ve.wagainstX, givingw. - When
wisnothing, take the unweighted standard deviation ofX, centred onmean. - Otherwise take the standard deviation of
Xweighted byw, centred onmean.
The vector methods ignore ve.me: a mean of nothing reaches Statistics.std, which centres on the mean of X — the weighted mean when w is not nothing. The matrix methods resolve the centre from ve.me under the same ve.w, so the two paths answer the same number for the same data.
Arguments
ve: Variance estimator.X: Data vectorobservations × 1.mean: Optional mean value to use for centering.
Validation
corrected = trueneeds a weight type that carries a bias correction. A plainStatsBase.Weightscarries none, andStatsBaseraises anArgumentError.
Returns
sd::Number: Standard deviation ofX.
Examples
julia> sv = SimpleVariance()SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ nothing corrected ┴ Bool: truejulia> X = [1.0, 2.0, 3.0];julia> std(sv, X)1.0julia> svw = SimpleVariance(; w = StatsBase.Weights([0.2, 0.3, 0.5]), corrected = false)SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ StatsBase.Weights{Float64, Float64, Vector{Float64}}: [0.2, 0.3, 0.5] corrected ┴ Bool: falsejulia> std(svw, X)0.7810249675906654Related
Statistics.var — Method
Statistics.var(
ve::SimpleVariance,
X::MatNum;
dims::Int = 1,
mean = nothing,
kwargs...
) -> ArrNumCompute the variance using a SimpleVariance estimator for a matrix.
This method computes the variance of the input matrix X using the configuration specified in ve.
Mathematical definition
Unweighted, corrected = true:
\[\begin{align} \hat{\sigma}^2_j &= \frac{1}{T-1} \sum_{t=1}^{T} (r_{tj} - \hat{\mu}_j)^2\,. \end{align}\]
Unweighted, corrected = false:
\[\begin{align} \hat{\sigma}^2_j &= \frac{1}{T} \sum_{t=1}^{T} (r_{tj} - \hat{\mu}_j)^2\,. \end{align}\]
Weighted:
\[\begin{align} \hat{\sigma}^2_j &= \frac{\sum_{t=1}^{T} w_t (r_{tj} - \hat{\mu}_j)^2}{\sum_{t=1}^{T} w_t - c}\,. \end{align}\]
Where:
- $\hat{\sigma}^2_j$: Estimated variance of asset $j$.
- $r_{tj}$: Return of asset $j$ at time $t$.
- $\hat{\mu}_j$: Estimated mean of asset $j$.
- $T$: Number of observations.
- $w_{t}$: Observation weight of observation $t$.
- $c$: Bias correction of the weighted denominator. It is fixed by the type of the weights, never by the estimator:
corrected = falsegives $c = 0$ for every type, andcorrected = truegives $c = 1$ forStatsBase.FrequencyWeights, $c = \sum_t w_t^2 / \sum_t w_t$ forStatsBase.AnalyticWeightsand $c = \sum_t w_t / T$ forStatsBase.ProbabilityWeights.
Algorithm
- Check that
dimsis1or2. - When
meanisnothing, compute the centring vectormuwithve.me, afterfactorywritesve.winto it; otherwise takemufrommean. - Resolve the observation weights from
ve.wagainstX, givingw. - When
wisnothing, take the unweighted variance ofXalongdims, centred onmu. - Otherwise take the variance of
Xweighted bywalongdims, centred onmu.
$\hat{\mu}_j$ comes from ve.me, and ve.w reaches ve.me through factory. A SimpleVariance whose w is set therefore weights the centre and the squared deviations alike, so a vector and its one-column matrix answer the same number. Pass mean for any other centre.
Arguments
ve: Variance estimator.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.dims: Dimension along which to perform the computation.mean: Optional mean value to use for centering.kwargs...: Additional keyword arguments passed to the mean estimator.
Validation
dims in (1, 2).corrected = trueneeds a weight type that carries a bias correction. A plainStatsBase.Weightscarries none, andStatsBaseraises anArgumentError.
Returns
vr::ArrNum: Variance vector ofX, reshaped to be consistent with the dimension along which the value is computed.
Examples
julia> sv = SimpleVariance()SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ nothing corrected ┴ Bool: truejulia> Xmat = [1.0 2.0; 3.0 4.0];julia> var(sv, Xmat; dims = 1)1×2 Matrix{Float64}: 2.0 2.0Related
Statistics.var — Method
var(
ve::SimpleVariance{Nothing},
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}};
dims,
mean,
kwargs...
) -> Any
SimpleVariance{Nothing} overload of var(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...). Uses SimpleExpectedReturns to compute the mean when none is provided, ignoring the me field.
Statistics.var — Method
Statistics.var(
ve::SimpleVariance,
X::VecNum;
mean = nothing
) -> NumberCompute the variance using a SimpleVariance estimator for a vector.
This method computes the variance of the input vector X using the configuration specified in ve.
Mathematical definition
var(ve::SimpleVariance, X::MatNum; dims::Int = 1, mean = nothing, kwargs...) defines the variance in each of the four cases that ve.w and ve.corrected select, and this method returns it for a single series.
Algorithm
- Resolve the observation weights from
ve.wagainstX, givingw. - When
wisnothing, take the unweighted variance ofX, centred onmean. - Otherwise take the variance of
Xweighted byw, centred onmean.
The vector methods ignore ve.me: a mean of nothing reaches Statistics.var, which centres on the mean of X — the weighted mean when w is not nothing. The matrix methods resolve the centre from ve.me under the same ve.w, so the two paths answer the same number for the same data.
Arguments
ve: Variance estimator.X: Data vectorobservations × 1.mean: Optional mean value to use for centering.
Validation
corrected = trueneeds a weight type that carries a bias correction. A plainStatsBase.Weightscarries none, andStatsBaseraises anArgumentError.
Returns
vr::Number: Variance ofX.
Examples
julia> sv = SimpleVariance()SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ nothing corrected ┴ Bool: truejulia> X = [1.0, 2.0, 3.0];julia> var(sv, X)1.0julia> svw = SimpleVariance(; w = StatsBase.Weights([0.2, 0.3, 0.5]), corrected = false)SimpleVariance me ┼ SimpleExpectedReturns │ w ┴ nothing w ┼ StatsBase.Weights{Float64, Float64, Vector{Float64}}: [0.2, 0.3, 0.5] corrected ┴ Bool: falsejulia> var(svw, X)0.61Related
Incremental fit
The sample variance folds one observation at a time, so a long history need not be held or re-read. partial_fit! returns a new estimator whose cache field carries the state, and var reads the fit off the estimator alone.
PortfolioOptimisers.partial_fit! — Method
partial_fit!(
state::SimpleVarianceState,
x::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Any
SimpleVarianceState method of partial_fit!. Folds one observation into the running count, mean and per-asset accumulator.
Mathematical definition
\[\begin{align} n &\leftarrow n + 1\\ \boldsymbol{d} &= \boldsymbol{x} - \boldsymbol{\mu}\\ \boldsymbol{\mu} &\leftarrow \boldsymbol{\mu} + \frac{\boldsymbol{d}}{n}\\ \boldsymbol{M} &\leftarrow \boldsymbol{M} + \boldsymbol{d} \odot (\boldsymbol{x} - \boldsymbol{\mu})\, . \end{align}\]
Where:
- $n$: observation count.
- $\boldsymbol{x}$: the observation.
- $\boldsymbol{\mu}$: the running mean.
- $\boldsymbol{d}$: deviation of the observation from the mean before the fold.
- $\boldsymbol{M}$: the running per-asset accumulator.
The last line reads $\boldsymbol{\mu}$ after the third line moved it, where $\boldsymbol{d}$ read it before. That asymmetry is Welford's, and it is what keeps the accumulator non-negative.
Algorithm
- Refuse an observation whose length is not the number of assets the state describes.
- Add one to the count.
- Take the deviation of the observation from the mean before the fold, giving
d. - Move
muin place alongd, by the reciprocal of the new count. - Add
dtimes the deviation from the mean after the fold toM, in place. - Rebind the count with
Accessors.@reset, and return the state.
PortfolioOptimisers.partial_fit! — Method
partial_fit!(
est::Union{AbstractEstimator, CovarianceEstimator},
X::Union{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}}};
dims,
active_mask,
estimation_mask
) -> Any
Folds observations into the sample buffer an estimator carries.
The buffering arm of partial_fit!, and the method every estimator carrying a SampleBufferState reaches. A family that folds exactly writes methods of its own, and each of them narrows the cache type parameter of its own estimator to the state that fold reads, so a buffer never meets them and this method is what remains. The state's type is therefore the whole route, and nothing refuses the step.
It is one method over both arms of the interface rather than two, because the families that refuse the step declare one method over both arms too, and a pair of narrower methods here would be ambiguous against each of them. So the arm is chosen by the type of X inside the body, which is statically resolved at every call site.
A buffer carries the per-observation masks beside the observations, so a CoveragePolicy mask threads through the wrapper as it does through an estimator's own accumulator, and the read-out hands it back to the batch verb. A wrapped estimator folded under a policy therefore answers what a batch fit over the same window under the same policy answers, and the unwrapped and wrapped paths agree.
Algorithm
- Read the buffer out of the
cachefield withassert_sample_buffer, which refuses an estimator that was never wrapped inOnline. - Fold a matrix and its masks through the block arm of
partial_fit!, and a vector and its masks through the single-observation arm. - Rebind
est.cachewithAccessors.@reset, and return the estimator.
Arguments
est: Estimator whose buffer is folded forward.X: Observations to fold. A matrix holds one observation per row whendims == 1, and one per column whendims == 2. A vector is a single observation across the assets, anddimsis ignored.dims: Dimension along which to perform the computation.active_mask: The active mask of the block, of the shape ofX, or of one entry per asset whenXis one observation, ornothing.estimation_mask: The estimation mask, on the same terms asactive_mask.
Validation
estcarries aSampleBufferState. AnArgumentErroris thrown otherwise.- The masks, when they are not
nothing, have the shape ofX. ADimensionMismatchis thrown otherwise. - A buffer holding observations is given the masks it already records. An
ArgumentErroris thrown otherwise. dims in (1, 2).
Returns
est: The estimator, with itscachefield rebound to the buffer after the last observation.
Related
PortfolioOptimisers.partial_fit! — Method
partial_fit!(
est::Union{AbstractEstimator, CovarianceEstimator},
X::Union{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}}};
dims,
active_mask,
estimation_mask
) -> Any
Folds observations into the sample buffer an estimator carries.
The buffering arm of partial_fit!, and the method every estimator carrying a SampleBufferState reaches. A family that folds exactly writes methods of its own, and each of them narrows the cache type parameter of its own estimator to the state that fold reads, so a buffer never meets them and this method is what remains. The state's type is therefore the whole route, and nothing refuses the step.
It is one method over both arms of the interface rather than two, because the families that refuse the step declare one method over both arms too, and a pair of narrower methods here would be ambiguous against each of them. So the arm is chosen by the type of X inside the body, which is statically resolved at every call site.
A buffer carries the per-observation masks beside the observations, so a CoveragePolicy mask threads through the wrapper as it does through an estimator's own accumulator, and the read-out hands it back to the batch verb. A wrapped estimator folded under a policy therefore answers what a batch fit over the same window under the same policy answers, and the unwrapped and wrapped paths agree.
Algorithm
- Read the buffer out of the
cachefield withassert_sample_buffer, which refuses an estimator that was never wrapped inOnline. - Fold a matrix and its masks through the block arm of
partial_fit!, and a vector and its masks through the single-observation arm. - Rebind
est.cachewithAccessors.@reset, and return the estimator.
Arguments
est: Estimator whose buffer is folded forward.X: Observations to fold. A matrix holds one observation per row whendims == 1, and one per column whendims == 2. A vector is a single observation across the assets, anddimsis ignored.dims: Dimension along which to perform the computation.active_mask: The active mask of the block, of the shape ofX, or of one entry per asset whenXis one observation, ornothing.estimation_mask: The estimation mask, on the same terms asactive_mask.
Validation
estcarries aSampleBufferState. AnArgumentErroris thrown otherwise.- The masks, when they are not
nothing, have the shape ofX. ADimensionMismatchis thrown otherwise. - A buffer holding observations is given the masks it already records. An
ArgumentErroris thrown otherwise. dims in (1, 2).
Returns
est: The estimator, with itscachefield rebound to the buffer after the last observation.
Related
Statistics.var — Method
Statistics.var(
ve::SimpleVariance,
state::SimpleVarianceState
) -> VecNum
Statistics.var(
ve::SimpleVariance
) -> VecNumRead the variance of an incremental fit out of a SimpleVarianceState.
The two-argument method reads a state the caller holds, and the one-argument method reads the state the cache field of ve carries. Both return the per-asset variance as a vector, assets × 1, where the batch method over a matrix returns a row when dims = 1.
Mathematical definition
\[\begin{align} \hat{\sigma}^2_j &= \frac{M_j}{n - c}\,. \end{align}\]
Where:
- $\hat{\sigma}^2_j$: Estimated variance of asset $j$.
- $M_j$: running accumulator of asset $j$.
- $n$: observation count.
- $c$: one when
ve.correctedholds, and zero otherwise.
Algorithm
- Refuse a configuration no incremental fit reproduces, with
assert_partial_fittable. - Take the divisor
n - c, and return a vector ofNaNwhen it is below one, in the waymin_obsreads an asset with too few observations. - Otherwise divide the accumulator by the divisor.
Arguments
ve: Variance estimator.state: The state to read.
Validation
vecarries no observation weights. AnArgumentErroris thrown otherwise.ve.meis aSimpleExpectedReturnscarrying no observation weights, ornothing. AnArgumentErroris thrown otherwise.ve.cacheis notnothing, for the one-argument method. AnArgumentErroris thrown otherwise.
Returns
vr::VecNum: Per-asset variance of the fit,assets × 1, orNaNwhere the state holds too few observations.
Examples
julia> ve = foldl(partial_fit!, eachrow([1.0 2.0; 3.0 4.0]); init = SimpleVariance());julia> var(ve)2-element Vector{Float64}: 2.0 2.0Related
PortfolioOptimisers.port_opt_view — Method
port_opt_view(
x::SimpleVarianceState,
i,
args...
) -> Union{SimpleVarianceState{_A, _B, _C, Nothing} where {_A, _B, _C}, SimpleVarianceState{_A, _B, _C, __T_cvg} where {_A, _B, _C, __T_cvg<:CoverageCounts}}
Slices a SimpleVarianceState to the selected assets.
The Welford accumulator of one asset reads that asset's observations alone, and reads no other asset. So the slice of the state is the state of the sliced universe, entry for entry, and the count is shared by every asset and passes through. The slice copies by index and does not view: a later partial_fit! on the viewed estimator would otherwise write through into the arrays of the estimator the view was taken from.
Arguments
x: The state to slice.i: Index or indices of the assets to keep.args...: Additional positional arguments (ignored).
Returns
state::SimpleVarianceState: The state of the same sample over the selected assets.
Related
PortfolioOptimisers.merge_states — Method
merge_states(
a::SimpleVarianceState,
b::SimpleVarianceState
) -> Union{SimpleVarianceState{_A, _B, _C, Nothing} where {_A, _B, _C}, SimpleVarianceState{_A, _B, _C, __T_cvg} where {_A, _B, _C, __T_cvg<:(CoverageCounts{_A, Nothing} where _A)}}
Folds two SimpleVarianceState fitted on disjoint blocks into the state of the concatenated block.
Algorithm
- Refuse the pair with
assert_mergeable_states. - Fold the counts, the means and the accumulators with
chan_merge, whose elementwise method reads a per-asset accumulator.
Arguments
a: The state of the first block of observations.b: The state of the second block of observations.
Validation
aandbpassassert_mergeable_states.
Returns
state::SimpleVarianceState: The state the two blocks give when they are fitted as one block.
Related
Available-case fit
With a CoveragePolicy in its cvg field the estimator fits each asset on that asset's own finite and active observations, and PortfolioOptimisers.coverage_variance routes between that arm and the Coverage Universe one.
PortfolioOptimisers.partial_fit! — Method
partial_fit!(
state::SimpleVarianceState,
x::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
_::Nothing,
_::Union{Nothing, AbstractVector{<:Bool}}
) -> Any
Nothing method of the coverage arm of partial_fit! for a SimpleVarianceState. An estimator that carries no CoveragePolicy folds through partial_fit!(state::SimpleVarianceState, x::VecNum), and the active mask is ignored.
Related
PortfolioOptimisers.partial_fit! — Method
partial_fit!(
state::SimpleVarianceState,
x::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
cvg::CoveragePolicy,
active_mask::Union{Nothing, AbstractVector{<:Bool}}
) -> Any
CoveragePolicy method of the coverage arm of partial_fit! for a SimpleVarianceState. Folds one observation into the running per-asset count, mean and accumulator, reading each asset's own observations alone.
Mathematical definition
\[\begin{align} \nu_j &\leftarrow \nu_j + 1\\ d_j &= r_{tj} - \mu_j\\ \mu_j &\leftarrow \mu_j + \frac{d_j}{\nu_j}\\ M_j &\leftarrow M_j + d_j (r_{tj} - \mu_j)\, , \end{align}\]
for every asset $j$ that is finite and active at observation $t$, and no line at all for an asset that is not. Where:
- $\nu_j$: the number of observations at which asset $j$ was finite and active.
- $r_{tj}$: Return of asset $j$ at time $t$.
- $\mu_j$: the running mean of asset $j$.
- $d_j$: the deviation of asset $j$ from its mean before the fold.
- $M_j$: the running second-moment accumulator of asset $j$.
The last line reads $\mu_j$ after the third line moved it, which is Welford's asymmetry, so the accumulator is exact per asset and a skipped observation costs the asset nothing.
Algorithm
- Refuse an observation whose length is not the number of assets the state describes.
- Read the valid assets and the newly inactive ones with
coverage_valid. - Apply the algorithm's fold-time rule with
fold_inactive!. - Fold each valid asset's return into its own count, mean and accumulator.
- Move the per-asset bookkeeping on with
coverage_step!, add one to the observation count, and return the state.
Arguments
state: The state to fold into, mutated in place.x: One observation, one entry per asset.cvg: The policy the estimator carries.active_mask: The active mask of the Asset Panel at this observation, ornothing.
Validation
length(x)is the number of assets the state describes. ADimensionMismatchis thrown otherwise.
Returns
state::SimpleVarianceState: The state after the observation.
Related
PortfolioOptimisers.fold_inactive! — Method
fold_inactive!(
_::ResetCoverage,
state::SimpleVarianceState,
ni::AbstractVector{<:Bool}
) -> SimpleVarianceState
SimpleVarianceState method of fold_inactive! under ResetCoverage. Zeroes the count, the centre, the running mean and the accumulator of every asset that has just gone inactive, so that a relisting starts the asset cold. The centre of a per-asset state is nothing, because its mu is already the cell's centre, and coverage_reset! passes that through.
Related