Regime Adjusted Exponential Weighted Variance

Types

PortfolioOptimisers.RegimeAdjustedMethodType
abstract type RegimeAdjustedMethod <: AbstractEstimator

Abstract supertype for all regime adjustment methods.

All concrete subtypes should subtype RegimeAdjustedMethod and implement the regime_multiplier interface.

Interfaces

In order to implement a new regime adjustment method that works seamlessly with the library, subtype RegimeAdjustedMethod and implement the following method:

regime_multiplier interface

  • regime_multiplier(method::RegimeAdjustedMethod, regime_state::Number) -> Number: Computes the variance scaling multiplier from the smoothed regime state.

Arguments

  • method: The concrete regime adjustment method instance.
  • regime_state::Number: The current smoothed regime state value.

Returns

  • mult::Number: The multiplicative scaling factor applied to the variance.

Examples

julia> struct MyRegimeMethod <: PortfolioOptimisers.RegimeAdjustedMethod endjulia> function PortfolioOptimisers.regime_multiplier(::MyRegimeMethod, s::Number)           return abs(s)       endjulia> PortfolioOptimisers.regime_multiplier(MyRegimeMethod(), -1.5)1.5

Related

source
PortfolioOptimisers.LogRegimeAdjustedType
struct LogRegimeAdjusted{__T_x, __T_y, __T_kappa} <: RegimeAdjustedMethod

Regime adjustment method that scales variance exponentially with the smoothed log-deviation of standardised squared returns from its expected value under stationarity.

Mathematical definition

The regime state $s$ is defined as $\bar{s} = \frac{1}{T}\sum_t \ln\max(z_t^2, \varepsilon) - \kappa$, where $\kappa = \psi(x) + \ln y$ ($\psi$ = digamma) is the stationary expectation of $\ln z^2$ under a $\chi^2(1)$ distribution scaled by $y$, and $\varepsilon$ is a small positive threshold.

\[\begin{align} \kappa &= \psi(x) + \ln y\,, \\ s &= \frac{1}{T}\sum_{t} \ln\!\max(z_t^2, \varepsilon) - \kappa\,, \\ \mathrm{mult} &= \exp(x \cdot s)\,. \end{align}\]

Where:

  • $\kappa$: Stationary expectation of $\ln z^2$ under the specified distribution.
  • $\psi$: Digamma function.
  • $x$, $y$: Parameters of LogRegimeAdjusted.
  • $s$: Smoothed log-deviation regime state.
  • $T$: Number of observations.
  • $z_t^2$: Standardised squared return at time $t$.
  • $\varepsilon$: Small positive threshold for numerical stability.
  • $\mathrm{mult}$: Variance scaling multiplier.

Fields

  • x: Shape parameter of the log regime adjustment.
  • y: Scale parameter of the log regime adjustment.
  • kappa: Precomputed normalisation constant digamma(x) + log(y) for the log regime adjustment.

Constructors

LogRegimeAdjusted(;    x::Number = 0.5,    y::Number = 2.0) -> LogRegimeAdjusted

Keywords correspond to the struct's fields. The kappa field is derived from x and y and cannot be set directly.

Validation

  • x is valid (i.e., x >= 0, finite, and non-empty).
  • y is valid (i.e., y >= 0, finite, and non-empty).

Examples

julia> LogRegimeAdjusted()LogRegimeAdjusted      x ┼ Float64: 0.5      y ┼ Float64: 2.0  kappa ┴ Float64: -1.2703628454614782

Related

source
PortfolioOptimisers.FirstMomentRegimeAdjustedType
struct FirstMomentRegimeAdjusted{__T_x} <: RegimeAdjustedMethod

Regime adjustment method that scales variance by the ratio of the mean absolute deviation of standardised returns to the first-moment normalisation constant x.

Mathematical definition

The regime state $s$ and multiplier are:

\[\begin{align} s &= \frac{1}{x} \cdot \frac{1}{T}\sum_t \sqrt{\max(z_t^2, 0)}\,, \\ \mathrm{mult} &= s\,. \end{align}\]

Where:

  • $s$: Regime state (ratio of mean absolute deviation to normalisation constant $x$).
  • $x = \sqrt{2/\pi}$: Expected value of $|z|$ for a standard normal $z$.
  • $T$: Number of observations.
  • $z_t$: Standardised return at time $t$.
  • $\mathrm{mult}$: Variance scaling multiplier.

Fields

  • x: First-moment normalisation constant for the regime adjustment.

Constructors

FirstMomentRegimeAdjusted(;    x::Number = sqrt(2 * inv(π))) -> FirstMomentRegimeAdjusted

Keywords correspond to the struct's fields.

Validation

  • x is valid (i.e., x >= 0, finite, and non-empty).

Examples

julia> FirstMomentRegimeAdjusted()FirstMomentRegimeAdjusted  x ┴ Float64: 0.7978845608028654

Related

source
PortfolioOptimisers.RootMeanSquaredAdjustedType
struct RootMeanSquaredAdjusted <: RegimeAdjustedMethod

Regime adjustment method that scales variance by the square root of the mean of the standardised squared returns.

Mathematical definition

\[\begin{align} s &= \frac{1}{T}\sum_t z_t^2\,, \\ \mathrm{mult} &= \sqrt{\max(s, 0)}\,. \end{align}\]

Where:

  • $s$: Mean of standardised squared returns.
  • $T$: Number of observations.
  • $z_t$: Standardised return at time $t$.
  • $\mathrm{mult}$: Variance scaling multiplier.

Related

source
PortfolioOptimisers.RegimeAdjustedExpWeightedVarianceType
struct RegimeAdjustedExpWeightedVariance{__T_decay, __T_min_obs, __T_hac_lags, __T_regime_method, __T_regime_decay, __T_regime_min_obs, __T_regime_lohi_mult, __T_min_val, __T_centred, __T_cache} <: AbstractVarianceEstimator

Online exponentially weighted variance estimator with regime-state adjustment.

At each observation, it updates a running exponentially weighted variance and computes a standardised squared innovation . After accumulating enough observations, it smooths a regime state using regime_decay, then scales the final variance by regime_multiplier(regime_method, regime_state)².

A regime_method of nothing turns the adjustment off: no regime state advances, so the multiplier stays at one and the estimator is the plain exponentially weighted recursion. That is what a consumer needs when it reads a volatility rather than a regime-scaled risk figure, and EWVolatility is the one in the library.

This estimator is mask-aware, so a prior fitted with it keeps a young asset investable and zero-fills the rows the asset was missing through scenario_fill: every consumer of a Prior Result reads its returns matrix, and a scenario-based measure then reads a zero return where the asset had none and understates that asset's risk over those rows, while the variance stays the estimate this recursion made from the rows it saw. The fill is silent at or below the fitting prior's own fill_limit field, a share of that asset's own observations, warns above it, and refuses any fill under strict; fill_limit defaults to nothing, and this family carries no CoveragePolicy to derive a limit from, so every fill is named.

Mathematical definition

EWM variance update (decay $\lambda$):

\[\begin{align} v_t &= \lambda v_{t-1} + (1 - \lambda)(r_t - \bar{r})^2\,. \end{align}\]

Standardised innovation:

\[\begin{align} z_t^2 &= (r_t - \bar{r})^2 / v_t\,. \end{align}\]

Regime state smoothed with regime_decay $\lambda_r$ ($g$ defined by RegimeAdjustedMethod):

\[\begin{align} s_t &= \lambda_r s_{t-1} + (1 - \lambda_r) \cdot g(z_t^2)\,. \end{align}\]

Final variance:

\[\begin{align} \hat{\sigma}^2 &= \mathrm{mult}(s_T)^2 \cdot v_T\,. \end{align}\]

When regime_lohi_mult is not nothing, mult(s_T) is clamped to the (lo, hi) range that field gives before the square is taken.

Where:

  • $v_t$: Exponentially weighted variance at time $t$.
  • $\lambda$: EWM decay parameter (decay field).
  • $r_t$: Return at time $t$.
  • $\bar{r}$: Mean return.
  • $z_t^2$: Standardised squared innovation $(r_t - \bar{r})^2 / v_t$.
  • $s_t$: Smoothed regime state at time $t$.
  • $\lambda_r$: Regime decay parameter (regime_decay field).
  • $g(\cdot)$: Regime state transformation (see RegimeAdjustedMethod).
  • $\hat{\sigma}^2$: Final regime-adjusted variance.
  • $\mathrm{mult}(s_T)$: Variance scaling multiplier (see RegimeAdjustedMethod).
  • $T$: Number of observations.

Fields

  • decay: Exponential decay factor for the exponentially weighted estimator.
  • min_obs: Minimum number of observations required before the estimator produces a valid result.
  • hac_lags: Optional number of lags for Heteroskedasticity and Autocorrelation Consistent (HAC) kernel correction of squared returns. If nothing, no HAC correction is applied.
  • regime_method: Regime adjustment method used to compute the per-observation regime state, or nothing to apply no regime adjustment.
  • regime_decay: Exponential decay factor for smoothing the regime state.
  • regime_min_obs: Minimum number of regime observations required before the regime multiplier is applied.
  • regime_lohi_mult: Optional (lo, hi) tuple bounding the regime multiplier range. If nothing, no clamping is applied.
  • min_val: Minimum threshold to prevent division by zero or degenerate estimates.
  • centred: Whether to treat the returns as pre-centred (mean zero). If false, the location is estimated online.

Constructors

RegimeAdjustedExpWeightedVariance(;    decay::Number             = exp2(-inv(40.0)),    min_obs::Integer          = round(Int, max(1, inv(log2(inv(decay))))),    hac_lags::Option{<:Integer} = nothing,    regime_method::Option{<:RegimeAdjustedMethod} = FirstMomentRegimeAdjusted(),    regime_decay::Number      = exp2(-2 / inv(log2(inv(decay)))),    regime_min_obs::Integer   = round(Int, max(1, inv(log2(inv(decay))) / 2)),    regime_lohi_mult::Option{<:Tuple{<:Number, <:Number}} = nothing,    min_val::Number           = sqrt(eps()),    centred::Bool             = false,    cache::Option{<:AbstractPartialFitState} = nothing) -> RegimeAdjustedExpWeightedVariance

Keywords correspond to the struct's fields.

Validation

  • decay > 0.
  • min_obs > 0.
  • If hac_lags is not nothing, hac_lags > 0.
  • regime_min_obs > 0.
  • If regime_lohi_mult is not nothing, 0 < regime_lohi_mult[1] < regime_lohi_mult[2].

Examples

julia> ce = RegimeAdjustedExpWeightedVariance();julia> ce.decay  exp2(-inv(40.0))truejulia> ce.min_obs40

Related

source

Functions

PortfolioOptimisers.regime_multiplierFunction
regime_multiplier(
    method::LogRegimeAdjusted,
    regime_state::Number
) -> Any

Computes the variance scaling multiplier for the log regime adjustment method.

Arguments

  • method::LogRegimeAdjusted: Log regime adjustment method.
  • regime_state::Number: Current smoothed regime state.

Returns

  • mult::Number: Variance scaling multiplier exp(method.x * regime_state).

Related

source
regime_multiplier(
    _::FirstMomentRegimeAdjusted,
    regime_state::Number
) -> Number

Computes the variance scaling multiplier for the first-moment regime adjustment method.

Arguments

  • ::FirstMomentRegimeAdjusted: First-moment regime adjustment method (unused).
  • regime_state::Number: Current smoothed regime state.

Returns

  • mult::Number: Variance scaling multiplier equal to regime_state directly.

Related

source
regime_multiplier(
    _::RootMeanSquaredAdjusted,
    regime_state::Number
) -> Any

Computes the variance scaling multiplier for the root-mean-squared regime adjustment method.

Arguments

  • ::RootMeanSquaredAdjusted: Root-mean-squared regime adjustment method (unused).
  • regime_state::Number: Current smoothed regime state.

Returns

  • mult::Number: Variance scaling multiplier sqrt(max(regime_state, 0)).

Related

source
Statistics.varMethod
Statistics.var(
    ce::RegimeAdjustedExpWeightedVariance,
    X::MatNum;
    dims::Int = 1,
    estimation_mask::Option{<:AbstractMatrix{<:Bool}} = nothing,
    active_mask::Option{<:AbstractMatrix{<:Bool}} = nothing,
    kwargs...
) -> Vector{<:Number}

Compute the regime-adjusted exponentially weighted variance for each asset.

Iterates over the observation dimension of X, updating an online variance cache at each step. After processing all observations, applies a bias-correction factor and scales the result by the square of the regime multiplier derived from the smoothed regime state.

Arguments

  • ce: Regime-adjusted exponentially weighted variance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • dims: Dimension along which to perform the computation.
  • estimation_mask: Optional boolean matrix with the same size as X. When provided, only assets where estimation_mask[i, :] (or [:, i]) is true contribute to the regime state update for observation i.
  • active_mask: Optional boolean matrix with the same size as X. When provided, assets that become inactive have their variance and observation count reset.
  • kwargs: Additional keyword arguments (ignored).

Validation

  • dims in (1, 2).
  • If estimation_mask is not nothing, size(X) == size(estimation_mask).
  • If active_mask is not nothing, size(X) == size(active_mask).

Returns

  • var::Vector{<:Number}: Per-asset regime-adjusted exponentially weighted variance vector of length assets. Assets with fewer than ce.min_obs observations return NaN.

Related

source
Statistics.varMethod
Statistics.var(ce::RegimeAdjustedExpWeightedVariance, X::MatNum,
               pnl::Option{<:AssetPanel}; dims::Int = 1, kwargs...) -> MatNum
Statistics.std(ce::RegimeAdjustedExpWeightedVariance, X::MatNum,
               pnl::Option{<:AssetPanel}; dims::Int = 1, kwargs...) -> MatNum
variance_series(ce::RegimeAdjustedExpWeightedVariance, X::MatNum,
                pnl::Option{<:AssetPanel}; dims::Int = 1, kwargs...) -> MatNum

Take the whole window, and read the two universe masks of the Asset Panel.

RegimeAdjustedExpWeightedVariance is mask-aware, so it overrides the reduce-and-expand root of its verb. It knows its own warm-up, its freeze on a holiday and its reset on an inactive period, so it emits its own frame over the whole window rather than taking a clean block from coverage_reduction. An asset outside the Coverage Universe therefore keeps a number here, where a plain estimator would carry NaN.

The panel travels as the third positional argument, and this method unpacks it onto the active_mask and estimation_mask keywords the estimator already has. No panel, and a static panel, both give the unmasked path.

Algorithm

  1. Read the two masks with panel_moment_masks.
  2. Delegate to the two-argument method with them on its keywords.

Arguments

  • ce: Covariance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • pnl: Optional AssetPanel, whose active mask the Coverage Universe of the fit is derived from. nothing makes the rule finiteness alone.
  • dims: Dimension along which to perform the computation.
  • kwargs...: Additional keyword arguments passed to the two-argument method.

Returns

  • sigma::MatNum: The variance, or the standard deviation, of every asset of the window.

Related

source
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

  1. Read the buffer out of the cache field with assert_sample_buffer, which refuses an estimator that was never wrapped in Online.
  2. Fold a matrix and its masks through the block arm of partial_fit!, and a vector and its masks through the single-observation arm.
  3. Rebind est.cache with Accessors.@reset, and return the estimator.

Arguments

  • est: Estimator whose buffer is folded forward.
  • X: Observations to fold. A matrix holds one observation per row when dims == 1, and one per column when dims == 2. A vector is a single observation across the assets, and dims is ignored.
  • dims: Dimension along which to perform the computation.
  • active_mask: The active mask of the block, of the shape of X, or of one entry per asset when X is one observation, or nothing.
  • estimation_mask: The estimation mask, on the same terms as active_mask.

Validation

  • est carries a SampleBufferState. An ArgumentError is thrown otherwise.
  • The masks, when they are not nothing, have the shape of X. A DimensionMismatch is thrown otherwise.
  • A buffer holding observations is given the masks it already records. An ArgumentError is thrown otherwise.
  • dims in (1, 2).

Returns

  • est: The estimator, with its cache field rebound to the buffer after the last observation.

Related

source
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

  1. Read the buffer out of the cache field with assert_sample_buffer, which refuses an estimator that was never wrapped in Online.
  2. Fold a matrix and its masks through the block arm of partial_fit!, and a vector and its masks through the single-observation arm.
  3. Rebind est.cache with Accessors.@reset, and return the estimator.

Arguments

  • est: Estimator whose buffer is folded forward.
  • X: Observations to fold. A matrix holds one observation per row when dims == 1, and one per column when dims == 2. A vector is a single observation across the assets, and dims is ignored.
  • dims: Dimension along which to perform the computation.
  • active_mask: The active mask of the block, of the shape of X, or of one entry per asset when X is one observation, or nothing.
  • estimation_mask: The estimation mask, on the same terms as active_mask.

Validation

  • est carries a SampleBufferState. An ArgumentError is thrown otherwise.
  • The masks, when they are not nothing, have the shape of X. A DimensionMismatch is thrown otherwise.
  • A buffer holding observations is given the masks it already records. An ArgumentError is thrown otherwise.
  • dims in (1, 2).

Returns

  • est: The estimator, with its cache field rebound to the buffer after the last observation.

Related

source
Statistics.varMethod
Statistics.var(
    ce::RegimeAdjustedExpWeightedVariance,
    state::RegimeAdjustedVarianceState;
    kwargs...
) -> Vector{<:Number}

Read the regime-adjusted variance out of a state held by hand.

This is regime_adjusted_variance under the family's public verb, so a state a caller keeps outside an estimator answers the same call as one the estimator holds. The state is read and never written.

Arguments

  • ce: Regime-adjusted exponentially weighted variance estimator.
  • state: Running state of an incremental fit.
  • kwargs: Additional keyword arguments (ignored).

Returns

  • var::Vector{<:Number}: Per-asset regime-adjusted exponentially weighted variance vector of length assets. An asset with fewer than ce.min_obs observations is NaN.

Examples

julia> X = [0.01 -0.02; -0.015 0.03; 0.02 -0.01; -0.005 0.012];julia> ce = partial_fit!(RegimeAdjustedExpWeightedVariance(; decay = 0.9, min_obs = 2,                                                           regime_min_obs = 2), X);julia> isequal(var(ce, ce.cache), var(ce))true

Related

source
Statistics.varMethod
Statistics.var(ce::RegimeAdjustedExpWeightedVariance; kwargs...) -> Vector{<:Number}

Read the regime-adjusted variance out of the estimator's own state.

The one-argument form is what an incremental fit answers: partial_fit! leaves the state in the cache field, and this verb turns it into the ordinary answer. An estimator that has been given no observation carries no state, so the call is refused rather than answered with a zero.

Arguments

  • ce: Regime-adjusted exponentially weighted variance estimator carrying a state.
  • kwargs: Additional keyword arguments (ignored).

Validation

  • ce.cache is not nothing. An ArgumentError is thrown otherwise.

Returns

  • var::Vector{<:Number}: Per-asset regime-adjusted exponentially weighted variance vector of length assets. An asset with fewer than ce.min_obs observations is NaN.

Examples

julia> X = [0.01 -0.02; -0.015 0.03; 0.02 -0.01; -0.005 0.012];julia> ce = partial_fit!(RegimeAdjustedExpWeightedVariance(; decay = 0.9, min_obs = 2,                                                           regime_min_obs = 2), X);julia> length(var(ce))2julia> var(RegimeAdjustedExpWeightedVariance())ERROR: ArgumentError: `ce` holds no partial-fit state, so there is nothing to read. Call `partial_fit!(ce, X)` first, or `var(ce, X)` for a fit over a whole sample.[...]

Related

source
Statistics.stdMethod
Statistics.std(
    ce::RegimeAdjustedExpWeightedVariance,
    X::MatNum;
    dims::Int = 1,
    estimation_mask::Option{<:AbstractMatrix{<:Bool}} = nothing,
    active_mask::Option{<:AbstractMatrix{<:Bool}} = nothing,
    kwargs...
) -> Vector{<:Number}

Compute the regime-adjusted exponentially weighted standard deviation for each asset.

The root of Statistics.var(ce::RegimeAdjustedExpWeightedVariance, X::MatNum; dims::Int = 1, estimation_mask::Option{<:AbstractMatrix{<:Bool}} = nothing, active_mask::Option{<:AbstractMatrix{<:Bool}} = nothing, kwargs...). The variance is a non-negative exponentially weighted average scaled by a squared multiplier, so the root is real. An asset that var answers with NaN stays NaN.

Arguments

  • ce: Regime-adjusted exponentially weighted variance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • dims: Dimension along which to perform the computation.
  • estimation_mask: Optional boolean matrix with the same size as X. When provided, only assets where estimation_mask[i, :] (or [:, i]) is true contribute to the regime state update for observation i.
  • active_mask: Optional boolean matrix with the same size as X. When provided, assets that become inactive have their variance and observation count reset.
  • kwargs: Additional keyword arguments (ignored).

Validation

  • dims in (1, 2).
  • If estimation_mask is not nothing, size(X) == size(estimation_mask).
  • If active_mask is not nothing, size(X) == size(active_mask).

Returns

  • std::Vector{<:Number}: Per-asset regime-adjusted exponentially weighted standard deviation vector of length assets. Assets with fewer than ce.min_obs observations return NaN.

Examples

julia> X = [0.01 -0.02; -0.015 0.03; 0.02 -0.01; -0.005 0.012];julia> ce = RegimeAdjustedExpWeightedVariance(; decay = 0.9, min_obs = 2, regime_min_obs = 2);julia> isapprox(std(ce, X), sqrt.(var(ce, X)))true

Related

source
Statistics.stdMethod
Statistics.std(
    ce::RegimeAdjustedExpWeightedVariance,
    state::RegimeAdjustedVarianceState;
    kwargs...
) -> Vector{<:Number}

Read the regime-adjusted standard deviation out of a state held by hand.

The root of Statistics.var(ce::RegimeAdjustedExpWeightedVariance, state::RegimeAdjustedVarianceState; kwargs...), so a state a caller keeps outside an estimator answers the same call as one the estimator holds. The state is read and never written.

Arguments

  • ce: Regime-adjusted exponentially weighted variance estimator.
  • state: Running state of an incremental fit.
  • kwargs: Additional keyword arguments (ignored).

Returns

  • std::Vector{<:Number}: Per-asset regime-adjusted exponentially weighted standard deviation vector of length assets. An asset with fewer than ce.min_obs observations is NaN.

Examples

julia> X = [0.01 -0.02; -0.015 0.03; 0.02 -0.01; -0.005 0.012];julia> ce = partial_fit!(RegimeAdjustedExpWeightedVariance(; decay = 0.9, min_obs = 2,                                                           regime_min_obs = 2), X);julia> isequal(std(ce, ce.cache), std(ce))true

Related

source
Statistics.stdMethod
Statistics.std(ce::RegimeAdjustedExpWeightedVariance; kwargs...) -> Vector{<:Number}

Read the regime-adjusted standard deviation out of the estimator's own state.

The one-argument form is what an incremental fit answers: partial_fit! leaves the state in the cache field, and this verb turns it into the ordinary answer. An estimator that has been given no observation carries no state, so the call is refused rather than answered with a zero.

Arguments

  • ce: Regime-adjusted exponentially weighted variance estimator carrying a state.
  • kwargs: Additional keyword arguments (ignored).

Validation

  • ce.cache is not nothing. An ArgumentError is thrown otherwise.

Returns

  • std::Vector{<:Number}: Per-asset regime-adjusted exponentially weighted standard deviation vector of length assets. An asset with fewer than ce.min_obs observations is NaN.

Examples

julia> X = [0.01 -0.02; -0.015 0.03; 0.02 -0.01; -0.005 0.012];julia> ce = partial_fit!(RegimeAdjustedExpWeightedVariance(; decay = 0.9, min_obs = 2,                                                           regime_min_obs = 2), X);julia> length(std(ce))2julia> std(RegimeAdjustedExpWeightedVariance())ERROR: ArgumentError: `ce` holds no partial-fit state, so there is nothing to read. Call `partial_fit!(ce, X)` first, or `std(ce, X)` for a fit over a whole sample.[...]

Related

source
PortfolioOptimisers.merge_statesMethod
merge_states(
    a::RegimeAdjustedVarianceState,
    b::RegimeAdjustedVarianceState
) -> Union{}

Refuses a pair of regime-adjusted states, because this family does not merge.

A merge needs the state of a block to be a sufficient statistic for what that block contributes, and this one is not. The regime state reads each observation's standardised squared innovation, which divides by the running variance and is gated by the running observation count, so a block fitted from a cold start weighs its own first observations differently from the same block fitted after another. The exponentially weighted accumulator itself does fold, as $\lambda^{n_B} v_A + v_B$, but the regime state that scales it does not, and an uncentred fit also carries its running location while a HAC fit carries its buffer of recent returns.

Fold the second block into the first with partial_fit! instead. A sequential fit is exact, and it is the route this family gives.

Arguments

  • a: The state of the first block of observations.
  • b: The state of the second block of observations.

Validation

  • a and b pass assert_mergeable_states, so a mismatched pair is named as such.
  • The pair is then refused with an ArgumentError, whatever it holds.

Returns

  • Nothing is returned. The method always throws.

Examples

julia> X = [0.01 -0.02; -0.015 0.03; 0.02 -0.01; -0.005 0.012];julia> ce = partial_fit!(RegimeAdjustedExpWeightedVariance(; decay = 0.9, min_obs = 2,                                                           regime_min_obs = 2), X);julia> try           PortfolioOptimisers.merge_states(ce.cache, ce.cache)       catch err           err isa ArgumentError       endtrue

Related

source