Gerber Information Quality Covariance

PortfolioOptimisers.BaseGerberIQCovarianceType
abstract type BaseGerberIQCovariance <: BaseGerberCovariance

Abstract supertype for all Gerber Information Quality covariance estimators.

All concrete and/or abstract types implementing Gerber Information Quality covariance estimation algorithms should be subtypes of BaseGerberIQCovariance.

The family extends BaseGerberCovariance in two directions. It weights a co-movement by the region of the return plane it falls in, instead of counting it, and it discounts a co-movement by its age. GerberCovarianceAlgorithm states the co-movement statistic these estimators reduce to, and this file does not restate it.

Interfaces

If moving away from the already established Gerber Information Quality covariance algorithms, you must follow AbstractCovarianceEstimator to implement the entire chain.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.GerberIQCovarianceAlgorithmType
abstract type GerberIQCovarianceAlgorithm <: AbstractMomentAlgorithm

Abstract supertype for all Gerber Information Quality covariance estimation algorithms.

All concrete and/or abstract types implementing Gerber Information Quality covariance estimation algorithms should be subtypes of GerberIQCovarianceAlgorithm.

A subtype is a squeezing template. It cuts the plane of the two assets' returns into channels, and it names the weight that a co-movement in each channel carries. The library ships the source's three templates, ordered by how many channels they separate: BasicGerberIQ with one boundary and one weight, PartialGerberIQ with four boundaries and ten weights, and FullGerberIQ with four boundaries and twenty-one weights over thirty-six channels.

Interfaces

A subtype must implement gerber_iq_weight, which returns the weight of one co-movement, and gerber_iq_assert_c_d, which checks the noise threshold c against the template's boundaries. It may implement clamp_gerber_iq_n; the fall-through leaves the template unchanged.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.GerberIQEpsEstimatorType
abstract type GerberIQEpsEstimator <: AbstractEstimator

Abstract supertype for all temporal lookback and delay Gerber Information Quality parameter estimators.

All concrete and/or abstract types implementing Gerber Information Quality parameter estimators should be subtypes of GerberIQEpsEstimator.

A subtype computes the delay of the source's temporal vector, the number of periods into the past over which a co-movement carries its full weight. The source names it $\varepsilon$ and leaves its value to expert judgement or to an outer optimisation. The library adds a default formula; gerber_iq_eps states it.

Interfaces

A subtype must implement PortfolioOptimisers.gerber_iq_eps(e::MySubtype, X::MatNum) -> Number. A subtype that implements no method takes the fall-through of gerber_iq_eps.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.GerberIQGammaEstimatorType
abstract type GerberIQGammaEstimator <: AbstractEstimator

Abstract supertype for Gerber IQ estimators for tuning the strength of the lookback decay.

All concrete and/or abstract types implementing Gerber Information Quality parameter estimators should be subtypes of GerberIQGammaEstimator.

A subtype computes the decay rate of the source's temporal vector, the discount rate applied to a co-movement older than the delay. The source names it $\gamma$, requires it to be positive, and leaves its value to expert judgement or to an outer optimisation. The library adds a default formula; gerber_iq_gamma states it.

Interfaces

A subtype must implement PortfolioOptimisers.gerber_iq_gamma(y::MySubtype, X::MatNum) -> Number. A subtype that implements no method takes the fall-through of gerber_iq_gamma.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.GerberIQScalerEstimatorType
abstract type GerberIQScalerEstimator <: AbstractEstimator

Abstract supertype for Gerber IQ estimators for scaling the threshold parameters for defining significant co-movements.

All concrete and/or abstract types implementing threshold scalers for Gerber Information Quality parameter estimators should be subtypes of GerberIQScalerEstimator.

A subtype answers one question for a pair of assets: in whose units are the pair's thresholds measured. The source names four answers — each asset's own volatility, the mean of the two, the greater of the two, and the lesser of the two. The library ships the first as AssetVolatilityGerberIQScaler and the second as the fall-through of gerber_iq_scaling. The other two are reached through the Function arm of GerberIQScaler.

Interfaces

A subtype must implement PortfolioOptimisers.gerber_iq_scaling(sca::MySubtype, sdi::Number, sdj::Number) -> (Number, Number). A subtype that implements no method takes the fall-through of gerber_iq_scaling.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.GerberIQDecayEstimatorType
abstract type GerberIQDecayEstimator <: AbstractEstimator

Abstract supertype for the Gerber IQ estimators that discount an observation by its age.

All concrete and/or abstract types implementing temporal decay for Gerber Information Quality parameter estimators should be subtypes of GerberIQDecayEstimator.

A subtype is a non-increasing function of age. The source states that the age penalty may be any non-increasing function, and gives the exponential form as its own choice; ExpGerberIQDecay implements that form. A subtype is configuration, so it holds its parameters and never a Result. Two methods make it usable: regenerate_decay fills any parameter the caller left unset, and the functor returns the weight of one observation.

Interfaces

In order to implement a new Gerber IQ decay estimator which will work seamlessly with the library, subtype GerberIQDecayEstimator with all necessary parameters as part of the struct, and implement the following methods:

Regenerate Decay

  • PortfolioOptimisers.regenerate_decay(decay::GerberIQDecayEstimator, X::AbstractMatrix) -> GerberIQDecayEstimator: Fallback for automatically computing the decay parameters based on the input data X.

Arguments

  • decay: The decay estimator to regenerate.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.

Returns

  • decay::GerberIQDecayEstimator: A new concrete instance of the subtype of GerberIQDecayEstimator with the decay parameters generated from the input data X.

Functor

  • (decay::GerberIQDecayEstimator)(T::Number, k::Number) -> Number: Evaluate the decay estimator for observation k out of T.

Arguments

  • T::Number: The total number of observations.
  • k::Number: The current observation index.

Returns

  • d::Number: The decay value for observation k out of T.

Examples

We can create a dummy Gerber IQ decay estimator as follows:

julia> struct GaussianDecay{T} <: PortfolioOptimisers.GerberIQDecayEstimator           a::T           function GaussianDecay(a::Union{Nothing, <:Number})               if isa(a, Number)                   PortfolioOptimisers.@argcheck(a >= 0,                                                 DomainError(a, "`a` must be non-negative"))               end               return new{typeof(a)}(a)           end       endjulia> function GaussianDecay(; a::Union{Nothing, <:Number} = nothing)           return GaussianDecay(a)       endGaussianDecayjulia> function PortfolioOptimisers.regenerate_decay(decay::GaussianDecay{<:Number},                                                     ::AbstractMatrix)           return decay       endjulia> function PortfolioOptimisers.regenerate_decay(decay::GaussianDecay{Nothing},                                                     X::AbstractMatrix)           T = size(X, 1)           return GaussianDecay(; a = inv(log(T)))       endjulia> function (decay::GaussianDecay)(T::Number, k::Number)           m = T - k + 1           return exp(-m^2 / (2 * decay.a^2))       endjulia> cor(GerberIQCovariance(; decay = GaussianDecay()), [1.0 2.0; 0.3 0.7; 0.5 1.1])2×2 Matrix{Float64}: 1.0  1.0 1.0  1.0julia> cov(GerberIQCovariance(; decay = GaussianDecay()), [1.0 2.0; 0.3 0.7; 0.5 1.1])2×2 Matrix{Float64}: 0.13      0.240069 0.240069  0.443333

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.AssetVolatilityGerberIQScalerType
struct AssetVolatilityGerberIQScaler <: GerberIQScalerEstimator

Scales the threshold parameters using the individual asset volatilities.

Each asset keeps its own units, so asset $i$ is measured against $\sigma_i$ and asset $j$ against $\sigma_j$. This is the convention of Kendall's tau and of the Gerber statistic, and it is the choice under which the Gerber IQ statistic reduces to the Gerber statistic; gerber_IQ states that reduction. The fall-through of gerber_iq_scaling makes the other choice and gives both assets the mean of the two volatilities.

Mathematical definition

\[\begin{align} (s_i,\, s_j) &= (\sigma_i,\, \sigma_j)\,. \end{align}\]

Where:

  • $s_i$, $s_j$: Threshold scaling factors of the pair.
  • $\sigma_i$: Standard deviation of asset $i$.

Constructors

AssetVolatilityGerberIQScaler() -> AssetVolatilityGerberIQScaler

Examples

julia> AssetVolatilityGerberIQScaler()AssetVolatilityGerberIQScaler()

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.ExpGerberIQDecayType
struct ExpGerberIQDecay{__T_e, __T_y} <: GerberIQDecayEstimator

Exponential Gerber IQ temporal decay.

This is the source's own age penalty. A co-movement no older than e periods carries its full weight, and one older than that is discounted at the rate y for every further period. Either field may be left as nothing; regenerate_decay then fills it from the returns matrix before the statistic runs.

Fields

  • e: Delay. A co-movement no older than e periods carries its full weight. The source names it $\varepsilon$.
  • y: Decay rate. It discounts a co-movement for every period of age beyond e. The source names it $\gamma$.

Constructors

ExpGerberIQDecay(e::Option{<:GerberIQEps} = nothing,                 y::Option{<:GerberIQGamma} = nothing)

Keywords correspond to the struct's fields.

Validation

A field that is not a Number carries no check here, because it is a rule and not a value. regenerate_decay resolves it, and the resolved instance is validated by this same constructor.

Functors

(decay::ExpGerberIQDecay)(T::Number, k::Number) -> Number

Implements the exponential decay for Gerber IQ covariance.

Warning

The functor is not meant to be called directly unless all parameters are numeric. Otherwise, call regenerate_decay first.

Mathematical definition

\[\begin{align} d &= \exp\left[-y \max(0, T - k - e)\right]\,. \end{align}\]

Where:

  • $T$: Is the number of observations.
  • $k$: Is the current index.
  • $e$: Parameter in the instance of ExpGerberIQDecay.
  • $y$: Parameter in the instance of ExpGerberIQDecay.
  • $d$: Is the decay factor.

Arguments

  • T: Number of observations.
  • k: Current time index.

Returns

  • d: The decay factor.

Examples

julia> ExpGerberIQDecay()ExpGerberIQDecay  e ┼ nothing  y ┴ nothing

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.regenerate_decayFunction
regenerate_decay(decay::ExpGerberIQDecay, X::AbstractMatrix) -> ExpGerberIQDecay
regenerate_decay(decay::GerberIQDecayEstimator, X::AbstractMatrix) -> ExpGerberIQDecay

Automatically sets the decay parameters based on the input data X.

The function allocates; it never writes into its argument. A decay estimator is configuration and is treated as immutable, so a regenerated parameter arrives in a new ExpGerberIQDecay. The one case that allocates nothing is an ExpGerberIQDecay whose two fields are already numbers: there is nothing to resolve, and the same object is returned. The caller must therefore use the returned value; discarding it leaves the unresolved estimator in place.

Algorithm

  1. Return decay unchanged when it is an ExpGerberIQDecay whose e and y are both a Number.
  2. Otherwise resolve the delay e with gerber_iq_eps, reading the estimator's own e for an ExpGerberIQDecay and nothing for any other subtype.
  3. Resolve the decay rate y the same way with gerber_iq_gamma.
  4. Return a new ExpGerberIQDecay built from e and y.

Step 2 is why the fall-through discards the subtype: it has no field the two resolvers can read, so it resolves both from X alone and returns an ExpGerberIQDecay. A subtype that must keep its own form implements this function, as the # Interfaces section of GerberIQDecayEstimator states.

Arguments

  • decay: The decay estimator to regenerate.
    • ::ExpGerberIQDecay: If both parameters are numeric, returns the input, otherwise returns a new ExpGerberIQDecay with the regenerated parameters.
    • ::GerberIQDecayEstimator: Fallback for automatically setting the decay parameters e, and y based on the input data X, using gerber_iq_eps and gerber_iq_gamma with nothing as the first input. Custom subtypes of GerberIQDecayEstimator should implement this method, else they default to the fallback.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.

Returns

  • decay::ExpGerberIQDecay: With parameters based on X.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.BasicGerberIQType
struct BasicGerberIQ{__T_d, __T_n} <: GerberIQCovarianceAlgorithm

Implements the basic Gerber IQ covariance template. Divides the comovement data into regions and applies the co-movement compression to co-movements falling within each region. Co-movements within the dashed regions may or may not be included depending on the GerberIQ algorithm used. Co-movements within the central region are always ignored.

This is the source's own reduced template: one boundary and one weight for the whole plane. It is the template the source's results are built on, and it is this estimator's default.

Mathematical definition

\[\begin{align} \eta_{t,\,i,\,j} &= \begin{cases} 1 & d s_i \leq \lvert x_{t,\,i} \rvert \; \text{and} \; d s_j \leq \lvert x_{t,\,j} \rvert \\ n & \lvert x_{t,\,i} \rvert < d s_i \; \text{and} \; \lvert x_{t,\,j} \rvert < d s_j \\ n^2 & \text{otherwise} \end{cases}\,. \end{align}\]

Where:

  • $\eta_{t,\,i,\,j}$: Squeezing weight of the co-movement of assets $i$ and $j$ at observation $t$.
  • $x_{t,\,i}$: Return of asset $i$ at observation $t$.
  • $s_i$, $s_j$: Threshold scaling factors of the pair.
  • $d$: Significance threshold.
  • $n$: Compression weight.

The three cases are the source's tail, body and wing. Both returns are large in the tail, both are small in the body, and one of each in the wing. Because $0 \leq n \leq 1$ the weights obey $n^2 \leq n \leq 1$, so a co-movement of two similar magnitudes counts for more than one of two dissimilar magnitudes. That ordering is the source's own judgement, and it is what the single weight n buys in exchange for its lost degrees of freedom.

The body case is reachable only when $c < d$. A co-movement with both returns inside the noise threshold never reaches the template, so at $c = d$ the band that carries n is empty and only $1$ and $n^2$ occur.

The diagram shows a visual representation of the regions defined by BasicGerberIQ. In this case c = 1 and d = 3.

  • The dashed lines indicate the limits of the areas where movements are considered small.
  • Only the Gerber1 algorithm takes these regions into account as part of the neutral count.
  • The region where co-movements are considered insignificant in both axes (square around r0) are always ignored.
  • Single weight lines indicate zero delimiters.
  • The double weight lines indicate areas where movements are considered significant.
  • Co-movements within each region are weighed according to their labels.
            4 ┬─────┰───────────┬─────┬─────┬───────────┰─────┐     ┌────    │  1  ┃    n^2    ╎     │     ╎    n^21  d ─┤      3 ┾━━━━━╋━━━━━━━━━━━┿━━━━━┿━━━━━┿━━━━━━━━━━━╋━━━━━┥     └────    │     ┃           ╎     │     ╎           ┃     │            2 ┤ n^2 ┃     n     ╎     │     ╎     n     ┃ n^2              │     ┃           ╎     │     ╎           ┃     │     ┌────  1 ┼╌╌╌╌╌╂╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┴╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╂╌╌╌╌╌┤     │        │     ┃           ╎           ╎           ┃     │ 2c ─┤ r_j  0 ┼─────╂───────────┤    r0     ├───────────╂─────┤     │        │     ┃           ╎           ╎           ┃     │     └──── -1 ┼╌╌╌╌╌╂╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┬╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╂╌╌╌╌╌┤              │     ┃           ╎     │     ╎           ┃     │           -2 ┤ n^2 ┃     n     ╎     │     ╎     n     ┃ n^2     ┌────    │     ┃           ╎     │     ╎           ┃     │  d ─┤     -3 ┾━━━━━╋━━━━━━━━━━━┿━━━━━┿━━━━━┿━━━━━━━━━━━╋━━━━━┥     └────    │  1  ┃    n^2    ┊     │     ╎    n^21           -4 ┼─────╀─────┬─────┼─────┼─────┼─────┬─────╀─────┤             -4    -3    -2    -1     0     1     2     3     4                                     r_i                 │     │        │           │        │     │                 └──┬──┘        └─────┬─────┘        └──┬──┘                    d                2c                 d

Fields

  • d: Significance threshold. A return at or beyond d scaled units from zero is large. It is measured in the same units as the noise threshold c of GerberIQCovariance, and must be at least as large as it.
  • n: Compression weight, in [0, 1]. A co-movement of two large returns keeps its full weight of one, a co-movement of two small returns keeps n, and a co-movement of one of each keeps n^2.

Constructors

BasicGerberIQ(; d::Number = 2.0, n::Number = 0.5)

Keywords correspond to the struct's fields.

Validation

Examples

julia> BasicGerberIQ()BasicGerberIQ  d ┼ Float64: 2.0  n ┴ Float64: 0.5

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.PartialGerberIQType
struct PartialGerberIQ{__T_dcp, __T_dcn, __T_ddp, __T_ddn, __T_n1, __T_n2, __T_n3, __T_n4, __T_n5, __T_n6, __T_n7, __T_n8, __T_n9, __T_n10} <: GerberIQCovarianceAlgorithm

Gerber Information Quality template with asymmetric thresholds. Concordant and discordant co-movements take independently configurable significance thresholds.

This is the source's sixteen-channel template, the middle rung of the family. It gives the boundary vector its four independent components and allows ten distinct weights, where BasicGerberIQ collapses both to one scalar and FullGerberIQ opens the plane to thirty-six channels.

Mathematical definition

Every boundary is scaled onto its own axis before it is compared with a return.

\[\begin{align} \delta_{i} &= \delta\, s_i\,. \end{align}\]

Where:

  • $\delta$: One of the four boundaries dcp, dcn, ddp and ddn.
  • $\delta_{i}$: That boundary on the axis of asset $i$.
  • $s_i$: Threshold scaling factor of asset $i$.

The four boundaries cut the plane into sixteen channels, and n1 to n10 are the distinct weights those channels take once the plane's symmetry about the line $x_i = x_j$ is imposed. The template reads the signed return, not its magnitude, so it separates a pair by sign as well as by size: a concordant pair is measured against dcp when both returns are positive and against dcn when both are negative, and a discordant pair is measured against ddp and ddn. A co-movement in no named channel carries weight zero.

The diagram shows a visual representation of the regions defined by PartialGerberIQ. In this case c = 1, dcp = 2, ddn = 2, ddp = 3, and dcn = 3.

  • The dashed lines indicate the limits of the areas where movements are considered small.
  • Only the Gerber1 algorithm takes these regions into account as part of the neutral count.
  • The region where co-movements are considered insignificant in both axes (square around r0) are always ignored.
  • Single weight lines indicate zero delimiters.
  • The double weight lines indicate areas where movements are considered significant.
  • Co-movements within each region are weighed according to their labels.
                         ddn                     dcp                       ┌──┴──┐                 ┌──┴──┐                       │     │                 │     │            4 ┬───────────┰─────┬─────┬─────┬─────┰───────────┐     ┌────    │    n6     ┃ n9  ╎     │     ╎     ┃           │ddp ─┤      3 ┾━━━━━━━━━━━╋━━━━━┿━━━━━┥     ╎ n7  ┃    n4     │     └────    │           ┃     ╎     │     ╎     ┃           │ ────┐            2 ┤    n10    ┃ n3  ╎     ┝━━━━━┿━━━━━╋━━━━━━━━━━━┥     ├─ dcp              │           ┃     ╎     │     ╎ n1  ┃    n7     │ ────┘     ┌────  1 ┼╌╌╌╌╌╌╌╌╌╌╌╂╌╌╌╌╌┼╌╌╌╌╌┴╌╌╌╌╌┼╌╌╌╌╌╂╌╌╌╌╌╌╌╌╌╌╌┤     │        │           ┃     ╎           ╎     ┃           │ 2c ─┤ r_j  0 ┼─────┰─────┸─────┤    r0     ├─────┸─────┰─────┤     │        │     ┃           ╎           ╎           ┃     │     └──── -1 ┼╌╌╌╌╌╂╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┬╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╂╌╌╌╌╌┤              │     ┃           ╎     │     ╎    n3     ┃ n9  │ ────┐           -2 ┤ n8  ┃    n2     ╎     ┝━━━━━┿━━━━━━━━━━━╋━━━━━┥     ├─ ddn     ┌────    │     ┃           ╎     │     ╎           ┃     │ ────┘dcn ─┤     -3 ┾━━━━━╋━━━━━━━━━━━┿━━━━━┥     ╎    n10    ┃ n6  │     └────    │ n5  ┃    n8     ╎     │     ╎           ┃     │           -4 ┼─────╀─────┬─────┼─────┼─────┼─────┬─────╀─────┤             -4    -3    -2    -1     0     1     2     3     4                                     r_i                 │     │        │           │        │     │                 └──┬──┘        └─────┬─────┘        └──┬──┘                   dcn               2c                ddp

Fields

  • dcp: Positive concordant movement threshold parameter.
  • dcn: Negative concordant movement threshold parameter.
  • ddp: Discordant movement threshold parameter, positive in r_i, negative in r_j.
  • ddn: Discordant movement threshold parameter, negative in r_i, positive in r_j.
  • n1: Noise suppression parameter for small positive concordant movements.
  • n2: Noise suppression parameter for small negative concordant movements.
  • n3: Noise suppression parameter for small discordant movements.
  • n4: Noise suppression parameter for large positive concordant movements.
  • n5: Noise suppression parameter for large negative concordant movements.
  • n6: Noise suppression parameter for large discordant movements.
  • n7: Noise suppression parameter for positive concordant movements where one axis has a large movement and the other is small.
  • n8: Noise suppression parameter for negative concordant movements where one axis has a large movement and the other is small.
  • n9: Noise suppression parameter for discordant movements where one axis has a large movement and the other is small for the region between ddn and zero.
  • n10: Noise suppression parameter for discordant movements where one axis has a large movement and the other is small for the region between ddp and zero.

Constructors

PartialGerberIQ(; dcp::Number = 2.0, dcn::Number = dcp, ddp::Number = dcp,                  ddn::Number = dcp, n1::Number = 0.5, n2::Number = n1,                  n3::Number = sqrt(n1 * n2), n4::Number = 1.0, n5::Number = n4,                  n6::Number = sqrt(n4 * n5), n7::Number = sqrt(n1 * n4),                  n8::Number = sqrt(n2 * n5), n9::Number = sqrt(n4 * n2),                  n10::Number = sqrt(n1 * n5))

Keywords correspond to the struct's fields.

Only the four diagonal weights carry a free default. n1, n2, n4 and n5 name the four magnitude classes, and each of the other six defaults to the geometric mean of the two diagonal weights of the classes its channel joins. That is the bound clamp_gerber_iq_n enforces under Gerber2, so the default template meets it whatever the four are set to. The four boundaries are equal by default, so the case split that method makes over ddp against dcp does not bind on the defaults.

Validation

Examples

julia> PartialGerberIQ()PartialGerberIQ  dcp ┼ Float64: 2.0  dcn ┼ Float64: 2.0  ddp ┼ Float64: 2.0  ddn ┼ Float64: 2.0   n1 ┼ Float64: 0.5   n2 ┼ Float64: 0.5   n3 ┼ Float64: 0.5   n4 ┼ Float64: 1.0   n5 ┼ Float64: 1.0   n6 ┼ Float64: 1.0   n7 ┼ Float64: 0.7071067811865476   n8 ┼ Float64: 0.7071067811865476   n9 ┼ Float64: 0.7071067811865476  n10 ┴ Float64: 0.7071067811865476

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.FullGerberIQType
struct FullGerberIQ{__T_dp1, __T_dp2, __T_dn1, __T_dn2, __T_n1, __T_n2, __T_n3, __T_n4, __T_n5, __T_n6, __T_n7, __T_n8, __T_n9, __T_n10, __T_n11, __T_n12, __T_n13, __T_n14, __T_n15, __T_n16, __T_n17, __T_n18, __T_n19, __T_n20, __T_n21} <: GerberIQCovarianceAlgorithm

Gerber Information Quality template with fine-grained asymmetric thresholds. Classifies co-movements into two positive and two negative magnitude classes.

This is the source's full template, the most general form the family takes. Two boundaries on each axis cut every return into a small, a moderate and a large class, giving six bands per axis and thirty-six channels in the plane. Symmetry about the line $x_i = x_j$ folds those thirty-six channels onto twenty-one distinct weights, which is the count the source states and the count this type carries.

Mathematical definition

Every boundary is scaled onto its own axis before it is compared with a return.

\[\begin{align} \delta_{i} &= \delta\, s_i\,. \end{align}\]

Where:

  • $\delta$: One of the four boundaries dp1, dp2, dn1 and dn2.
  • $\delta_{i}$: That boundary on the axis of asset $i$.
  • $s_i$: Threshold scaling factor of asset $i$.

A return of asset $i$ is large positive at or beyond $dp1_i$, moderate positive in $[dp2_i, dp1_i)$, small positive in $(0, dp2_i)$, and the three negative classes mirror them about zero against $dn2_i$ and $dn1_i$. The channel of a co-movement is the pair of classes its two returns fall in, and its weight is the field named for that pair. A co-movement in no named channel carries weight zero, which happens only when a return is exactly zero.

The diagram shows a visual representation of the regions defined by FullGerberIQ. In this case c = 1, dp2 = 2, dn2 = 2, dp1 = 3, and dn1 = 3. In this version, the limits are allowed to cross over the zero line. Thus, the constructor ensures dp1 >= dp2 and dn1 >= dn2 by swapping values if necessary to ensure consistency.

  • The dashed lines indicate the limits of the areas where movements are considered small.
  • Only the Gerber1 algorithm takes these regions into account as part of the neutral count.
  • The region where co-movements are considered insignificant in both axes (square around r0) are always ignored.
  • Single weight lines indicate zero delimiters.
  • The double weight lines indicate areas where movements are considered significant.
  • Co-movements within each region are weighed according to their labels.
                         dn2                     dp2                       ┌──┴──┐                 ┌──┴──┐                       │     │                 │     │            4 ┬─────┰─────┰─────┬─────┬─────┬─────┰─────┰─────┐     ┌────    │ n13 ┃ n19 ┃ n18 ╎     │     ╎ n15 ┃ n14 ┃ n11 │dp1 ─┤      3 ┾━━━━━╋━━━━━╋━━━━━┿━━━━━┿━━━━━┿━━━━━╋━━━━━╋━━━━━┥     └────    │ n20 ┃ n6  ┃ n9  ╎     │     ╎ n7  ┃ n4  ┃ n14 │ ────┐            2 ┾━━━━━╋━━━━━╋━━━━━┿━━━━━┿━━━━━┿━━━━━╋━━━━━╋━━━━━┥     ├─ dp2              │ n21 ┃ n10 ┃ n3  ╎     │     ╎ n1  ┃ n7  ┃ n15 │ ────┘     ┌────  1 ┼╌╌╌╌╌╂╌╌╌╌╌╂╌╌╌╌╌┼╌╌╌╌╌┴╌╌╌╌╌┼╌╌╌╌╌╂╌╌╌╌╌╂╌╌╌╌╌┤     │        │     ┃     ┃     ╎           ╎     ┃     ┃     │ 2c ─┤ r_j  0 ┼─────╂─────╂─────┤    r0     ├─────╂─────╂─────┤     │        │     ┃     ┃     ╎           ╎     ┃     ┃     │     └──── -1 ┼╌╌╌╌╌╂╌╌╌╌╌╂╌╌╌╌╌┼╌╌╌╌╌┬╌╌╌╌╌┼╌╌╌╌╌╂╌╌╌╌╌╂╌╌╌╌╌┤              │ n16 ┃ n8  ┃ n2  ╎     │     ╎ n3  ┃ n9  ┃ n18 │ ────┐           -2 ┾━━━━━╋━━━━━╋━━━━━┿━━━━━┿━━━━━┿━━━━━╋━━━━━╋━━━━━┥     ├─ dn2     ┌────    │ n17 ┃ n5  ┃ n8  ╎     │     ╎ n10 ┃ n6  ┃ n19 │ ────┘dn1 ─┤     -3 ┾━━━━━╋━━━━━╋━━━━━┿━━━━━┿━━━━━┿━━━━━╋━━━━━╋━━━━━┥     └────    │ n12 ┃ n17 ┃ n16 ╎     │     ╎ n21 ┃ n20 ┃ n13 │           -4 ┼─────╀─────╀─────┼─────┼─────┼─────╀─────╀─────┤             -4    -3    -2    -1     0     1     2     3     4                                     r_i                 │     │        │           │        │     │                 └──┬──┘        └─────┬─────┘        └──┬──┘                   dn1               2c                dp1

Fields

  • dp1: Outer positive boundary. A positive return at or beyond it is large. The constructor swaps dp1 and dp2 when needed, so dp1 >= dp2 always holds.
  • dp2: Inner positive boundary. A positive return between it and dp1 is moderate, and one below it is small.
  • dn1: Outer negative boundary. A negative return at or beyond -dn1 is large.
  • dn2: Inner negative boundary. A negative return between -dn1 and -dn2 is moderate, and one above -dn2 is small.
  • n1: Weight of a concordant co-movement of two small positive returns.
  • n2: Weight of a concordant co-movement of two small negative returns.
  • n3: Weight of a discordant co-movement of a small positive return with a small negative return.
  • n4: Weight of a concordant co-movement of two moderate positive returns.
  • n5: Weight of a concordant co-movement of two moderate negative returns.
  • n6: Weight of a discordant co-movement of a moderate positive return with a moderate negative return.
  • n7: Weight of a concordant positive co-movement of a small return with a moderate one.
  • n8: Weight of a concordant negative co-movement of a small return with a moderate one.
  • n9: Weight of a discordant co-movement whose positive return is moderate and whose negative return is small.
  • n10: Weight of a discordant co-movement whose positive return is small and whose negative return is moderate.
  • n11: Weight of a concordant co-movement of two large positive returns.
  • n12: Weight of a concordant co-movement of two large negative returns.
  • n13: Weight of a discordant co-movement of a large positive return with a large negative return.
  • n14: Weight of a concordant positive co-movement of a moderate return with a large one.
  • n15: Weight of a concordant positive co-movement of a small return with a large one.
  • n16: Weight of a concordant negative co-movement of a small return with a large one.
  • n17: Weight of a concordant negative co-movement of a moderate return with a large one.
  • n18: Weight of a discordant co-movement whose positive return is large and whose negative return is small.
  • n19: Weight of a discordant co-movement whose positive return is large and whose negative return is moderate.
  • n20: Weight of a discordant co-movement whose positive return is moderate and whose negative return is large.
  • n21: Weight of a discordant co-movement whose positive return is small and whose negative return is large.

Constructors

FullGerberIQ(; dp1::Number = 2.0, dp2::Number = dp1, dn1::Number = dp1,               dn2::Number = dp1, n1::Number = 0.5, n2::Number = n1,               n3::Number = sqrt(n1 * n2), n4::Number = 0.75, n5::Number = n4,               n6::Number = sqrt(n4 * n5), n7::Number = sqrt(n1 * n4),               n8::Number = sqrt(n2 * n5), n9::Number = sqrt(n4 * n2),               n10::Number = sqrt(n1 * n5), n11::Number = 1.0, n12::Number = n11,               n13::Number = sqrt(n11 * n12), n14::Number = sqrt(n4 * n11),               n15::Number = sqrt(n1 * n11), n16::Number = sqrt(n2 * n12),               n17::Number = sqrt(n5 * n12), n18::Number = sqrt(n2 * n11),               n19::Number = sqrt(n5 * n11), n20::Number = sqrt(n4 * n12),               n21::Number = sqrt(n1 * n12))

Keywords correspond to the struct's fields.

Only the six diagonal weights carry a free default. n1, n2, n4, n5, n11 and n12 name the six magnitude classes, and each of the other fifteen defaults to the geometric mean of the two diagonal weights of the classes its channel joins. That is the bound clamp_gerber_iq_n enforces under Gerber2, so the default template meets it whatever the six are set to, and the clamp never moves a default. #494 is the defect that made this the rule: four of the earlier defaults read two mixed weights instead, which let a two-asset sample return a correlation above 1.

Validation

The boundary swap is not a raise. dp1 and dp2 are ordered by extrema and so are dn1 and dn2, so a caller who names them the other way round gets a working template rather than an error.

Examples

julia> FullGerberIQ()FullGerberIQ  dp1 ┼ Float64: 2.0  dp2 ┼ Float64: 2.0  dn1 ┼ Float64: 2.0  dn2 ┼ Float64: 2.0   n1 ┼ Float64: 0.5   n2 ┼ Float64: 0.5   n3 ┼ Float64: 0.5   n4 ┼ Float64: 0.75   n5 ┼ Float64: 0.75   n6 ┼ Float64: 0.75   n7 ┼ Float64: 0.6123724356957945   n8 ┼ Float64: 0.6123724356957945   n9 ┼ Float64: 0.6123724356957945  n10 ┼ Float64: 0.6123724356957945  n11 ┼ Float64: 1.0  n12 ┼ Float64: 1.0  n13 ┼ Float64: 1.0  n14 ┼ Float64: 0.8660254037844386  n15 ┼ Float64: 0.7071067811865476  n16 ┼ Float64: 0.7071067811865476  n17 ┼ Float64: 0.8660254037844386  n18 ┼ Float64: 0.7071067811865476  n19 ┼ Float64: 0.8660254037844386  n20 ┼ Float64: 0.8660254037844386  n21 ┴ Float64: 0.7071067811865476

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
PortfolioOptimisers.GerberIQCovarianceType
struct GerberIQCovariance{__T_ve, __T_me, __T_pdm, __T_c, __T_decay, __T_sc, __T_kind, __T_alg, __T_ex} <: BaseGerberIQCovariance

Configures and applies Gerber Information Quality covariance estimators.

GerberIQCovariance encapsulates all components required for Gerber Information Quality based covariance or correlation estimation.

Four knobs carry the source's own parameters. c is the noise threshold, kind is the squeezing template that supplies the weight of a co-movement, sc fixes the units the thresholds are measured in, and decay discounts a co-movement by its age. alg is the one knob the source does not carry: its canonical statistic is the Gerber1 branch alone, and this estimator also offers Gerber0 and Gerber2 from the classic Gerber family. gerber_IQ states the three branches and the reduction that ties them to that family.

The source's lookback duration $\tau$ has no field. The estimator always reads every row of X and lets decay discount the oldest ones, which is the $\tau = T - 1$ case of the source.

Fields

  • ve: Variance estimator.
  • me: Expected returns estimator.
  • pdm: Positive definite matrix estimator.
  • c: Noise threshold. A return within c scaled units of zero is noise, and so is a return of exactly zero at any c. A co-movement whose two returns are both noise is dropped. It must be no larger than every boundary of kind.
  • sc: Threshold scaling factor estimator for co-movement thresholds GerberIQScaler.
  • alg: Gerber covariance algorithm.
  • ex: Parallel execution strategy..

Constructors

GerberIQCovariance(; ve::StatsBase.CovarianceEstimator = SimpleVariance(),                     me::AbstractExpectedReturnsEstimator = SimpleExpectedReturns(),                     pdm::Option{<:AbstractPosdefEstimator} = Posdef(), c::Number = 0.5,                     decay::GerberIQDecayEstimator = ExpGerberIQDecay(),                     sc::Option{<:GerberIQScaler} = nothing,                     kind::GerberIQCovarianceAlgorithm = BasicGerberIQ(),                     alg::GerberCovarianceAlgorithm = Gerber1(),                     ex::FLoops.Transducers.Executor = FLoops.Transducers.ThreadedEx())

Keywords correspond to the struct's fields.

Validation

  • c >= 0: c must be non-negative.
  • c <= kind.d (or equivalent for the chosen kind): via gerber_iq_assert_c_d.
Warning

The constructor may replace kind. It passes the template through clamp_gerber_iq_n, which lowers some weights under Gerber2, so the stored template is not always the one that was passed in. Read ce.kind rather than the argument when the exact weights matter.

Propagated parameters

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

  • ve: Recursively updated via factory.
  • me: Recursively updated via factory.
  • decay: Recursively updated via factory.
  • alg: Recursively updated 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:

Examples

julia> GerberIQCovariance()GerberIQCovariance     ve ┼ SimpleVariance        │          me ┼ SimpleExpectedReturns        │             │   w ┴ nothing        │           w ┼ nothing        │   corrected ┴ Bool: true     me ┼ SimpleExpectedReturns        │   w ┴ nothing    pdm ┼ Posdef        │      alg ┼ UnionAll: NearestCorrelationMatrix.Newton        │   kwargs ┴ @NamedTuple{}: NamedTuple()      c ┼ Float64: 0.5  decay ┼ ExpGerberIQDecay        │   e ┼ nothing        │   y ┴ nothing     sc ┼ nothing   kind ┼ BasicGerberIQ        │   d ┼ Float64: 2.0        │   n ┴ Float64: 0.5    alg ┼ Gerber1()     ex ┴ Transducers.ThreadedEx{@NamedTuple{}}: Transducers.ThreadedEx()

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
Statistics.corMethod
Statistics.cor(
    ce::GerberIQCovariance,
    X::MatNum;
    dims::Int = 1,
    kwargs...
) -> MatNum

Compute the Gerber IQ correlation matrix.

This method computes the Gerber IQ correlation matrix for the input data matrix X. The mean and standard deviation vectors are computed using the estimator's expected returns and variance estimators. The Gerber IQ correlation is then computed via gerber_IQ.

The standard deviations serve two purposes at once. They scale the thresholds through gerber_iq_scaling, and in cov they rescale the correlation into a covariance.

Algorithm

  1. Orient X to observations × assets with dims_oriented.
  2. Compute the per-asset standard deviations with the estimator's ve.
  3. Raise every standard deviation to at least eps(eltype(sd)), so a constant asset cannot divide by zero.
  4. Centre the returns with the estimator's me through demean_returns.
  5. Return the matrix that gerber_IQ builds from the centred returns and those standard deviations.

Arguments

  • ce: Gerber IQ covariance estimator.
  • X: Data matrix (observations × assets).
  • dims: Dimension along which to perform the computation.
  • kwargs...: Additional keyword arguments passed to the mean and standard deviation estimators.

Validation

  • dims is either 1 or 2.

Returns

  • rho::MatNum: The Gerber IQ correlation matrix. Its diagonal is one for every asset.
Note

An asset that never leaves its own noise zone gets a zero row, because no observation votes for any pair it belongs to. Its diagonal entry is one, which comovement_unit_diagonal! writes, so the matrix stays a formal correlation matrix and the asset reads as uncorrelated with every other one. That is what the sample says about it. Lower c when a short window meets a quiet asset, and the asset votes again. #495 is the defect that led to this rule.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source
Statistics.covMethod
Statistics.cov(
    ce::GerberIQCovariance,
    X::MatNum;
    dims::Int = 1,
    kwargs...
) -> MatNum

Compute the Gerber IQ covariance matrix.

This method computes the Gerber IQ covariance matrix for the input data matrix X. The mean and standard deviation vectors are computed using the estimator's expected returns and variance estimators. The Gerber IQ correlation is then computed via gerber_IQ.

Mathematical definition

\[\begin{align} \hat{\mathbf{\Sigma}} &= \boldsymbol{\rho} \odot \left(\boldsymbol{\sigma} \boldsymbol{\sigma}^{\intercal}\right)\,. \end{align}\]

Where:

  • $\hat{\mathbf{\Sigma}}$: Estimated covariance matrix.
  • $\boldsymbol{\rho}$: Gerber IQ correlation matrix.
  • $\boldsymbol{\sigma}$: Vector of asset standard deviations.
  • $\odot$: Element-wise multiplication.

The covariance is the correlation of cor rescaled by the same standard deviations that scaled its thresholds, so its diagonal is exactly $\boldsymbol{\sigma}^2$.

Algorithm

  1. Run the five steps of cor(ce::GerberIQCovariance, X::MatNum; dims::Int = 1, kwargs...), giving the correlation matrix and the standard deviations.
  2. Rescale that matrix in place with StatsBase.cor2cov! and those standard deviations, and return it.

Arguments

  • ce: Gerber IQ covariance estimator.
  • X: Data matrix (observations × assets).
  • dims: Dimension along which to perform the computation.
  • kwargs...: Additional keyword arguments passed to the mean and standard deviation estimators.

Validation

  • dims is either 1 or 2.

Returns

  • sigma::MatNum: The Gerber IQ covariance matrix. Its diagonal is the variance of each asset, because cor2cov! scales a unit correlation diagonal by $\boldsymbol{\sigma}^2$.

Related

References

  • [15] S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).
source

References

[15]
S. Gerber, W. Smyth, H. Markowitz, Y. Miao, P. Ernst and P. Sargen. Squeezing financial noise: A novel approach to covariance matrix estimation. Available at SSRN 4986939 (2025).