PortfolioOptimisersCovariance

PortfolioOptimisers.PortfolioOptimisersCovarianceType
struct PortfolioOptimisersCovariance{__T_ce, __T_mp, __T_cache} <: AbstractCovarianceEstimator

Runs any covariance estimator, then applies a matrix post-processing step to its result.

ce computes the raw matrix and mp repairs or filters it — positive-definite repair, denoising, and detoning — so the composite is the estimator the rest of the library takes as its default.

Fields

  • ce: Covariance estimator.
  • mp: Matrix processing estimator.
  • cache: Optional partial-fit state. It is nothing until partial_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: factory carries it unchanged, because a factory call resolves configuration rather than the sample; port_opt_view slices it to the selected assets by index copy, so the viewed estimator answers over those assets alone; and obs_weights_view drops 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

PortfolioOptimisersCovariance(;    ce::StatsBase.CovarianceEstimator = Covariance(),    mp::AbstractMatrixProcessingEstimator = MatrixProcessing(),    cache::Option{<:AbstractPartialFitState} = nothing) -> PortfolioOptimisersCovariance

Keywords correspond to the struct's fields.

The incremental fit

The composite folds by composition, and the state it carries decides which of the two routes it takes.

With cache holding nothing, partial_fit! forwards the observation to ce.ce and keeps nothing of its own, because mp reads no observation that a moment and a count cannot stand in for: pdm and dt read sigma alone, and dn reads the effective sample ratio T / N. The one-argument Statistics.cov then reads the inner estimator's folded matrix and applies mp from observation_count, which is exactly the size(X, 1) the matrix arm would have read. An mp.alg of a caller's own is the one step with no shape substitute, and it is refused by name at the fold.

With cache holding a SampleBufferState — which Online seeds — the composite takes the buffering route instead, and its read-out is the batch verb over the observations the buffer kept. That is the route an mp.alg needs.

Propagated parameters

When factory is called on this type, the following @fprop-tagged fields are automatically propagated:

  • ce: Recursively updated via factory.
  • cache: Carried unchanged via factory.

View parameters

When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:

Observation view parameters

When obs_weights_view is called on this type:

  • cache: Dropped via obs_weights_view, because no slice of a state exists on the observation axis.

Examples

julia> PortfolioOptimisersCovariance()PortfolioOptimisersCovariance  ce ┼ Covariance     │    me ┼ SimpleExpectedReturns     │       │   w ┴ nothing     │    ce ┼ GeneralCovariance     │       │   ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true)     │       │    w ┴ nothing     │   alg ┼ FullMoment()     │     w ┴ nothing  mp ┼ MatrixProcessing     │     pdm ┼ Posdef     │         │      alg ┼ UnionAll: NearestCorrelationMatrix.Newton     │         │   kwargs ┴ @NamedTuple{}: NamedTuple()     │      dn ┼ nothing     │      dt ┼ nothing     │     alg ┼ nothing     │   order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg)

Related

source
Statistics.covMethod
Statistics.cov(ce::PortfolioOptimisersCovariance, X::MatNum; dims = 1,
               active_mask::Option{<:AbstractMatrix{<:Bool}} = nothing, kwargs...)

Compute the covariance matrix with post-processing using a PortfolioOptimisersCovariance estimator.

This method computes the covariance matrix for the input data matrix X using the underlying covariance estimator in ce, and then applies the matrix post-processing step specified by ce.mp.

The composite is transparent to a gap: it forwards X and active_mask to ce.ce untouched, so gap_fill_value on it is gap_fill_value on ce.ce. A composite that wraps a gap-aware estimator therefore takes no finiteness refusal of its own, and repairs the finite block rather than the whole frame, which is what the AssetPanel method beside it does.

Algorithm

  1. Check dims, and orient X and active_mask to observations × assets, transposing them when dims == 2.
  2. Refuse a gapped sample with assert_finite_sample when gap_fill_value on ce is finite, because ce.ce is then a plain estimator that has no answer for one.
  3. Compute sigma with Statistics.cov(ce.ce, X; kwargs...), adding active_mask when one is given.
  4. When sigma is immutable, copy it into a Matrix, because step 5 writes in place.
  5. Apply matrix_processing! with ce.mp to sigma, in place, or matrix_processing_block! when ce.ce is gap-aware, so an asset outside the Coverage Universe keeps its NaN row and column.
  6. Return sigma.

ce.ce runs before ce.mp, and ce.mp.order fixes the order of the steps inside the post-processing. Step 1 orients X once, so the estimator and the post-processing both read the same orientation and neither takes a dims of its own.

Arguments

  • ce: Composite covariance estimator with post-processing.
  • 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.
  • active_mask: Optional boolean matrix with the same size as X, forwarded to ce.ce when it is given.
  • kwargs...: Additional keyword arguments passed to the underlying covariance estimator and matrix processing step.

Validation

  • dims in (1, 2).

Returns

  • sigma::Matrix{<:Number}: The processed covariance matrix.

Related

source
Statistics.corMethod
Statistics.cor(ce::PortfolioOptimisersCovariance, X::MatNum; dims = 1,
               active_mask::Option{<:AbstractMatrix{<:Bool}} = nothing, kwargs...)

Compute the correlation matrix with post-processing using a PortfolioOptimisersCovariance estimator.

This method computes the correlation matrix for the input data matrix X using the underlying covariance estimator in ce, and then applies the matrix post-processing step specified by ce.mp.

Algorithm

  1. Check dims and orient X to observations × assets, transposing it when dims == 2.
  2. Compute rho with Statistics.cor(ce.ce, X; kwargs...).
  3. When rho is immutable, copy it into a Matrix, because step 4 writes in place.
  4. Apply matrix_processing! with ce.mp to rho, in place.
  5. Return rho.

ce.ce runs before ce.mp, and ce.mp.order fixes the order of the steps inside the post-processing. Step 1 orients X once, so the estimator and the post-processing both read the same orientation and neither takes a dims of its own.

Arguments

  • ce: Composite covariance estimator with post-processing.
  • 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.
  • active_mask: Optional boolean matrix with the same size as X, forwarded to ce.ce when it is given.
  • kwargs...: Additional keyword arguments passed to the underlying covariance estimator and matrix processing step.

Validation

  • dims in (1, 2).

Returns

  • rho::Matrix{<:Number}: The processed correlation matrix.

Related

source
Statistics.covMethod
Statistics.cov(ce::PortfolioOptimisersCovariance, X::MatNum,
               pnl::Option{<:AssetPanel}; dims = 1, kwargs...) -> MatNum
Statistics.cor(ce::PortfolioOptimisersCovariance, X::MatNum,
               pnl::Option{<:AssetPanel}; dims = 1, kwargs...) -> MatNum

Forward the Asset Panel to the estimator that this composite wraps, then repair the finite block of the frame it gets back.

This is the composite's override of the reduce-and-expand root. The inner estimator owns the reduction, because it alone knows whether it is plain or mask-aware, and this method owns the repair. The repair runs on the finite block through matrix_processing_block!, so an asset outside the Coverage Universe keeps its NaN row and column and nothing else is touched.

Algorithm

  1. Check dims and orient X to observations × assets.
  2. Compute the matrix with the inner estimator, forwarding pnl as its third positional argument.
  3. When the matrix is immutable, copy it into a Matrix, because step 4 writes in place.
  4. Repair its finite block with matrix_processing_block!, under ce.mp and the columns of X the block names.
  5. Return the matrix.

Arguments

  • ce: Composite covariance estimator with post-processing.
  • 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 underlying estimator and to the matrix processing step.

Validation

  • dims in (1, 2).

Returns

  • sigma::MatNum: The processed covariance matrix, or correlation matrix, on the full asset universe.

Related

source
PortfolioOptimisers.partial_fit!Method
partial_fit!(ce::PortfolioOptimisersCovariance{<:Any, <:Any, Nothing}, X::MatNum;
             dims::Int = 1, kwargs...)
partial_fit!(ce::PortfolioOptimisersCovariance{<:Any, <:Any, Nothing}, x::VecNum;
             kwargs...)

Folds observations into a PortfolioOptimisersCovariance by forwarding them to ce.ce.

The composite is exact by composition and keeps no state of its own: ce.ce folds the raw matrix, and ce.mp is a read-out step that runs on whatever matrix it is given. The composite therefore owns no accumulator, and its cache stays nothing on this route — which is what selects the route, because a composite carrying a SampleBufferState is one Online seeded and takes the buffering fold instead.

The step is O(N²), the inner estimator's own, plus nothing.

ce.mp reads no observation that a moment and a count cannot stand in for, with one exception: an mp.alg of a caller's own is handed the whole sample, and assert_shape_only_matrix_processing refuses it here, at the fold, rather than at the read-out where the rows would already be gone.

Algorithm

  1. Refuse an mp carrying a sample-reading alg.
  2. Rebind ce.ce to the estimator partial_fit! gives, with Accessors.@reset.

Arguments

  • ce: Covariance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • x: One observation, whose entries are the assets.
  • dims: Dimension along which to perform the computation.
  • kwargs...: Additional keyword arguments, forwarded to ce.ce.

Validation

  • ce.mp.alg is nothing. An ArgumentError is thrown otherwise.

Returns

  • ce: The composite, with ce.ce rebound to the estimator carrying the state after the last observation.

Related

source
Statistics.covMethod
Statistics.cov(ce::PortfolioOptimisersCovariance{<:Any, <:Any, Nothing}; kwargs...)
Statistics.cor(ce::PortfolioOptimisersCovariance{<:Any, <:Any, Nothing}; kwargs...)

Reads the covariance, or the correlation, a folded PortfolioOptimisersCovariance has accumulated.

The read-out of the composition fold. ce.ce answers its own folded matrix, and ce.mp is applied to it from the shape of the sample: observation_count reads the number of observations folded off the inner state, and it is exactly the size(X, 1) the matrix arm of matrix_processing! would have read, NaN rows included. The substitution is therefore an identity, not an approximation, and this method answers what a batch fit over the same observations answers.

The matrix the inner estimator returns is copied when it is immutable, because the processing writes in place, exactly as the matrix methods beside this one do.

Algorithm

  1. Read the inner estimator's folded matrix with the one-argument Statistics.cov or Statistics.cor.
  2. Copy it into a Matrix when it is immutable.
  3. Apply ce.mp in place through the shape arm of matrix_processing_block!, with T from observation_count and N from the matrix. It is the block arm rather than the plain one because a fold over a changing universe answers NaN for an asset outside the Coverage Universe, exactly as the AssetPanel methods beside it do; a complete matrix costs nothing extra.
  4. Return the matrix.

Arguments

  • ce: Covariance estimator.
  • kwargs...: Additional keyword arguments, forwarded to ce.ce.

Validation

  • ce.ce carries a partial-fit state. An ArgumentError is thrown otherwise.
  • ce.mp.alg is nothing. An ArgumentError is thrown otherwise.

Returns

  • sigma::MatNum: The processed covariance matrix, or rho, the processed correlation matrix.

Related

source
Statistics.covMethod
Statistics.cov(ce::PortfolioOptimisersCovariance{<:Any, <:Any, <:SampleBufferState})
Statistics.cor(ce::PortfolioOptimisersCovariance{<:Any, <:Any, <:SampleBufferState})

Reads the covariance, or the correlation, of a buffered PortfolioOptimisersCovariance by refitting over its buffer.

The read-out of the buffering route, which Online seeds and which an mp.alg of a caller's own needs. It is the batch verb over the observations the buffer kept, so it answers exactly what a batch fit over those rows answers, mp.alg included.

Arguments

  • ce: Covariance estimator.

Validation

Returns

  • sigma::MatNum: The processed covariance matrix, or rho, the processed correlation matrix.

Related

source