Skip to content
18

Base moments

Abstract moment types and fallbacks

Some optimisations and constraints make use of summary statistics. These types and functions form the base for moment estimation in PortfolioOptimisers.jl.

They also provide generic fallbacks for the various functionality in the library.

PortfolioOptimisers.AbstractExpectedReturnsEstimator Type
julia
abstract type AbstractExpectedReturnsEstimator <: AbstractEstimator

Abstract supertype for all expected returns estimator types.

All concrete and/or abstract types that implement expected returns estimation should be subtypes of AbstractExpectedReturnsEstimator.

Interfaces

In order to implement a new expected returns estimator which will work seamlessly with the library, subtype AbstractExpectedReturnsEstimator with all necessary parameters–-including observation weights–-as part of the struct, and implement the following methods:

Expected returns

  • Statistics.mean(me::AbstractExpectedReturnsEstimator, X::MatNum; kwargs...) -> ArrNum: Expected returns estimation.

Arguments

  • me: Expected returns estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • kwargs...: Additional keyword arguments passed to the mean estimator.

Returns

  • mu::ArrNum: Expected returns vector features x 1 if the dims keyword does not exist or dims = 2, 1 x features if dims = 1.

Factory

  • PortfolioOptimisers.factory(me::AbstractExpectedReturnsEstimator, w::PortfolioOptimisers.ObsWeights) -> AbstractExpectedReturnsEstimator: Factory method for creating instances of the estimator with new observation weights.

Arguments

  • me: Expected returns estimator.

  • w: Observation weights vector observations × 1.

Returns

  • me: New expected returns estimator of the same type as the argument, with the appropriate weights applied.

Examples

julia
julia> struct MyExpectedReturnsEstimator{T1} <:
              PortfolioOptimisers.AbstractExpectedReturnsEstimator
           w::T1
           function MyExpectedReturnsEstimator(w::PortfolioOptimisers.Option{<:PortfolioOptimisers.ObsWeights})
               PortfolioOptimisers.assert_nonempty_nonneg_finite_val(w, :w)
               return new{typeof(w)}(w)
           end
       end

julia> function MyExpectedReturnsEstimator(;
                                           w::PortfolioOptimisers.Option{<:PortfolioOptimisers.ObsWeights} = nothing)
           return MyExpectedReturnsEstimator(w)
       end
MyExpectedReturnsEstimator

julia> function PortfolioOptimisers.factory(::MyExpectedReturnsEstimator,
                                            w::PortfolioOptimisers.ObsWeights)
           return MyExpectedReturnsEstimator(; w = w)
       end

julia> function Statistics.mean(est::MyExpectedReturnsEstimator, X::PortfolioOptimisers.MatNum;
                                dims::Int = 1, kwargs...)
           PortfolioOptimisers.assert_dims(dims)
           if dims == 2
               X = X'
           end
           w = isnothing(est.w) ? fill(one(eltype(X)), size(X, 1)) : est.w
           X = X .* w
           mu = sum(X; dims = 1) / sum(w)
           return isone(dims) ? reshape(mu, 1, :) : reshape(mu, :, 1)
       end

julia> mean(MyExpectedReturnsEstimator(), [1.0 2.0; 0.3 0.7; 0.5 1.1]; dims = 2)
3×1 Matrix{Float64}:
 1.5
 0.5
 0.8

julia> PortfolioOptimisers.factory(MyExpectedReturnsEstimator(), StatsBase.Weights([1, 2, 3]))
MyExpectedReturnsEstimator
  w ┴ StatsBase.Weights{Int64, Int64, Vector{Int64}}: [1, 2, 3]

Related

source
PortfolioOptimisers.AbstractExpectedReturnsAlgorithm Type
julia
abstract type AbstractExpectedReturnsAlgorithm <: AbstractAlgorithm

Abstract supertype for all expected returns algorithm types.

All concrete and/or abstract types that implement a specific algorithm used by an expected returns estimator should be subtypes of AbstractExpectedReturnsAlgorithm.

Interfaces

Given that these are meant to be used by expected returns estimators, there are no specific methods that need to be implemented for this abstract type. However, it serves as a marker for dispatching and organising different expected returns algorithms within the library. The interfaces should be defined at the level of the expected returns estimator that utilises these algorithms.

Related

source
PortfolioOptimisers.AbstractMomentAlgorithm Type
julia
abstract type AbstractMomentAlgorithm <: AbstractAlgorithm

Abstract supertype for all moment algorithm types.

All concrete and/or abstract types that implement a specific algorithm for moment estimation should be subtypes of AbstractMomentAlgorithm.

Interfaces

Given that these are meant to be used by covariance estimators, there are no specific methods that need to be implemented for this abstract type. However, it serves as a marker for dispatching and organising different moment algorithms within the library. The interfaces should be defined at the level of the covariance estimator that utilises these algorithms.

Related

source
PortfolioOptimisers.AbstractCovarianceEstimator Type
julia
abstract type AbstractCovarianceEstimator <: CovarianceEstimator

Abstract supertype for all covariance estimator types.

All concrete and/or abstract types that implement covariance estimation should be subtypes of AbstractCovarianceEstimator.

Interfaces

In order to implement a new covariance estimator which will work seamlessly with the library, subtype AbstractCovarianceEstimator with all necessary parameters–-including observation weights–-as part of the struct, and implement the following methods:

Covariance and correlation

  • Statistics.cov(ce::AbstractCovarianceEstimator, X::MatNum; kwargs...) -> MatNum: Covariance matrix estimation.

  • Statistics.cor(ce::AbstractCovarianceEstimator, X::MatNum; kwargs...) -> MatNum: Correlation matrix estimation.

Arguments

  • ce: Covariance estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • kwargs...: Additional keyword arguments passed to the underlying covariance estimator.

Returns

  • sigrho::MatNum: Covariance/correlation matrix features x features.

Factory

  • PortfolioOptimisers.factory(ce::AbstractCovarianceEstimator, w::PortfolioOptimisers.ObsWeights) -> AbstractCovarianceEstimator: Factory method for creating instances of the estimator with new observation weights.

Arguments

  • ce: Covariance estimator.

  • w: Observation weights vector observations × 1.

Returns

  • ce: New covariance estimator of the same type as the argument, with the new weights applied.

Examples

We can create a dummy covariance estimator as follows:

julia
julia> struct MyCovarianceEstimator{T1} <: PortfolioOptimisers.AbstractCovarianceEstimator
           w::T1
           function MyCovarianceEstimator(w::PortfolioOptimisers.Option{<:PortfolioOptimisers.ObsWeights})
               PortfolioOptimisers.assert_nonempty_nonneg_finite_val(w, :w)
               return new{typeof(w)}(w)
           end
       end

julia> function MyCovarianceEstimator(;
                                      w::PortfolioOptimisers.Option{<:PortfolioOptimisers.ObsWeights} = nothing)
           return MyCovarianceEstimator(w)
       end
MyCovarianceEstimator

julia> function PortfolioOptimisers.factory(::MyCovarianceEstimator,
                                            w::PortfolioOptimisers.ObsWeights)
           return MyCovarianceEstimator(; w = w)
       end

julia> function Statistics.cov(est::MyCovarianceEstimator, X::PortfolioOptimisers.MatNum;
                               dims::Int = 1, kwargs...)
           PortfolioOptimisers.assert_dims(dims)
           if dims == 2
               X = X'
           end
           w = ifelse(isnothing(est.w), StatsBase.fweights(fill(1.0, size(X, 1))), est.w)
           X = X .* w
           sigma = X * X'
           return sigma
       end

julia> function Statistics.cor(est::MyCovarianceEstimator, X::PortfolioOptimisers.MatNum;
                               dims::Int = 1, kwargs...)
           PortfolioOptimisers.assert_dims(dims)
           if dims == 2
               X = X'
           end
           w = isnothing(est.w) ? StatsBase.fweights(fill(1.0, size(X, 1))) : est.w
           X = X .* w
           sigma = X * X'
           d = LinearAlgebra.diag(sigma)
           StatsBase.cov2cor!(sigma, sqrt.(d))
           return sigma
       end

julia> cov(MyCovarianceEstimator(), [1.0 2.0; 0.3 0.7; 0.5 1.1])
3×3 Matrix{Float64}:
 5.0  1.7   2.7
 1.7  0.58  0.92
 2.7  0.92  1.46

julia> cor(MyCovarianceEstimator(), [1.0 2.0; 0.3 0.7; 0.5 1.1])
3×3 Matrix{Float64}:
 1.0       0.998274  0.999315
 0.998274  1.0       0.999764
 0.999315  0.999764  1.0

julia> PortfolioOptimisers.factory(MyCovarianceEstimator(), StatsBase.Weights([1, 2, 3]))
MyCovarianceEstimator
  w ┴ StatsBase.Weights{Int64, Int64, Vector{Int64}}: [1, 2, 3]

Related

source
PortfolioOptimisers.AbstractVarianceEstimator Type
julia
abstract type AbstractVarianceEstimator <: AbstractCovarianceEstimator

Abstract supertype for all variance estimator types.

All concrete and/or abstract types that implement variance estimation should be subtypes of AbstractVarianceEstimator.

Interfaces

In order to implement a new covariance estimator which will work seamlessly with the library, subtype AbstractVarianceEstimator with all necessary parameters–-including observation weights–-as part of the struct, and implement the following methods:

Variance and standard deviation

  • Statistics.var(ve::AbstractVarianceEstimator, X::MatNum; kwargs...) -> ArrNum: Variance estimation.

  • Statistics.std(ve::AbstractVarianceEstimator, X::MatNum; kwargs...) -> ArrNum: Standard deviation estimation.

  • Statistics.var(ve::AbstractVarianceEstimator, X::VecNum; kwargs...) -> Num: Variance estimation.

  • Statistics.std(ve::AbstractVarianceEstimator, X::VecNum; kwargs...) -> Num: Standard deviation estimation.

Arguments

  • ve: Variance estimator.

  • X

    • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

    • X: Data vector observations × 1.

  • kwargs...: Additional keyword arguments passed to the mean estimator.

Returns

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

    • res::ArrNum: Variance or standard deviation vector of X, reshaped to be consistent with the dimension along which the value is computed.
  • X: Data vector observations × 1.

    • res::Number: Variance or standard deviation X

Factory

  • PortfolioOptimisers.factory(ve::AbstractVarianceEstimator, w::PortfolioOptimisers.ObsWeights) -> AbstractVarianceEstimator: Factory method for creating instances of the estimator with new observation weights.

Arguments

  • ve: Variance estimator.

  • w: Observation weights vector observations × 1.

Returns

  • ve: New variance estimator of the same type as the argument, with the new weights applied.

Examples

We can create a dummy variance estimator as follows:

julia
julia> struct MyVarianceEstimator{T1} <: PortfolioOptimisers.AbstractVarianceEstimator
           w::T1
           function MyVarianceEstimator(w::PortfolioOptimisers.Option{<:PortfolioOptimisers.ObsWeights})
               PortfolioOptimisers.assert_nonempty_nonneg_finite_val(w, :w)
               return new{typeof(w)}(w)
           end
       end

julia> function MyVarianceEstimator(;
                                    w::PortfolioOptimisers.Option{<:PortfolioOptimisers.ObsWeights} = nothing)
           return MyVarianceEstimator(w)
       end
MyVarianceEstimator

julia> function PortfolioOptimisers.factory(::MyVarianceEstimator,
                                            w::PortfolioOptimisers.ObsWeights)
           return MyVarianceEstimator(; w = w)
       end

julia> function Statistics.var(est::MyVarianceEstimator, X::PortfolioOptimisers.MatNum;
                               dims::Int = 1, kwargs...)
           PortfolioOptimisers.assert_dims(dims)
           if dims == 2
               X = X'
           end
           w = isnothing(est.w) ? StatsBase.fweights(fill(1.0, size(X, 1))) : est.w
           X = X .* w
           sigma = LinearAlgebra.diag(X * X')
           return isone(dims) ? reshape(sigma, 1, :) : reshape(sigma, :, 2)
       end

julia> function Statistics.std(est::MyVarianceEstimator, X::PortfolioOptimisers.MatNum;
                               dims::Int = 1, kwargs...)
           PortfolioOptimisers.assert_dims(dims)
           if dims == 2
               X = X'
           end
           w = isnothing(est.w) ? StatsBase.fweights(fill(1.0, size(X, 1))) : est.w
           X = X .* w
           sigma = sqrt.(LinearAlgebra.diag(X * X'))
           return isone(dims) ? reshape(sigma, 1, :) : reshape(sigma, :, 1)
       end

julia> function Statistics.var(est::MyVarianceEstimator, X::PortfolioOptimisers.VecNum; kwargs...)
           w = isnothing(est.w) ? StatsBase.fweights(fill(1.0, size(X, 1))) : est.w
           X = X .* w
           return mean(LinearAlgebra.diag(X' * X))
       end

julia> function Statistics.std(est::MyVarianceEstimator, X::PortfolioOptimisers.VecNum; kwargs...)
           w = isnothing(est.w) ? StatsBase.fweights(fill(1.0, size(X, 1))) : est.w
           X = X .* w
           return sqrt(mean(LinearAlgebra.diag(X' * X)))
       end

julia> var(MyVarianceEstimator(), [1.0 2.0; 0.3 0.7; 0.5 1.1])
1×3 Matrix{Float64}:
 5.0  0.58  1.46

julia> std(MyVarianceEstimator(), [1.0 2.0; 0.3 0.7; 0.5 1.1])
1×3 Matrix{Float64}:
 2.23607  0.761577  1.2083

julia> PortfolioOptimisers.factory(MyVarianceEstimator(), StatsBase.Weights([1, 2, 3]))
MyVarianceEstimator
  w ┴ StatsBase.Weights{Int64, Int64, Vector{Int64}}: [1, 2, 3]

Related

source
PortfolioOptimisers.port_opt_view Method
julia
port_opt_view(
    ce::CovarianceEstimator,
    _,
    args...
) -> SpearmanCovariance{<:AbstractVarianceEstimator}

No-op fallback for getting the view of a covariance estimator.

Arguments

  • ce: Covariance estimator.

  • args...: Optional arguments (ignored).

Returns

  • ce::StatsBase.CovarianceEstimator: The original covariance estimator.

Related

source
PortfolioOptimisers.factory Method
julia
factory(
    ce::StatsBase.CovarianceEstimator,
    args...;
    kwargs...
) -> StatsBase.CovarianceEstimator

Fallback for covariance estimator factory methods.

Arguments

  • ce: Covariance estimator.

  • args...: Optional arguments (ignored).

  • kwargs...: Optional keyword arguments (ignored).

Returns

  • ce::StatsBase.CovarianceEstimator: The original covariance estimator.

Related

source
PortfolioOptimisers.port_opt_view Method
julia
port_opt_view(
    me::AbstractExpectedReturnsEstimator,
    _,
    args...
) -> Union{EquilibriumExpectedReturns{<:CovarianceEstimator, Nothing, <:Number}, EquilibriumExpectedReturns{var"#s179", <:AbstractVector{var"#s35"}, <:Number} where {var"#s179"<:CovarianceEstimator, var"#s35"<:(Union{var"#s34", var"#s33"} where {var"#s34"<:Number, var"#s33"<:AbstractJuMPScalar})}}

No-op fallback for getting the view of an expected returns estimator.

Arguments

  • me: Expected returns estimator.

  • args...: Optional arguments (ignored).

Returns

  • me::AbstractExpectedReturnsEstimator: The original expected returns estimator.

Related

source
PortfolioOptimisers.factory Method
julia
factory(a::Union{Nothing, <:AbstractEstimator, <:AbstractAlgorithm,
                 <:AbstractResult}, args...; kwargs...) -> a

No-op factory function for constructing objects with a uniform interface.

Defining methods which dispatch on the first argument allows for a consistent factory interface across different types.

factory and port_opt_view are the two propagation mechanisms in this library. They are duals: factory threads runtime values (prior moments, observation weights, previous portfolio weights) down through a composed struct tree; port_opt_view threads an index selection (a subset of assets or observations) down through the same tree.

Arguments

  • a: Indicates no object should be constructed.

  • args...: Arbitrary positional arguments (ignored).

  • kwargs...: Arbitrary keyword arguments (ignored).

Returns

  • a: The input unchanged.

Examples

julia
julia> factory(nothing, 1, 2; x = 3)

julia> factory(MeanValue())
MeanValue
  w ┴ nothing

Related

source
PortfolioOptimisers.port_opt_view Method
julia
port_opt_view(
    alg::AbstractExpectedReturnsAlgorithm,
    _,
    args...
) -> AbstractExpectedReturnsAlgorithm

No-op fallback for getting the view of an expected returns algorithm.

Arguments

  • alg: The expected returns algorithm.

  • args...: Optional arguments (ignored).

Returns

  • alg::AbstractExpectedReturnsAlgorithm: The original expected returns algorithm.

Related

source
PortfolioOptimisers.factory Method
julia
factory(a::Union{Nothing, <:AbstractEstimator, <:AbstractAlgorithm,
                 <:AbstractResult}, args...; kwargs...) -> a

No-op factory function for constructing objects with a uniform interface.

Defining methods which dispatch on the first argument allows for a consistent factory interface across different types.

factory and port_opt_view are the two propagation mechanisms in this library. They are duals: factory threads runtime values (prior moments, observation weights, previous portfolio weights) down through a composed struct tree; port_opt_view threads an index selection (a subset of assets or observations) down through the same tree.

Arguments

  • a: Indicates no object should be constructed.

  • args...: Arbitrary positional arguments (ignored).

  • kwargs...: Arbitrary keyword arguments (ignored).

Returns

  • a: The input unchanged.

Examples

julia
julia> factory(nothing, 1, 2; x = 3)

julia> factory(MeanValue())
MeanValue
  w ┴ nothing

Related

source
Statistics.cov Method
julia
Statistics.cov(ce::AbstractCovarianceEstimator, X::MatNum; dims::Int = 1, kwargs...)

Generic covariance fallback assembling the covariance matrix from the estimator's correlation matrix and the marginal standard deviations of its variance estimator ce.ve.

This fallback lets a correlation-style covariance estimator define only its Statistics.cor method; the covariance is then recovered by rescaling the correlation matrix with the standard deviations obtained from std(ce.ve, X). Estimators whose covariance is not a plain rescaling of their correlation (for example ImpliedVolatility) override this method.

Mathematical definition

Σ^ij=ρ^ijσ^iσ^j.

Where:

  • Σ^: Estimated covariance matrix.

  • ρ^ij: Correlation between assets i and j, from cor(ce, X).

  • σ^i: Standard deviation of asset i, from std(ce.ve, X).

Arguments

  • ce: Covariance estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • dims: Dimension along which to perform the computation.

  • kwargs...: Additional keyword arguments passed to cor and to the variance estimator.

Returns

  • sigma::MatNum: Covariance matrix features x features.

Related

source
PortfolioOptimisers.robust_cov Function
julia
robust_cov(
    ce::StatsBase.CovarianceEstimator,
    X::MatNum,
    [w::StatsBase.AbstractWeights];
    dims::Int = 1,
    mean = nothing,
    kwargs...
) -> MatNum

Tries calling compat_cov and falls back to a densified Matrix if a MethodError is thrown.

Arguments

  • ce: Covariance estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • w: Optional observation weights vector observations × 1, or a concrete subtype of DynamicAbstractWeights. If nothing, the computation is unweighted.

  • dims: Dimension along which to perform the computation.

  • mean: Optional mean value to use for centering.

  • kwargs...: Additional keyword arguments passed to compat_cov.

Returns

  • sigma::MatNum: Covariance matrix features x features.

Details

  • This function computes the optionally weighted covariance matrix using the provided estimator and keyword arguments.

  • If the call throws a MethodError, it is retried once with a densified Matrix(X).

Related

source
PortfolioOptimisers.robust_cor Function
julia
robust_cor(
    ce::StatsBase.CovarianceEstimator,
    X::MatNum,
    [w::StatsBase.AbstractWeights];
    dims::Int = 1,
    mean = nothing,
    kwargs...
) -> MatNum

Tries calling compat_cor and falls back to a densified Matrix if a MethodError is thrown.

Arguments

  • ce: Covariance estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • w: Optional observation weights vector observations × 1, or a concrete subtype of DynamicAbstractWeights. If nothing, the computation is unweighted.

  • dims: Dimension along which to perform the computation.

  • mean: Optional mean value to use for centering.

  • kwargs...: Additional keyword arguments passed to compat_cor.

Returns

  • rho::MatNum: Correlation matrix features x features.

Details

  • This function computes the optionally weighted correlation matrix using the provided estimator and keyword arguments.

  • If the call throws a MethodError, it is retried once with a densified Matrix(X).

Related

source
PortfolioOptimisers.compat_cov Function
julia
compat_cov(
    ce::StatsBase.CovarianceEstimator,
    X::MatNum,
    [w::StatsBase.AbstractWeights];
    dims::Int = 1,
    mean = nothing,
    kwargs...
) -> MatNum

Compute the covariance matrix robustly using the specified covariance estimator ce, data matrix X, and optional weights vector w.

Arguments

  • ce: Covariance estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • w: Optional observation weights vector observations × 1, or a concrete subtype of DynamicAbstractWeights. If nothing, the computation is unweighted.

  • dims: Dimension along which to perform the computation.

  • mean: Optional mean value to use for centering.

  • kwargs...: Additional keyword arguments passed to cov.

Returns

  • sigma::MatNum: Covariance matrix features x features.

Details

  • This function computes the optionally weighted covariance matrix using the provided estimator and keyword arguments.

  • Keyword arguments are only forwarded if the estimator's cov method accepts them (checked via hasmethod); otherwise the call is made with dims and mean alone. If the forwarded call throws a MethodError (e.g. a kwargs... slurp that rejects them further down its call chain), it is retried without them. Genuine errors thrown by the estimator propagate to the caller.

  • If the call throws a MethodError, it is retried once with a densified Matrix(X).

Related

source
PortfolioOptimisers.compat_cor Function
julia
compat_cor(
    ce::StatsBase.CovarianceEstimator,
    X::MatNum,
    [w::StatsBase.AbstractWeights];
    dims::Int = 1,
    mean = nothing,
    kwargs...
) -> MatNum

Compute the correlation matrix robustly using the specified covariance estimator ce, data matrix X, and optional weights vector w.

Arguments

  • ce: Covariance estimator.

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • w: Optional observation weights vector observations × 1, or a concrete subtype of DynamicAbstractWeights. If nothing, the computation is unweighted.

  • dims: Dimension along which to perform the computation.

  • mean: Optional mean value to use for centering.

  • kwargs...: Additional keyword arguments passed to cor.

Returns

  • rho::MatNum: Correlation matrix features x features.

Details

  • This function computes the optionally weighted correlation matrix using the provided estimator and keyword arguments.

  • Keyword arguments are only forwarded if the estimator's cor method accepts them (checked via hasmethod); otherwise the call is made with dims and mean alone. If the forwarded call throws a MethodError (e.g. a kwargs... slurp that rejects them further down its call chain), it is retried without them. Genuine errors thrown by the estimator propagate to the caller.

  • If the estimator defines no suitable cor method, the result is computed with robust_cov and converted to a correlation matrix.

  • If the call throws a MethodError, it is retried once with a densified Matrix(X).

Related

source
PortfolioOptimisers.moment_window_and_weights Function
julia
moment_window_and_weights(
    X::VecNum_MatNum,
    w::Option{<:ObsWeights},
    args...;
    dims = dims,
    kwargs...
) -> (VecNum_MatNum, Option{<:StatsBase.AbstractWeights})
moment_window_and_weights(
    X::VecNum_MatNum,
    w::Option{<:ObsWeights},
    window::VecInt;
    dims = dims,
    kwargs...
) -> (VecNum_MatNum, Option{<:StatsBase.AbstractWeights})

Apply the observation window and resolve weights for moment estimation.

Slices X to the last window observations (if provided) and resolves the observation weights, returning the windowed data and finalised weights.

Arguments

  • X: Data matrix or vector.

  • w: Optional observation weights vector observations × 1, or a concrete subtype of DynamicAbstractWeights. If nothing, the computation is unweighted.

  • Either:

    • args: Additional positional arguments (ignored).

    • window: Observation window.

  • dims: Dimension along which to perform the computation. Ignored if X is a vector.

  • kwargs: Additional keyword arguments (ignored).

Returns

  • X::VecNum_MatNum: Appropriately windowed data matrix.

  • w::Option{<:StatsBase.AbstractWeights}: Resolved and appropriately windowed weights.

Details

  • If window is provided:

  • If no window is provided:

  • Returns the appropriate X and w.

Related

source
PortfolioOptimisers.windowed_preamble Function
julia
windowed_preamble(
    est,
    w::Union{Nothing, DynamicAbstractWeights, AbstractWeights},
    window::Union{Nothing, Integer, AbstractVector{<:Integer}},
    X::AbstractMatrix{<:Union{var"#s34", var"#s33"} where {var"#s34"<:Number, var"#s33"<:AbstractJuMPScalar}};
    iv,
    dims,
    kwargs...
) -> Tuple{Any, Any, Nothing}

Shared preamble for windowed moment estimators (matrix input).

Resolves the window specification, subsets X (and iv) to the selected observations, rebinds observation weights to the window, and builds a weight-updated copy of est via factory. Whenever a window is given — an Int (which resolves to a range) or an explicit index vector — iv is subset to the same rows, or columns when dims = 2, so it stays aligned with the windowed returns. Only window = nothing, which resolves to a Colon, leaves iv unchanged.

Arguments

  • est: Wrapped moment estimator to be cloned with updated weights.

  • w: Optional observation weights applied after windowing.

  • window: Window specification — nothing (full data), an Int (last window observations), or a VecInt of explicit row/column indices.

  • X: Data matrix of asset returns.

  • iv: Optional instrument variable matrix; subsetted to the window when window is a VecInt.

  • dims: Observation dimension — 1 for rows (default), 2 for columns.

  • kwargs...: Passed through to moment_window_and_weights.

Returns

  • (inner, X, iv): Weight-updated estimator, windowed returns matrix, and (possibly subsetted) instrument variable matrix.

Related

source
julia
windowed_preamble(
    est,
    w::Union{Nothing, DynamicAbstractWeights, AbstractWeights},
    window::Union{Nothing, Integer, AbstractVector{<:Integer}},
    X::AbstractVector{<:Union{var"#s34", var"#s33"} where {var"#s34"<:Number, var"#s33"<:AbstractJuMPScalar}}
) -> Tuple{Any, Any}

Shared preamble for windowed moment estimators (vector input).

Resolves the window specification, subsets X to the selected observations, rebinds observation weights to the window, and builds a weight-updated copy of est via factory.

Arguments

  • est: Wrapped moment estimator to be cloned with updated weights.

  • w: Optional observation weights applied after windowing.

  • window: Window specification — nothing (full data), an Int (last window observations), or a VecInt of explicit indices.

  • X: Data vector of returns.

Returns

  • (inner, X): Weight-updated estimator and windowed returns vector.

Related

source
PortfolioOptimisers.demean_returns Function
julia
demean_returns(X::MatNum, me::AbstractExpectedReturnsEstimator; dims::Int = 1, mean = nothing,
               kwargs...) -> MatNum

Demeans the returns in X using the expected returns estimator me or if provided, a mean array.

Arguments

  • X: Data matrix observations × features if the dims keyword does not exist or dims = 1, features × observations when dims = 2.

  • me: Expected returns estimator.

  • dims: Dimension along which to perform the computation.

  • mean: Optional mean value to use for centering.

  • kwargs...: Additional keyword arguments for the expected returns estimator.

Returns

  • MatNum: The demeaned returns matrix.

Related

source

Windowed estimator generation

The five windowed estimators — WindowedExpectedReturns, WindowedVariance, WindowedCovariance, WindowedCoskewness and WindowedCokurtosis — share one shape: wrap an inner estimator, restrict it to a trailing window, and forward every moment call to it. Each is generated from a single declaration by @windowed_estimator, so the struct, its constructor, its factory/port_opt_view methods, its forwarding methods and all of their docstrings cannot drift apart.

The entries below are the macro and its expansion-time machinery. They are internal: callers use the five estimators, not these.

PortfolioOptimisers.@windowed_estimator Macro
julia
@windowed_estimator Name <: Super begin
    field::FieldType = Default()
    noun    = "Noun"
    forward = [generic(::MatNum; mean) => :ret_key, ...]
    doctest = """..."""
end

Declare a windowed moment estimator: a wrapper that restricts an inner moment estimator to a sub-window of observations and rebinds observation weights to that window, leaving the inner estimator's semantics untouched.

One invocation emits the whole family member — the @propagatable @concrete struct (inner estimator tagged @fprop @vprop, w tagged @wprop, plus window), both constructors with their validation, one forwarding method per forward entry, the export, and every docstring.

Five nominal types exist rather than one parametric Windowed{E} because each answers a different generic and must subtype a different abstract estimator — AbstractCovarianceEstimator, CoskewnessEstimator, and the rest are load-bearing for dispatch across the library, and a Julia struct's supertype cannot depend on a type parameter. This macro is what keeps the five in sync; see ADR 0039.

Body

  • field::FieldType = Default(): the inner estimator. The field name is also its field_dict key and the argument name of every generated method, so it must follow the library convention (me, ce, ve, ske, kte).

  • noun: capitalised noun phrase naming the moment, e.g. "Expected returns". Drives all generated prose.

  • forward: one mini-signature per generic to forward, paired with the ret_dict key(s) documenting its return values. Naming mean in the mini-signature emits it as a named keyword instead of letting it ride in kwargs..., where it would leak into windowed_preamble.

  • doctest: the body of the jldoctest block for the # Examples section, without its fences.

Unknown keys, malformed forward entries, and unknown field_dict/ret_dict keys are rejected at macro-expansion time with a did_you_mean suggestion.

Examples

julia
@windowed_estimator WindowedVariance <: AbstractVarianceEstimator begin
    ve::AbstractVarianceEstimator = SimpleVariance()
    noun = "Variance"
    forward = [Statistics.var(::MatNum; mean) => :vararr,
               Statistics.var(::VecNum; mean) => :varnum]
    doctest = """
    julia> WindowedVariance()
    ...
    """
end

Related

source
PortfolioOptimisers.WINDOWED_ESTIMATOR_KEYS Constant
julia
WINDOWED_ESTIMATOR_KEYS

Assignment keys recognised in a @windowed_estimator body, besides the single field::Type = default declaration. Anything else is rejected at macro-expansion time with a did_you_mean suggestion, so a mistyped key cannot silently produce a malformed docstring or a missing forwarding method.

Related

source
PortfolioOptimisers.WINDOWED_ESTIMATOR_INPUTS Constant
julia
WINDOWED_ESTIMATOR_INPUTS

Input types a @windowed_estimator forward entry may declare. MatNum generates the matrix forwarder (threading dims and iv through windowed_preamble), VecNum the vector forwarder.

Related

source
PortfolioOptimisers.windowed_parse_field Function
julia
windowed_parse_field(ex) -> Tuple{Symbol, Any, Any}

Parse the field::Type = default line of a @windowed_estimator body into the inner estimator's field name, its declared type, and its keyword-constructor default.

The field name doubles as the field_dict key for the generated field docstring and as the argument name of every generated forwarding method, so it must follow the library's naming convention (me, ce, ve, ske, kte).

Related

source
PortfolioOptimisers.windowed_parse_forward Function
julia
windowed_parse_forward(
    ex
) -> Tuple{Any, Any, Bool, Vector{Symbol}}

Parse one forward entry of a @windowed_estimator body — generic(::MatNum; mean) => :ret_key — into the generic being forwarded, its input type, whether it names a mean keyword, and the ret_dict keys documenting its return values.

Naming mean in the mini-signature is what keeps it out of the forwarded kwargs..., where it would otherwise leak into windowed_preamble.

Related

source
PortfolioOptimisers.windowed_estimator_check_key Function
julia
windowed_estimator_check_key(
    key::Symbol,
    dict::AbstractDict,
    what::AbstractString
) -> Symbol

Validate that key names an entry of dict, appending a did_you_mean suggestion to the error when it does not. what names the table in the message.

Related

source
PortfolioOptimisers.windowed_estimator_suggest Function
julia
windowed_estimator_suggest(key, candidates) -> String

Suggest the nearest candidates entry to a mistyped @windowed_estimator key.

Wraps did_you_mean in a looser scoped configuration than the global default: Damerau-Levenshtein (so a transposed pair costs one edit, not two) at min_score = 0.5. The strict global default exists to keep near-miss probes from echoing real asset names back to the caller (ADR 0026); that boundary does not apply here, because the candidates are compile-time constants — block keys and field_dict/ret_dict names — with nothing to leak. At the default 0.7 under plain Levenshtein, short keys never match: nuon scores 0.5 against noun, so the suggestion would be dead code.

Related

source
PortfolioOptimisers.windowed_estimator_error Function
julia
windowed_estimator_error(msg::AbstractString)

Throw a uniform, expansion-time ArgumentError for a malformed @windowed_estimator declaration.

Related

source
PortfolioOptimisers.windowed_type_doc Function
julia
windowed_type_doc(
    name::Symbol,
    super,
    field::Symbol,
    ftype,
    default,
    noun::AbstractString,
    doctest::AbstractString,
    methods::Vector{String}
) -> Expr

Build the type docstring of a generated windowed estimator as an interpolation AST, keeping DocStringExtensions abbreviations and dictionary lookups live (see windowed_method_doc).

Related

source
PortfolioOptimisers.windowed_method_ref Function
julia
windowed_method_ref(
    gen,
    field::Symbol,
    name::Symbol,
    input::Symbol
) -> String

Render the generic(field::Name, X::Input) reference used to cross-link one generated forwarding method from the type's and its siblings' # Related sections.

Keyword arguments are deliberately omitted: Documenter resolves an @ref by positional method signature, and the two positional types already identify the method uniquely.

Related

source
PortfolioOptimisers.windowed_method_doc Function
julia
windowed_method_doc(
    gen,
    field::Symbol,
    name::Symbol,
    input::Symbol,
    has_mean::Bool,
    ret_keys::Vector{Symbol},
    noun::AbstractString,
    siblings::Vector{String}
) -> Expr

Build the docstring for one generated forwarding method as an interpolation AST.

Returning Expr(:string, ...) rather than a String is load-bearing: it keeps arg_dict and ret_dict lookups as live parts of the DocStr, exactly as a hand-written $(arg_dict[:dims]) would be.

Related

source
PortfolioOptimisers.windowed_method_def Function
julia
windowed_method_def(
    gen,
    field::Symbol,
    name::Symbol,
    input::Symbol,
    has_mean::Bool
) -> Expr

Build one generated forwarding method: resolve the window via windowed_preamble, then delegate to the inner estimator's own method.

Related

source

FullMoment and semi moments

Moments other than the expected return can be estimated using the entire spectrum of deviations (full), or only the deviations below a target (semi/downside). These types allow us to provide such functionality.

PortfolioOptimisers.FullMoment Type
julia
struct FullMoment <: AbstractMomentAlgorithm

FullMoment is used to indicate that all deviations are included in the moment estimation process.

Mathematical definition

D=Xt

Where:

  • X: Data vector observations × 1.

  • t: Target value, usually the unweighted (or weighted) expected value E[X].

Constructors

julia
FullMoment() -> FullMoment

Examples

julia
julia> FullMoment()
FullMoment()

Related

source
PortfolioOptimisers.SemiMoment Type
julia
struct SemiMoment <: AbstractMomentAlgorithm

SemiMoment is used for semi-moment estimators, where only observations below a target are considered.

Mathematical definition

D=min(Xt,0)

Where:

  • X: Data vector observations × 1.

  • t: Target value, usually the unweighted (or weighted) expected value E[X].

Constructors

julia
SemiMoment() -> SemiMoment

Examples

julia
julia> SemiMoment()
SemiMoment()

Related

source