Matrix processing
Co-moment matrices can be post-processed after being computed. These processes are often complementary but there is no set order.
At the base level, we have four possible post processing steps:
Positive definite projection.
Denoising.
Detoning.
Custom process.
The only set order is that positive definite projection should come first. This is because the other post-processing methods work best with positive definite matrices, and may use positive definite projection internally.
Aside from this, there is no set canonical order, the closest to a heuristic we can justify is to denoise before detoning. As such we provide all permutations of ordering for the last three steps.
PortfolioOptimisers.AbstractMatrixProcessingEstimator Type
abstract type AbstractMatrixProcessingEstimator <: AbstractEstimator endAbstract supertype for all matrix processing estimator types in PortfolioOptimisers.jl.
All concrete and/or abstract types that implement matrix processing routines–-such as covariance matrix cleaning, denoising, or detoning–-should be subtypes of AbstractMatrixProcessingEstimator.
Interfaces
In order to implement a new matrix processing estimator which will work seamlessly with the library, subtype AbstractMatrixProcessingEstimator with all necessary parameters as part of the struct, and implement the following methods:
matrix_processing!(mp::AbstractMatrixProcessingEstimator, sigma::MatNum, X::MatNum, args...; kwargs...): In-place processing of a covariance or correlation matrix.matrix_processing(mp::AbstractMatrixProcessingEstimator, sigma::MatNum, X::MatNum, args...; kwargs...): Optional out-of-place processing of a covariance or correlation matrix.
Arguments
mp: Matrix processing estimator.sigma: Covariance-like or correlation-like matrix.X: Data matrix.args...: Additional positional arguments passed to custom algorithms.kwargs...: Additional keyword arguments passed to custom algorithms.
Returns
sigma::MatNum: The processed input matrixsigma.
Examples
We can create a dummy matrix processing estimator as follows:
julia> struct MyMatrixProcessingEstimator <: PortfolioOptimisers.AbstractMatrixProcessingEstimator end
julia> function PortfolioOptimisers.matrix_processing!(est::MyMatrixProcessingEstimator,
sigma::PortfolioOptimisers.MatNum,
X::PortfolioOptimisers.MatNum)
# Implement your in-place matrix processing logic here.
println("Processing matrix in-place...")
return sigma
end
julia> function PortfolioOptimisers.matrix_processing(est::MyMatrixProcessingEstimator,
sigma::PortfolioOptimisers.MatNum,
X::PortfolioOptimisers.MatNum)
sigma = copy(sigma)
println("Copy sigma...")
matrix_processing!(est, sigma, X)
return sigma
end
julia> matrix_processing!(MyMatrixProcessingEstimator(), [1.0 2.0; 2.0 1.0], rand(10, 2))
Processing matrix in-place...
2×2 Matrix{Float64}:
1.0 2.0
2.0 1.0
julia> matrix_processing(MyMatrixProcessingEstimator(), [1.0 2.0; 2.0 1.0], rand(10, 2))
Copy sigma...
Processing matrix in-place...
2×2 Matrix{Float64}:
1.0 2.0
2.0 1.0Related
sourcePortfolioOptimisers.AbstractMatrixProcessingAlgorithm Type
abstract type AbstractMatrixProcessingAlgorithm <: AbstractAlgorithm endAbstract supertype for all matrix processing algorithm types in PortfolioOptimisers.jl.
All concrete and/or abstract types that implement a specific matrix processing algorithm should be subtypes of AbstractMatrixProcessingAlgorithm.
Interfaces
In order to implement a new matrix processing algorithm that works with the current matrix processing estimator, subtype AbstractMatrixProcessingAlgorithm, with all necessary parameters as part of the struct, and implement the following methods:
matrix_processing_algorithm!(mpa::AbstractMatrixProcessingAlgorithm, sigma::MatNum, args...; kwargs...): In-place application of a custom matrix processing algorithm.matrix_processing_algorithm(mpa::AbstractMatrixProcessingAlgorithm, sigma::MatNum, args...; kwargs...): Optional out-of-place application of a custom matrix processing algorithm.
Arguments
mpa: Matrix processing algorithm.args...: Additional positional arguments.kwargs...: Additional keyword arguments.
Returns
sigma::MatNum: The input matrixsigmaafter applying the algorithm.
Examples
We can create a dummy matrix processing algorithm as follows:
julia> struct MyMatrixProcessingAlgorithm <: PortfolioOptimisers.AbstractMatrixProcessingAlgorithm end
julia> function PortfolioOptimisers.matrix_processing_algorithm!(alg::MyMatrixProcessingAlgorithm,
sigma::PortfolioOptimisers.MatNum,
X::PortfolioOptimisers.MatNum;
kwargs...)
# Implement your in-place matrix processing algorithm logic here.
println("Applying custom matrix processing algorithm in-place...")
return sigma
end
julia> function PortfolioOptimisers.matrix_processing_algorithm(alg::MyMatrixProcessingAlgorithm,
sigma::PortfolioOptimisers.MatNum,
X::PortfolioOptimisers.MatNum;
kwargs...)
sigma = copy(sigma)
println("Copy sigma...")
return PortfolioOptimisers.matrix_processing_algorithm!(alg, sigma, X; kwargs...)
end
julia> matrix_processing!(DenoiseDetoneAlgMatrixProcessing(; alg = MyMatrixProcessingAlgorithm()),
[1.0 2.0; 2.0 1.0], rand(10, 2))
Applying custom matrix processing algorithm in-place...
2×2 Matrix{Float64}:
1.0 1.0
1.0 1.0
julia> PortfolioOptimisers.matrix_processing_algorithm(MyMatrixProcessingAlgorithm(),
[1.0 2.0; 2.0 1.0], rand(10, 2))
Copy sigma...
Applying custom matrix processing algorithm in-place...
2×2 Matrix{Float64}:
1.0 2.0
2.0 1.0Related
sourcePortfolioOptimisers.AbstractMatrixProcessingOrder Type
abstract type AbstractMatrixProcessingOrder <: AbstractAlgorithm endAbstract supertype for matrix processing order types in PortfolioOptimisers.jl.
All concrete and/or abstract types that specify the order of matrix processing steps—such as denoising, detoning, and algorithm application—should be subtypes of AbstractMatrixProcessingOrder.
Interfaces
Given that these are meant to be used by matrix processing estimators, there are no specific methods that need to be implemented for this abstract type. However, it serves as a marker for dispatching and organizing different matrix processing orders within the library. The interfaces should be defined at the level of the matrix processing estimator that utilises these orders.
Related Types
sourcePortfolioOptimisers.DenoiseDetoneAlg Type
struct DenoiseDetoneAlg <: AbstractMatrixProcessingOrder endMatrix processing order: Denoising → Detoning → Custom Algorithm.
DenoiseDetoneAlg specifies that matrix processing should be performed in the order of denoising, then detoning, followed by any custom algorithm. This type is used to configure the sequence of operations in matrix processing pipelines.
Related
PortfolioOptimisers.DenoiseAlgDetone Type
struct DenoiseAlgDetone <: AbstractMatrixProcessingOrder endMatrix processing order: Denoising → Custom Algorithm → Detoning.
DenoiseAlgDetone specifies that matrix processing should be performed in the order of denoising, then applying a custom algorithm, followed by detoning. This type is used to configure the sequence of operations in matrix processing pipelines.
Related
PortfolioOptimisers.DetoneDenoiseAlg Type
struct DetoneDenoiseAlg <: AbstractMatrixProcessingOrder endMatrix processing order: Detoning → Denoising → Custom Algorithm.
DetoneDenoiseAlg specifies that matrix processing should be performed in the order of detoning, then denoising, followed by any custom algorithm. This type is used to configure the sequence of operations in matrix processing pipelines.
Related
PortfolioOptimisers.DetoneAlgDenoise Type
struct DetoneAlgDenoise <: AbstractMatrixProcessingOrder endMatrix processing order: Detoning → Custom Algorithm → Denoising.
DetoneAlgDenoise specifies that matrix processing should be performed in the order of detoning, then applying a custom algorithm, followed by denoising. This type is used to configure the sequence of operations in matrix processing pipelines.
Related
PortfolioOptimisers.AlgDenoiseDetone Type
struct AlgDenoiseDetone <: AbstractMatrixProcessingOrder endMatrix processing order: Custom Algorithm → Denoising → Detoning.
AlgDenoiseDetone specifies that matrix processing should be performed in the order of applying a custom algorithm, then denoising, followed by detoning. This type is used to configure the sequence of operations in matrix processing pipelines.
Related
PortfolioOptimisers.AlgDetoneDenoise Type
struct AlgDetoneDenoise <: AbstractMatrixProcessingOrder endMatrix processing order: Custom Algorithm → Detoning → Denoising.
AlgDetoneDenoise specifies that matrix processing should be performed in the order of applying a custom algorithm, then detoning, followed by denoising. This type is used to configure the sequence of operations in matrix processing pipelines.
Related
PortfolioOptimisers.DenoiseDetoneAlgMatrixProcessing Type
struct DenoiseDetoneAlgMatrixProcessing{T1, T2, T3, T4, T5} <: AbstractMatrixProcessingEstimator
pdm::T1
dn::T2
dt::T3
alg::T4
order::T5
endA flexible container type for configuring and applying matrix processing routines in PortfolioOptimisers.jl.
DenoiseDetoneAlgMatrixProcessing encapsulates all steps required for processing covariance or correlation matrices, including positive definiteness enforcement, denoising, detoning, and optional custom matrix processing algorithms via matrix_processing! and matrix_processing. This estimator allows users to build complex matrix processing pipelines tailored to their specific needs.
Fields
pdm: Optional positive definite matrix estimator.dn: Optional matrix denoising estimator.dt: Optional matrix detoning estimator.alg: Optional custom matrix processing algorithm.order: Specifies the order in which denoising, detoning, and custom algorithm steps are applied.
Constructor
DenoiseDetoneAlgMatrixProcessing(; pdm::Option{<:Posdef} = Posdef(),
dn::Option{<:Denoise} = nothing,
dt::Option{<:Detone} = nothing,
alg::Option{<:AbstractMatrixProcessingAlgorithm} = nothing,
order::AbstractMatrixProcessingOrder = DenoiseDetoneAlg())Keyword arguments correspond to the fields above.
Examples
julia> DenoiseDetoneAlgMatrixProcessing()
DenoiseDetoneAlgMatrixProcessing
pdm ┼ Posdef
│ alg ┼ UnionAll: NearestCorrelationMatrix.Newton
│ kwargs ┴ @NamedTuple{}: NamedTuple()
dn ┼ nothing
dt ┼ nothing
alg ┼ nothing
order ┴ DenoiseDetoneAlg()
julia> DenoiseDetoneAlgMatrixProcessing(; dn = Denoise(), dt = Detone(; n = 2))
DenoiseDetoneAlgMatrixProcessing
pdm ┼ Posdef
│ alg ┼ UnionAll: NearestCorrelationMatrix.Newton
│ kwargs ┴ @NamedTuple{}: NamedTuple()
dn ┼ Denoise
│ alg ┼ ShrunkDenoise
│ │ alpha ┴ Float64: 0.0
│ args ┼ Tuple{}: ()
│ kwargs ┼ @NamedTuple{}: NamedTuple()
│ kernel ┼ typeof(AverageShiftedHistograms.Kernels.gaussian): AverageShiftedHistograms.Kernels.gaussian
│ m ┼ Int64: 10
│ n ┼ Int64: 1000
│ pdm ┼ Posdef
│ │ alg ┼ UnionAll: NearestCorrelationMatrix.Newton
│ │ kwargs ┴ @NamedTuple{}: NamedTuple()
dt ┼ Detone
│ n ┼ Int64: 2
│ pdm ┼ Posdef
│ │ alg ┼ UnionAll: NearestCorrelationMatrix.Newton
│ │ kwargs ┴ @NamedTuple{}: NamedTuple()
alg ┼ nothing
order ┴ DenoiseDetoneAlg()Related
References
[1] M. M. De Prado. Machine learning for asset managers (Cambridge University Press, 2020). Chapter 2.
[2] V. A. Marčenko and L. A. Pastur. Distribution of eigenvalues for some sets of random matrices. Mathematics of the USSR-Sbornik 1, 457 (1967).
PortfolioOptimisers.matrix_processing! Function
matrix_processing!(mp::AbstractMatrixProcessingEstimator, sigma::MatNum, X::MatNum, args...;
kwargs...)
matrix_processing!(::Nothing, sigma::MatNum, args...; kwargs...)No-op fallback for in-place processing of a covariance or correlation matrix.
Arguments
mp: Optional matrix processing estimator.sigma: Covariance-like or correlation-like matrix.X: Data matrix.args...: Additional positional arguments passed to custom algorithms.kwargs...: Additional keyword arguments passed to custom algorithms.
Returns
sigma::MatNum: The input matrixsigmais modified in-place.
Related
matrix_processing!(mp::DenoiseDetoneAlgMatrixProcessing, sigma::MatNum, X::MatNum, args...;
kwargs...)In-place matrix processing pipeline using the DenoiseDetoneAlg order.
This method applies a sequence of matrix processing steps to the input covariance or correlation matrix sigma, modifying it in-place. The steps are performed in the following order: positive definiteness enforcement, denoising, detoning, and an optional custom algorithm. The order is determined by the DenoiseDetoneAlg type.
Arguments
mp: Optional matrix processing estimator.sigma: Covariance-like or correlation-like matrix.X: Data matrix.args...: Additional positional arguments passed to custom algorithms.kwargs...: Additional keyword arguments passed to custom algorithms.
Returns
sigma::MatNum: The input matrixsigmais modified in-place.
Details
Applies positive definiteness enforcement using
mp.pdm.Applies denoising using
mp.dnand the ratioT / NfromX.Applies detoning using
mp.dt.Applies an optional custom matrix processing algorithm using
mp.alg.The order of operations depends on the specific type of
mp.order.
Examples
julia> using StableRNGs, Statistics
julia> rng = StableRNG(123456789);
julia> X = rand(rng, 10, 5);
julia> sigma = cov(X)
5×5 Matrix{Float64}:
0.132026 0.0022567 0.0198243 0.00359832 -0.00743829
0.0022567 0.0514194 -0.0131242 0.004123 0.0312379
0.0198243 -0.0131242 0.0843837 -0.0325342 -0.00609624
0.00359832 0.004123 -0.0325342 0.0424332 0.0152574
-0.00743829 0.0312379 -0.00609624 0.0152574 0.0926441
julia> matrix_processing!(DenoiseDetoneAlgMatrixProcessing(; dn = Denoise()), sigma, X)
5×5 Matrix{Float64}:
0.132026 0.0 0.0 0.0 0.0
0.0 0.0514194 0.0 0.0 0.0
0.0 0.0 0.0843837 0.0 0.0
0.0 0.0 0.0 0.0424332 0.0
0.0 0.0 0.0 0.0 0.0926441
julia> sigma = cov(X)
5×5 Matrix{Float64}:
0.132026 0.0022567 0.0198243 0.00359832 -0.00743829
0.0022567 0.0514194 -0.0131242 0.004123 0.0312379
0.0198243 -0.0131242 0.0843837 -0.0325342 -0.00609624
0.00359832 0.004123 -0.0325342 0.0424332 0.0152574
-0.00743829 0.0312379 -0.00609624 0.0152574 0.0926441
julia> matrix_processing!(DenoiseDetoneAlgMatrixProcessing(; dt = Detone()), sigma, X)
5×5 Matrix{Float64}:
0.132026 0.0124802 0.0117303 0.0176194 0.0042142
0.0124802 0.0514194 0.0273105 -0.0290864 0.0088165
0.0117303 0.0273105 0.0843837 -0.00279296 0.0619156
0.0176194 -0.0290864 -0.00279296 0.0424332 -0.0242252
0.0042142 0.0088165 0.0619156 -0.0242252 0.0926441Related
References
[1] M. M. De Prado. Machine learning for asset managers (Cambridge University Press, 2020). Chapter 2.
[2] V. A. Marčenko and L. A. Pastur. Distribution of eigenvalues for some sets of random matrices. Mathematics of the USSR-Sbornik 1, 457 (1967).
PortfolioOptimisers.matrix_processing Function
matrix_processing(mp::AbstractMatrixProcessingEstimator, sigma::MatNum, X::MatNum, args...;
kwargs...)
matrix_processing(::Nothing, args...; kwargs...)Out-of-place version of matrix_processing!.
Related
PortfolioOptimisers.matrix_processing_algorithm! Method
matrix_processing_algorithm!(::Nothing, sigma::MatNum, args...; kwargs...)No-op fallback for matrix processing algorithm routines.
These methods are called internally when no matrix processing algorithm is specified (i.e., when the algorithm argument is nothing). They perform no operation and return nothing, ensuring that the matrix processing pipeline can safely skip optional algorithmic steps.
Arguments
::Nothing: Indicates that no algorithm is notnothing.args...: Additional positional arguments (ignored).kwargs...: Additional keyword arguments (ignored).
Returns
sigma::MatNum: The input matrixsigmais returned unchanged.
Related
sourcePortfolioOptimisers.matrix_processing_algorithm Method
matrix_processing_algorithm(::Nothing, sigma::MatNum, args...; kwargs...)Same as matrix_processing_algorithm!, but meant for returning a new matrix instead of modifying it in-place.
Related
source