Regime Adjusted Exponential Weighted Covariance: private API

Types

PortfolioOptimisers.RegimeAdjustedCovarianceStateType
struct RegimeAdjustedCovarianceState{__T_ret_buffer, __T_covariance, __T_variance, __T_cor_state, __T_pair_obs_count, __T_XXt, __T_Xi, __T_X_old_i, __T_location, __T_obs_count, __T_active, __T_regime_state, __T_n_regime_obs} <: AbstractPartialFitState

Internal mutable cache for the online covariance update in RegimeAdjustedExpWeightedCovariance.

This type is an implementation detail and is not intended for direct use.

The three fields that carry the separate correlation recursion are nothing where cor_decay is nothing, because one decay then carries the whole matrix and no correlation state exists.

Fields

  • ret_buffer: Optional circular buffer of recent centred returns for HAC kernel correction.
  • covariance: Running exponentially weighted covariance matrix, seeded at zero.
  • variance: Running per-asset variance vector.
  • cor_state: Running exponentially weighted correlation state, or nothing where one decay governs both the variance and the correlation.
  • pair_obs_count: Pairwise count of co-observations, or nothing where one decay governs both the variance and the correlation.
  • XXt: Working matrix for the current (possibly HAC-adjusted) outer product of the returns.
  • Xi: Working array for the current centred returns.
  • X_old_i: Working array for lagged centred returns.
  • location: Exponentially smoothed location (mean) vector.
  • obs_count: Per-asset count of observations processed.
  • active: Boolean mask indicating which assets are currently active.
  • regime_state: Current smoothed regime state value.
  • n_regime_obs: Number of observations used to update the regime state.

Related

source

Functions

PortfolioOptimisers.has_separate_cor_decayFunction
has_separate_cor_decay(
    ce::RegimeAdjustedExpWeightedCovariance
) -> Any

States whether the estimator runs the variance and the correlation at separate decays.

A cor_decay of nothing states one decay for the whole matrix, and a cor_decay equal to decay states the same recursion in two places. Both take the single covariance recursion, so the cache allocates no correlation state.

Arguments

  • ce: Regime-adjusted exponentially weighted covariance estimator.

Returns

  • flag::Bool: true where cor_decay is not nothing and differs from decay.

Related

source
PortfolioOptimisers.regime_kappaFunction
regime_kappa(
    method::LogRegimeAdjusted,
    _::Union{DiagonalTarget, MahalanobisTarget},
    n::Integer
) -> Any

Computes the stationary expectation of the log regime statistic for a target that reads the whole active block.

MahalanobisTarget and DiagonalTarget both sum n standardised squares, so the statistic is a $\chi^2(n)$ variate under correct calibration and its log has expectation $\psi(x n) + \ln y$. The scalar case of RegimeAdjustedExpWeightedVariance is this expression at n = 1.

Arguments

  • method::LogRegimeAdjusted: Log regime adjustment method.
  • ::Union{MahalanobisTarget, DiagonalTarget}: Regime-adjustment target.
  • n::Integer: Count of assets that contribute to the statistic.

Returns

  • kappa::Number: digamma(method.x * n) + log(method.y).

Related

source
regime_kappa(
    method::LogRegimeAdjusted,
    _::PortfolioTarget,
    n::Integer
) -> Any

Computes the stationary expectation of the log regime statistic for the portfolio target.

PortfolioTarget reads one direction and multiplies by n, so its statistic is n times a $\chi^2(1)$ variate and the log has expectation $\ln n + \psi(x) + \ln y$.

Arguments

  • method::LogRegimeAdjusted: Log regime adjustment method.
  • ::PortfolioTarget: Portfolio regime-adjustment target.
  • n::Integer: Count of assets that contribute to the statistic.

Returns

  • kappa::Number: log(n) + digamma(method.x) + log(method.y).

Related

source
PortfolioOptimisers.regime_denomFunction
regime_denom(
    method::FirstMomentRegimeAdjusted,
    _::PortfolioTarget,
    n::Integer
) -> Any

Computes the first-moment normalisation of the regime statistic for the portfolio target.

The statistic is n times a squared standard normal, so the root has expectation $\sqrt{n}\,x$ with $x = \sqrt{2/\pi}$.

Arguments

  • method::FirstMomentRegimeAdjusted: First-moment regime adjustment method.
  • ::PortfolioTarget: Portfolio regime-adjustment target.
  • n::Integer: Count of assets that contribute to the statistic.

Returns

  • denom::Number: sqrt(n) * method.x.

Related

source
regime_denom(
    _::FirstMomentRegimeAdjusted,
    _::MahalanobisTarget,
    n::Integer
) -> Any

Computes the first-moment normalisation of the regime statistic for the Mahalanobis target.

The statistic is a $\chi^2(n)$ variate, so the root has expectation $\sqrt{2}\,\Gamma((n+1)/2)/\Gamma(n/2)$. The expression is evaluated through the log gamma function, which stays finite for a wide universe. At n = 1 it is $\sqrt{2/\pi}$, which is the constant the scalar case of RegimeAdjustedExpWeightedVariance carries.

Arguments

  • ::FirstMomentRegimeAdjusted: First-moment regime adjustment method (unused).
  • ::MahalanobisTarget: Mahalanobis regime-adjustment target.
  • n::Integer: Count of assets that contribute to the statistic.

Returns

  • denom::Number: sqrt(2) * exp(loggamma((n + 1) / 2) - loggamma(n / 2)).

Related

source
regime_denom(
    _::FirstMomentRegimeAdjusted,
    _::DiagonalTarget,
    n::Integer
) -> Any

Computes the first-moment normalisation of the regime statistic for the diagonal target.

The diagonal statistic ignores the correlations, so only the second-moment calibration is exact in general. The root of n is kept as the diagonal-risk proxy.

Arguments

  • ::FirstMomentRegimeAdjusted: First-moment regime adjustment method (unused).
  • ::DiagonalTarget: Diagonal regime-adjustment target.
  • n::Integer: Count of assets that contribute to the statistic.

Returns

  • denom::Number: sqrt(n).

Related

source
PortfolioOptimisers.get_regime_stateMethod
get_regime_state(
    _::RootMeanSquaredAdjusted,
    _::RegimeAdjustedTarget,
    stats::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    n::Integer,
    _
) -> Any

Transforms the root-mean-squared regime statistics into the values the regime state smooths.

Arguments

  • ::RootMeanSquaredAdjusted: Root-mean-squared regime adjustment method (unused).
  • ::RegimeAdjustedTarget: Regime-adjustment target (unused).
  • stats::VecNum: One statistic per calibration direction.
  • n::Integer: Count of assets that contribute to the statistic.
  • ::Any: Ignored minimum value argument.

Returns

  • val::VecNum: stats ./ n.

Related

source
PortfolioOptimisers.get_regime_stateMethod
get_regime_state(
    method::FirstMomentRegimeAdjusted,
    target::RegimeAdjustedTarget,
    stats::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    n::Integer,
    _
) -> Any

Transforms the first-moment regime statistics into the values the regime state smooths.

Arguments

  • method::FirstMomentRegimeAdjusted: First-moment regime adjustment method.
  • target::RegimeAdjustedTarget: Regime-adjustment target, which names the normalisation.
  • stats::VecNum: One statistic per calibration direction.
  • n::Integer: Count of assets that contribute to the statistic.
  • ::Any: Ignored minimum value argument.

Returns

  • val::VecNum: sqrt.(max.(stats, 0)) ./ regime_denom(method, target, n).

Related

source
PortfolioOptimisers.get_regime_stateMethod
get_regime_state(
    method::LogRegimeAdjusted,
    target::RegimeAdjustedTarget,
    stats::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    n::Integer,
    min_val::Number
) -> Any

Transforms the log regime statistics into the values the regime state smooths.

Arguments

  • method::LogRegimeAdjusted: Log regime adjustment method.
  • target::RegimeAdjustedTarget: Regime-adjustment target, which names the expectation.
  • stats::VecNum: One statistic per calibration direction.
  • n::Integer: Count of assets that contribute to the statistic.
  • min_val::Number: Floor applied before the logarithm.

Returns

  • val::VecNum: log.(max.(stats, min_val)) .- regime_kappa(method, target, n).

Related

source
PortfolioOptimisers.safe_regime_choleskyFunction
safe_regime_cholesky(
    C::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    min_val::Number
) -> Any

Factorises a covariance block for the Mahalanobis regime statistic, and refuses rather than throws when no ridge makes it factorise.

A block that carries a late-listed asset is not yet positive definite, and the regime statistic is one observation of a smoother rather than a result a caller reads. A refusal therefore skips that observation's regime update, and the fit continues.

Algorithm

  1. Try the plain factorisation of the lower triangle of C. Return it where it succeeds.
  2. Symmetrise C, and take the mean absolute diagonal as the scale. Where that is not a finite positive number, take the largest absolute entry, and at least one.
  3. Add a ridge of max(min_val * scale, eps * scale) to the diagonal, and try again. Multiply the ridge by ten after each failure, for three tries in all.
  4. Return nothing where every try fails.

Arguments

  • C::MatNum: Covariance block of the assets that contribute to the statistic.
  • min_val::Number: Scale of the first ridge.

Returns

  • chol::Option{<:LinearAlgebra.Cholesky}: The factorisation, or nothing where no ridge makes the block factorise.

Related

source
PortfolioOptimisers.regime_statisticFunction
regime_statistic(
    _::MahalanobisTarget,
    X::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    C::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    _::AbstractVector{<:Integer},
    min_val::Number
) -> Union{Nothing, Vector}

Computes the squared Mahalanobis distance of one observation against the covariance block.

The target reads every eigen-direction of the block, so it calibrates the whole covariance structure. It needs two active assets, which min_active_assets states.

Arguments

  • ::MahalanobisTarget: Mahalanobis regime-adjustment target.
  • X::VecNum: Centred returns of the assets that contribute to the statistic.
  • C::MatNum: Bias-corrected covariance block of those assets.
  • ::AbstractVector{<:Integer}: Ignored index of those assets.
  • min_val::Number: Scale of the ridge that safe_regime_cholesky applies.

Returns

  • stats::Option{<:VecNum}: One statistic, or nothing where the block does not factorise.

Related

source
regime_statistic(
    _::DiagonalTarget,
    X::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    C::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    _::AbstractVector{<:Integer},
    min_val::Number
) -> Vector

Computes the squared standardised Euclidean distance of one observation against the marginal volatilities of the covariance block.

The target divides each return by its own volatility and sums the squares, so it calibrates the diagonal risk scale and reads no correlation.

Arguments

  • ::DiagonalTarget: Diagonal regime-adjustment target.
  • X::VecNum: Centred returns of the assets that contribute to the statistic.
  • C::MatNum: Bias-corrected covariance block of those assets.
  • ::AbstractVector{<:Integer}: Ignored index of those assets.
  • min_val::Number: Floor applied to each variance before its root is taken.

Returns

  • stats::VecNum: One statistic.

Related

source
regime_statistic(
    target::PortfolioTarget,
    X::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    C::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    idx::AbstractVector{<:Integer},
    min_val::Number
) -> Any

Computes the squared standardised return of one observation along each portfolio direction.

Where target.w is nothing, one inverse-volatility direction is rebuilt from the block at every observation, which neutralises the dispersion of the volatilities so that a loud asset does not carry the statistic on its own. Where target.w holds weights, each row of that matrix is one direction, its entries are restricted to the assets that contribute, and a row that keeps no weight is dropped. Each direction gives its own statistic, and the caller averages the transformed values.

Algorithm

  1. Build the weight matrix over the contributing assets. Return nothing where no row keeps a positive weight.
  2. Normalise each row to sum to one.
  3. Return the count of contributing assets times the squared portfolio return, divided by the portfolio variance, for each row.

Arguments

  • target::PortfolioTarget: Portfolio regime-adjustment target.
  • X::VecNum: Centred returns of the assets that contribute to the statistic.
  • C::MatNum: Bias-corrected covariance block of those assets.
  • idx::AbstractVector{<:Integer}: Index of those assets in the universe.
  • min_val::Number: Floor applied to each variance and to each portfolio variance.

Returns

  • stats::Option{<:VecNum}: One statistic per direction, or nothing where no row keeps a positive weight.

Related

source
PortfolioOptimisers.hac_outer_product!Function
hac_outer_product!(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Any

Computes the outer product of one observation, with the Newey-West HAC correction where hac_lags is not nothing.

The correction adds each lagged cross-product and its transpose, weighted by the Bartlett kernel $w_j = 1 - j/(L+1)$, so the update reads the serial correlation of the returns. An entry of a lagged observation that is not finite is read as zero, which freezes that pair's contribution.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache (mutated).
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • X::VecNum: Current centred returns vector.

Returns

  • XXt::MatNum: The HAC-adjusted outer product stored in cache.XXt.

Related

source
PortfolioOptimisers.update_var_cor!Function
update_var_cor!(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance,
    valid::AbstractVector{<:Bool},
    pair_valid::AbstractMatrix{<:Bool}
)

Advances the separate variance and correlation recursions, and rebuilds the covariance from them.

This is the path cor_decay opens. The variance runs at decay and the correlation state at cor_decay, which lets a volatility that mean-reverts quickly sit beside a correlation that needs more data. The two are recombined into cache.covariance, which the regime statistic reads.

Algorithm

  1. Advance the variance with the diagonal of the outer product, floored at zero.
  2. Standardise the outer product by the running volatilities. An asset whose variance is not above min_val contributes zero.
  3. Advance the correlation state where both assets of the pair are valid, and count the pair.
  4. Normalise the correlation state of the active block to a unit diagonal, symmetrise it, and rescale it by the running volatilities into cache.covariance.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache (mutated).
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • valid::AbstractVector{<:Bool}: Assets with a finite return that are active.
  • pair_valid::AbstractMatrix{<:Bool}: Pairs whose two assets are both valid.

Returns

  • nothing: The cache is mutated in place.

Related

source
PortfolioOptimisers.bias_corrected_covarianceFunction
bias_corrected_covariance(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance
) -> Any

Removes the damping a zero seed leaves in the running state, and returns the covariance that read-out reports.

The recursion is seeded at zero, which keeps the state positive semi-definite at every step and damps it by $1 - \lambda^{n}$ after n observations. The correction is a congruence transform, so it restores the scale without breaking that property. Where cor_decay opens the separate path, the variance and the correlation are corrected at their own decays, and the correlation reads a pairwise count so that an asynchronous listing is corrected pair by pair.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache.
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.

Returns

  • sigma::MatNum: The bias-corrected covariance matrix. An inactive asset is NaN in its own row and column.

Related

source
PortfolioOptimisers.regime_covariance_blockFunction
regime_covariance_block(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance,
    idx::AbstractVector{<:Integer}
) -> Any

Returns the bias-corrected covariance block of the assets that contribute to the regime statistic.

This block calibrates the smoother and is never reported, so it applies the per-asset variance correction alone. Where the separate path runs, the correlation already sits inside cache.covariance normalised, and its pairwise correction cancels in that normalisation for a synchronous sample. bias_corrected_covariance is the exact read-out.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache.
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • idx::AbstractVector{<:Integer}: Index of the assets that contribute to the statistic.

Returns

  • sigma::MatNum: The bias-corrected covariance block of those assets.

Related

source
PortfolioOptimisers.update_regime!Function
update_regime!(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    valid::AbstractVector{<:Bool},
    estimation_mask::Union{Nothing, AbstractVector{<:Bool}}
) -> Any

Advances the smoothed regime state with one observation, one step ahead of the covariance update.

The observation is scored against the state that stands before it, so the statistic compares realised risk against predicted risk rather than against itself. Only an asset that was already above min_obs contributes, because the statistic is sensitive to a poorly estimated asset. A regime_method of nothing advances nothing.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache.
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • X::VecNum: Current centred returns vector, zeroed where the asset is not valid.
  • valid::AbstractVector{<:Bool}: Assets with a finite return that are active.
  • estimation_mask::Option{<:AbstractVector{<:Bool}}: Optional mask restricting which assets contribute to the statistic.

Returns

  • cache::RegimeAdjustedCovarianceState: The cache to read on and to pass to the next observation. regime_state and n_regime_obs are immutable fields that Accessors.@reset replaces, so the caller must rebind the cache to this return value.

Related

source
PortfolioOptimisers.process_observation!Method
process_observation!(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    estimation_mask::Union{Nothing, AbstractVector{<:Bool}},
    active_mask::Union{Nothing, AbstractVector{<:Bool}}
) -> Any

Processes a single observation row (or column) to update the online covariance cache.

Updates the running location, advances the regime state one step ahead of the covariance, and then advances the covariance itself. An asset that turns inactive at this observation has its row and column zeroed and its counts reset, so a later listing starts from a cold state.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache (mutated).
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • X::VecNum: Returns vector for the current observation.
  • estimation_mask::Option{<:AbstractVector{<:Bool}}: Optional mask restricting which assets contribute to the regime state update.
  • active_mask::Option{<:AbstractVector{<:Bool}}: Optional mask of currently active assets.

Returns

  • cache::RegimeAdjustedCovarianceState: The cache to read on and to pass to the next observation. The arrays are mutated in place, and the caller must rebind the cache to this return value because regime_state and n_regime_obs are immutable fields.

Related

source
PortfolioOptimisers.assert_regime_targetFunction
assert_regime_target(_::RegimeAdjustedTarget, _::Integer)

Accepts every regime-adjustment target that names no weights.

Arguments

  • ::RegimeAdjustedTarget: Regime-adjustment target (unused).
  • ::Integer: Ignored count of assets.

Returns

  • nothing.

Related

source
assert_regime_target(target::PortfolioTarget, N::Integer)

Checks the portfolio weights of the regime-adjustment target against the universe of the fit.

The target holds the weights, and the fit holds the universe, so the two meet here and nowhere earlier. Weights of nothing name the inverse-volatility direction, which needs no check.

Arguments

  • target::PortfolioTarget: Portfolio regime-adjustment target.
  • N::Integer: Count of assets in the fit.

Validation

  • target.w names N assets.
  • Every weight is non-negative, and every row sums to a positive number.

Returns

  • nothing.

Related

source
PortfolioOptimisers.regime_adjusted_covariance_pass!Function
regime_adjusted_covariance_pass!(
    f,
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    dims::Int64,
    estimation_mask::Union{Nothing, AbstractMatrix{<:Bool}},
    active_mask::Union{Nothing, AbstractMatrix{<:Bool}}
) -> Any
regime_adjusted_covariance_pass!(
    f,
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    dims::Int64,
    estimation_mask::Union{Nothing, AbstractMatrix{<:Bool}},
    active_mask::Union{Nothing, AbstractMatrix{<:Bool}},
    state::Union{Nothing, RegimeAdjustedCovarianceState}
) -> Any

Run one forward pass of the online covariance update over the observations of X, and call f after each observation.

The pass owns the argument validation, the orientation and the cache, so every verb that reads it states the recursion once.

Arguments

  • f: Called as f(i, cache) after observation i. A caller that wants the final cache alone reads the method that takes no f.
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • X::MatNum: Observation matrix.
  • dims::Int: Dimension along which the observations lie.
  • estimation_mask::Option{<:AbstractMatrix{<:Bool}}: Optional mask restricting which assets contribute to the regime state update.
  • active_mask::Option{<:AbstractMatrix{<:Bool}}: Optional mask of active assets.
  • state::Option{<:RegimeAdjustedCovarianceState}: Optional state to continue. A nothing starts a cold cache, which is what a fit over a whole sample needs. partial_fit! passes the estimator's own state.

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).
  • The portfolio weights of ce.regime_target, where it names any.
  • If state is not nothing, it holds as many assets as X.

Returns

  • cache::RegimeAdjustedCovarianceState: The cache after the last observation.

Related

source
regime_adjusted_covariance_pass!(
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    dims::Int64,
    estimation_mask::Union{Nothing, AbstractMatrix{<:Bool}},
    active_mask::Union{Nothing, AbstractMatrix{<:Bool}}
) -> Any
regime_adjusted_covariance_pass!(
    ce::RegimeAdjustedExpWeightedCovariance,
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    dims::Int64,
    estimation_mask::Union{Nothing, AbstractMatrix{<:Bool}},
    active_mask::Union{Nothing, AbstractMatrix{<:Bool}},
    state::Union{Nothing, RegimeAdjustedCovarianceState}
) -> Any

Run one forward pass of the online covariance update over the observations of X, and read no intermediate cache.

This is the callback method with a callback that does nothing, so a verb that wants the last cache alone states no callback of its own. cov and partial_fit! read the pass this way, and variance_series reads the callback method.

Arguments

  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.
  • X::MatNum: Observation matrix.
  • dims::Int: Dimension along which the observations lie.
  • estimation_mask::Option{<:AbstractMatrix{<:Bool}}: Optional mask restricting which assets contribute to the regime state update.
  • active_mask::Option{<:AbstractMatrix{<:Bool}}: Optional mask of active assets.
  • state::Option{<:RegimeAdjustedCovarianceState}: Optional state to continue. A nothing starts a cold cache, which is what a fit over a whole sample needs. partial_fit! passes the estimator's own state.

Returns

  • cache::RegimeAdjustedCovarianceState: The cache after the last observation.

Related

source
PortfolioOptimisers.regime_adjusted_covarianceFunction
regime_adjusted_covariance(
    cache::RegimeAdjustedCovarianceState,
    ce::RegimeAdjustedExpWeightedCovariance
) -> Any

Read the regime-adjusted covariance out of a cache, as it stands.

Removes the damping of the zero seed, blanks every asset that is not ready, symmetrises the block that is, and scales by the square of the regime multiplier. The cache is read, never written, so the same cache answers this call after every observation of a forward pass.

Where ce.regime_method is nothing, process_observation! advances no regime state, so cache.n_regime_obs stays at zero, which is below every admissible regime_min_obs. The multiplier is then one and the covariance is the plain recursion.

Where ce.regime_lohi_mult is not nothing, the multiplier is clamped to that (lo, hi) range before it is squared. Where it is nothing, no clamp runs.

Arguments

  • cache::RegimeAdjustedCovarianceState: Online covariance computation cache.
  • ce::RegimeAdjustedExpWeightedCovariance: Covariance estimator configuration.

Returns

  • sigma::MatNum: Regime-adjusted covariance matrix. An asset with fewer than ce.min_obs observations, or one that is not active, is NaN in its own row and column.

Related

source
PortfolioOptimisers.regime_adjusted_correlationFunction
regime_adjusted_correlation(
    sigma::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Any

Rescales a regime-adjusted covariance matrix to a unit diagonal.

An asset that the covariance blanks carries a NaN variance, so its row and column stay NaN here, and its diagonal entry stays NaN rather than becoming one. A finite entry outside [-1, 1] is round-off, and it is clamped.

Arguments

  • sigma::MatNum: Regime-adjusted covariance matrix.

Returns

  • rho::MatNum: The correlation matrix of sigma.

Related

source
PortfolioOptimisers.gap_fill_valueMethod
gap_fill_value(ce::RegimeAdjustedExpWeightedCovariance) -> Float64

Answer NaN, so a gapped sample reaches the recursion with its gaps intact.

The recursion updates only the sub-block of the assets that are valid at each observation, and the regime weight is taken from that sub-block alone, so a fill would both decay a frozen block and move the regime it is weighted by. The consumer therefore hands the sample as it stands, together with the active mask that explains the gap.

Arguments

  • ce: Covariance estimator.

Returns

  • fv::Float64: NaN.

Related

source
Base.copyMethod
copy(
    x::RegimeAdjustedCovarianceState
) -> Union{RegimeAdjustedCovarianceState{Nothing}, RegimeAdjustedCovarianceState{__T_ret_buffer} where __T_ret_buffer<:DataStructures.CircularBuffer}

Copies a RegimeAdjustedCovarianceState, so the copy shares no array with the original.

The copy method of the AbstractPartialFitState interface, which partial_fit calls before it folds. Every array field is copied, and the two scalar fields pass through. The circular buffer of recent centred returns is rebuilt at the same capacity, and each observation it holds is copied into it, so a fold on the copy pushes into a buffer of its own. The three fields of the separate correlation recursion pass through as nothing where they are nothing.

Arguments

  • x: The cache to copy.

Returns

  • state::RegimeAdjustedCovarianceState: A fresh cache, equal to x, whose arrays are fresh.

Related

source
PortfolioOptimisers.variance_seriesMethod
variance_series(
    ce::RegimeAdjustedExpWeightedCovariance,
    X::MatNum;
    dims::Int = 1,
    estimation_mask::Option{<:AbstractMatrix{<:Bool}} = nothing,
    active_mask::Option{<:AbstractMatrix{<:Bool}} = nothing,
    kwargs...
) -> Matrix{<:Number}

Compute the point-in-time regime-adjusted exponentially weighted variance series.

Row t holds the diagonal of what cov returns for the first t observations of X, so no row reads an observation after its own. The update is a recursion over one observation, so this method overrides the expanding-window fallback with a single forward pass: it reads the cache after each observation instead of refitting.

The fallback cannot answer this estimator. It slices X once per row and passes every keyword unsliced, so a mask of the whole window meets a window of t observations and the size check refuses the call.

Arguments

  • ce: Regime-adjusted exponentially weighted covariance 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 covariance 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

  • val::Matrix{<:Number}: Variance series, shaped as (T, N) if dims == 1 or (N, T) if dims == 2. An asset with fewer than ce.min_obs observations at row t is NaN there.

Related

source
PortfolioOptimisers.variance_seriesMethod
variance_series(
    ce::RegimeAdjustedExpWeightedCovariance,
    X::MatNum,
    pnl::Option{<:AssetPanel};
    dims::Int = 1,
    kwargs...
) -> Matrix{<:Number}

Compute the point-in-time regime-adjusted exponentially weighted variance series from a window of an Asset Panel.

This is the diagonal of the covariance of the same call, read after each observation, and it reads the panel's two masks through the same override.

Arguments

  • ce: Regime-adjusted exponentially weighted 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 (ignored).

Returns

  • val::Matrix{<:Number}: Variance series on the full asset universe, shaped as (T, N) if dims == 1 or (N, T) if dims == 2.

Related

source