Mean test

Tests of a zero mean

PortfolioOptimisers.AbstractMeanTestEstimator — Type
abstract type AbstractMeanTestEstimator <: AbstractEstimator

Abstract supertype for the tests of the null hypothesis that a serially dependent series has a mean of zero.

A Mean Test reads one series, such as the information coefficient series of a factor or of a Return Forecast. It answers a t-statistic, a two-sided p-value and a confidence interval of the mean. The consecutive entries of such a series can be correlated, so a test that treats them as independent overstates the evidence. Each member of the family states how it reads that dependence.

Interfaces

In order to implement a new Mean Test that works seamlessly with the library, subtype AbstractMeanTestEstimator and implement the following method:

Test method

  • mean_test(mt::AbstractMeanTestEstimator, c::VecNum, window::Real, rng) -> NamedTuple: Tests the mean of c against zero.

Arguments

  • mt: Concrete subtype instance.
  • c: The series. A NaN entry is an observation with no value.
  • window: Number of entries that the data of one entry spans, from the grid of the series, horizon / step for a forward window. A window above one means that consecutive entries share data. A test can ignore it.
  • rng: The random number generator that mean_test_rng resolves, or nothing.

Returns

  • res::NamedTuple: (; t_stat, p_value, mean_ci_lower, mean_ci_upper).

Generator method

  • mean_test_rng(mt::AbstractMeanTestEstimator) -> Option{<:Random.AbstractRNG}: The generator that the test draws from. The default method answers nothing. A test that draws random numbers implements it, and resolves its generator with resolve_rng.

Related

source
PortfolioOptimisers.OverlapMeanTest — Type
struct OverlapMeanTest{__T_law, __T_q, __T_min_obs, __T_min_periods} <: AbstractMeanTestEstimator

Tests the mean of a series against zero over the untapered long-run variance at the order that the overlap of its windows sets.

The test reads the overlap off the window that the caller derives from the grid, such as forecast_ic_window. Its order is $L = \lceil w \rceil - 1$, the number of entries on each side of a given entry that share data with it. It reads no dependence past the overlap. A series that is persistent past the overlap gives a t-statistic that is too large, and the untapered sum can be negative on a short series. WildBootstrapMeanTest is the default because of this.

The law sets the divisor and the degrees of freedom

The sum $Q$ of the centred products reads the deviations from the sample mean, not from the true mean, so its expectation is not $n$ times the long-run variance. Under the null hypothesis each entry is a sum of window independent periods, the score of a no-skill forecast over overlapping windows. The field law reads the divisor $n_{d}$ of $Q$ and the degrees of freedom $\nu$ of the Student law off that null law. The default NullMomentLaw makes the variance of the mean unbiased, and matches the variance of $Q$. It rejects a no-skill moving average of order four in 60 entries 4.9% of the time at the 5% level. BandCountLaw, the rule $n_{d} = \nu = n - 2L - 1$, rejects it 7.8% of the time, and a divisor of $n$ with the normal law about 10.6%. At $L = 0$ both laws give $n - 1$, and the test is the classical t-test, whose law under independent Gaussian entries is the Student law with $n - 1$ degrees of freedom.

Mathematical definition

\[\begin{align} \gamma_{j} &= \frac{1}{n_{d}} \sum_{t,\, t + j \in \mathcal{T}} \left( c_{t} - \bar{c} \right) \left( c_{t + j} - \bar{c} \right)\,, \\ \sigma^{2} &= \gamma_{0} + 2 \sum_{j = 1}^{L} \gamma_{j}\,, \\ t &= \frac{\bar{c}}{\sigma} \sqrt{n}\,, \\ p &= 2 \left( 1 - F_{\nu}(|t|) \right)\,, \\ \bar{c} &\pm F_{\nu}^{-1}(1 - q / 2) \frac{\sigma}{\sqrt{n}}\,. \end{align}\]

Where:

  • $c_{t}$: Entry $t$ of the series.
  • $\mathcal{T}$: The entries at which it is finite.
  • $n$: The number of entries in $\mathcal{T}$.
  • $\bar{c}$: The mean over $\mathcal{T}$.
  • $\gamma_{j}$: The autocovariance at lag $j$.
  • $L$: The order, $\lceil w \rceil - 1$, with $w$ the window.
  • $n_{d}$: The divisor that law sets, overlap_student_law.
  • $\sigma$: The long-run standard deviation, $\sqrt{n}$ times the standard error of the mean.
  • $F_{\nu}$: The distribution function of the Student law with the $\nu$ degrees of freedom that law sets.
  • $t$: The t-statistic.
  • $p$: The two-sided p-value.
  • $q$: q, so the last line is the confidence interval of the mean at the level $1 - q$.

A long-run variance that is not positive, or a divisor or degrees of freedom that are not positive, give a NaN t-statistic, p-value and interval. BandCountLaw has no positive count when $n \leq 2L + 1$, and NullMomentLaw none when the span of the series is at most $L + 1$ entries. At a window of at most one the order is zero, and the t-statistic is $\mathrm{IR} \sqrt{n}$. The rules of min_obs and min_periods are those of WildBootstrapMeanTest.

Fields

  • law: Law that sets the divisor of the long-run variance and the degrees of freedom of the Student law.
  • q: Significance level of the test, and one less the confidence level of the interval of the mean, in (0, 1).
  • min_obs: Least number of finite entries a series needs before the test answers, or nothing for no rule.
  • min_periods: Least number of windows that the span of a series needs before the test answers, the span over window, or nothing for no rule. For a forward window it is the number of holding periods that the history covers.

Constructors

OverlapMeanTest(;    law::AbstractOverlapStudentLaw = NullMomentLaw(),    q::Real = 0.05,    min_obs::Option{<:Integer} = nothing,    min_periods::Option{<:Real} = nothing,) -> OverlapMeanTest

Keywords correspond to the struct's fields.

The law NullMomentLaw is the default because it holds the level of the test. Its cost is linear in the length of the series and in $L$. A test under it takes 2 to 15 times a test under BandCountLaw: 0.35 ms against 0.03 ms for 1,000 entries at a window of 20, and 1.8 ms against 0.12 ms for 5,000. The default WildBootstrapMeanTest takes 16 ms and 97 ms there. BandCountLaw is the rule of the library before 2026-10-16.

Validation

  • 0 < q < 1. Raises a DomainError.
  • min_obs >= 2 and min_periods > 0, when given. Raise a DomainError.

Examples

julia> PortfolioOptimisers.mean_test(OverlapMeanTest(), [0.1, -0.2, 0.3, 0.2, NaN, 0.1], 1,                                     nothing)(t_stat = 1.1952286093343938, p_value = 0.29801481173121036, mean_ci_lower = -0.132294063538519, mean_ci_upper = 0.332294063538519)

Related

References

  • [12] F. E. Satterthwaite. An approximate distribution of estimates of variance components. Biometrics Bulletin 2, 110–114 (1946).
source
PortfolioOptimisers.WildBootstrapMeanTest — Type
struct WildBootstrapMeanTest{__T_kernel, __T_alg, __T_b, __T_span, __T_ddof, __T_n_sim, __T_q, __T_min_obs, __T_min_periods, __T_rng, __T_seed} <: AbstractMeanTestEstimator

Tests the mean of a series against zero with a fixed-bandwidth long-run variance and a Gaussian wild bootstrap of its null law.

The bandwidth is the fraction b of the span of the series, so the long-run variance reads the dependence at every lag up to it, past the overlap of the windows as well. The null law of such a t-statistic is not the normal law, and a change of the volatility over time moves it. The test therefore reads the p-value off n_sim draws of the statistic under the null hypothesis, as the source states. Each draw multiplies the centred series by independent standard normal draws, and computes the t-statistic of the product with the same kernel and the same bandwidth. The field alg sets how the test draws that law, an AbstractBootstrapDraws. Every algorithm draws the same law at a different cost.

The t-statistic is not on the scale of the normal law. Read the p-value or the interval to judge the evidence. The p-value is $(1 + K) / (M + 1)$, so it is never zero, and its resolution is $1 / (M + 1)$. The interval is the symmetric percentile-t interval of the bootstrap. It excludes zero exactly when the p-value is at most q.

Mathematical definition

\[\begin{align} Q &= \sum_{i, j \in \mathcal{T}} k\left(\frac{|i - j|}{B}\right) \left( c_{i} - \bar{c} \right) \left( c_{j} - \bar{c} \right)\,, \\ s &= \sqrt{\frac{Q}{n (n - \delta)}}\,, \quad t = \frac{\bar{c}}{s}\,, \\ c_{t}^{*} &= r_{t} \left( c_{t} - \bar{c} \right)\,, \quad r_{t} \sim \mathcal{N}(0, 1)\,, \\ p &= \frac{1 + \#\left\{ m : |t_{m}^{*}| \geq |t| \right\}}{M + 1}\,, \\ \bar{c} &\pm |t^{*}|_{(k)}\, s\,, \quad k = M + 1 - \max\left\{ c : \frac{c}{M + 1} \leq q \right\}\,. \end{align}\]

Where:

  • $c_{t}$: Entry $t$ of the series.
  • $\mathcal{T}$: The entries at which it is finite.
  • $n$: The number of entries in $\mathcal{T}$.
  • $\bar{c}$: The mean over $\mathcal{T}$.
  • $k$: The kernel, kernel, in the first line.
  • $B$: The bandwidth, $b T$, where $T$ is the span that span sets.
  • $Q$: The weighted sum of long_run_quadratic_form.
  • $s$: The long-run standard error of the mean. Every autocovariance divides by $n - \delta$, so the long-run variance is $Q / (n - \delta)$.
  • $\delta$: ddof. The default 0 is the divisor $n$ of the source. The divisor scales the observed statistic and every draw by one factor, so it moves the t-statistic alone, and no p-value and no interval. A series with $n \leq \delta$ has no statistic.
  • $t$: The t-statistic.
  • $r_{t}$: The multiplier of entry $t$.
  • $t_{m}^{*}$: The t-statistic of draw $m$, with $c^{*}$ in place of $c$.
  • $M$: n_sim.
  • $p$: The two-sided p-value.
  • $|t^{*}|_{(k)}$: The $k$-th smallest of the $|t_{m}^{*}|$, with $k$ the order in the last line. bootstrap_exceedance_cap gives the count $c$.
  • $q$: q, so the last line is the confidence interval of the mean at the level $1 - q$.

A t-statistic of a draw that is not finite counts as one at least as large as $t$. A series with fewer than two finite entries, or with a long-run variance that is not positive, gives a NaN t-statistic, p-value and interval. So does a series with fewer than min_obs finite entries, and a series whose span holds fewer than min_periods windows, the span over window. That is the only use of window.

Fields

  • kernel: Kernel that weights the autocovariances.
  • alg: Algorithm that draws the null law of the statistic. Every algorithm draws the same law, at a different cost.
  • b: Bandwidth as a fraction of the span of the series, in (0, 1].
  • span: Rule that sets the span of the series, which the bandwidth and min_periods read.
  • ddof: Number that the divisor of the long-run variance subtracts from the count of finite entries, 0 for the divisor $n$ of the source.
  • n_sim: Number of simulation samples.
  • q: Significance level of the test, and one less the confidence level of the interval of the mean, in (0, 1).
  • min_obs: Least number of finite entries a series needs before the test answers, or nothing for no rule.
  • min_periods: Least number of windows that the span of a series needs before the test answers, the span over window, or nothing for no rule. For a forward window it is the number of holding periods that the history covers.
  • rng: Random number generator.
  • seed: Optional seed. If set, the draws come from a copy of rng seeded with it, so rng does not advance and every call draws the same values. If nothing, the draws come from rng itself.

Constructors

WildBootstrapMeanTest(;    kernel::AbstractLongRunKernel = BartlettKernel(),    alg::AbstractBootstrapDraws = default_bootstrap_draws(kernel),    b::Real = 0.4,    span::AbstractMeanTestSpan = FiniteEntrySpan(),    ddof::Integer = 0,    n_sim::Integer = 1_999,    q::Real = 0.05,    min_obs::Option{<:Integer} = nothing,    min_periods::Option{<:Real} = nothing,    rng::Random.AbstractRNG = Random.default_rng(),    seed::Option{<:Integer} = nothing,) -> WildBootstrapMeanTest

Keywords correspond to the struct's fields.

The defaults of kernel, b and n_sim are those of the source. Its simulations find that a bandwidth of a mid size, such as b = 0.4, holds the size of the test, and that the Bartlett kernel has more power than the quadratic spectral kernel. The source states an option that the test does not take: it can multiply the residuals of an AR(1) fit in place of the deviations from the mean, to reduce the effect of short-run dynamics. The level q = 0.05 is the one of the library. The source uses 0.1 in its simulations and 0.01 in its application. A smaller b gives more power and a larger size distortion under strong dependence. The default alg is QuadratureSumDraws for the QuadraticSpectralKernel and ObservationDraws for every other kernel, from default_bootstrap_draws.

Validation

  • alg reads kernel, by assert_bootstrap_draws. Raises a ConflictingArgumentError.
  • 0 < b <= 1. Raises a DomainError.
  • ddof >= 0. Raises a DomainError.
  • n_sim > 0, and n_sim at most the max_n_sim of RESOURCE_LIMITS. Raises a DomainError.
  • 0 < q < 1, and 1 / (n_sim + 1) <= q, so the interval has an order statistic. Raises a DomainError.
  • min_obs >= 2 and min_periods > 0, when given. Raise a DomainError.

Examples

julia> mt = WildBootstrapMeanTest(; seed = 42);julia> res = PortfolioOptimisers.mean_test(mt, [0.1, -0.2, 0.3, 0.2, NaN, 0.1], 1,                                           PortfolioOptimisers.mean_test_rng(mt));julia> res.t_stat1.7320508075688772julia> 0 < res.p_value <= 1truejulia> res.mean_ci_lower < 0.1 < res.mean_ci_uppertrue

Related

References

  • [13] M. Demetrescu, C. Hanck and R. Kruse-Becher. Robust fixed-b inference in the presence of time-varying volatility. Econometrics and Statistics 37, 154–173 (2026). Section 3.1 and Section 4.
source
PortfolioOptimisers.mean_test — Function
mean_test(mt::OverlapMeanTest, c::VecNum, window::Real, rng) -> NamedTuple
mean_test(mt::WildBootstrapMeanTest, c::VecNum, window::Real,
          rng::Random.AbstractRNG) -> NamedTuple

Return the t-statistic, the two-sided p-value and the confidence interval of the mean of a series, under the null hypothesis that the mean is zero.

The test reads the entries of c at which it is finite. A NaN entry is in no pair, and the lag between two entries is their distance in the series, not in its finite subsequence. The docstring of each test states its rule.

Arguments

  • mt: A Mean Test.
  • c: The series.
  • window: Number of entries that the data of one entry spans, horizon / step for a forward window, from forecast_ic_window. OverlapMeanTest reads the order of its long-run variance off it. Both tests read it in the rule of min_periods.
  • rng: The generator of mean_test_rng. OverlapMeanTest does not read it.

Validation

  • window > 0. Raises a DomainError.

Returns

  • res::NamedTuple: (; t_stat, p_value, mean_ci_lower, mean_ci_upper).

Related

source
PortfolioOptimisers.mean_test_rng — Function
mean_test_rng(mt::AbstractMeanTestEstimator) -> Nothing
mean_test_rng(mt::WildBootstrapMeanTest) -> Random.AbstractRNG

Return the random number generator that a Mean Test draws from.

A summary of many series resolves the generator once and passes it to each call of mean_test, so a seeded test of many series is reproducible, and the series take different draws. A test that draws no random number answers nothing.

Arguments

  • mt: A Mean Test.

Returns

  • rng::Option{<:Random.AbstractRNG}: The generator that resolve_rng resolves from the rng and the seed of the test, or nothing.

Related

source

Laws of the overlap test

PortfolioOptimisers.AbstractOverlapStudentLaw — Type
abstract type AbstractOverlapStudentLaw <: AbstractAlgorithm

Abstract supertype for the rules that set the divisor of the long-run variance of an OverlapMeanTest, and the degrees of freedom of the Student law that its p-value and its interval read.

The untapered sum $Q$ of the centred products reads the deviations from the sample mean, so its expectation is not $n$ times the long-run variance. The law sets the divisor $n_{d}$ of $Q$ and the degrees of freedom $\nu$. At a window of at most one every law gives $n_{d} = \nu = n - 1$, the classical t-test.

Interfaces

In order to implement a new law that works seamlessly with the library, subtype AbstractOverlapStudentLaw and implement the following method:

Law method

  • overlap_student_law(law::AbstractOverlapStudentLaw, f::AbstractVector{Bool}, window::Real, n::Integer, T::Type) -> Tuple: The divisor and the degrees of freedom.

Arguments

  • law: Concrete subtype instance.
  • f: Whether each entry of the span of the series, from its first finite entry to its last, is a finite observation.
  • window: Number of entries that the data of one entry spans.
  • n: The number of finite entries, count(f).
  • T: The type of the statistic, which a law that computes its values reads them in.

Returns

  • nd::Real: The divisor of $Q$. A divisor that is not positive gives a NaN test.
  • nu::Real: The degrees of freedom. A value that is not positive gives a NaN test.

Related

source
PortfolioOptimisers.BandCountLaw — Type
struct BandCountLaw <: AbstractOverlapStudentLaw

Divides the sum of the centred products by the number of entries less the width of the band, and reads the Student law with as many degrees of freedom.

The rule is $n_{d} = \nu = n - 2L - 1$. The divisor is almost unbiased for $n$ times the variance of the mean under the null hypothesis. The degrees of freedom are not: the untapered sum varies much more than a sum of $n - 2L - 1$ independent squares, so the test rejects too often at $L > 0$. At the 5% level it rejects a no-skill moving average of order four in 60 entries 7.8% of the time, and one of order nineteen in 120 entries 12.4% of the time. NullMomentLaw holds the level. This law costs nothing past the sum itself.

Constructors

BandCountLaw() -> BandCountLaw

Examples

julia> PortfolioOptimisers.overlap_student_law(BandCountLaw(), trues(60), 5, 60, Float64)(51, 51)

Related

source
PortfolioOptimisers.NullMomentLaw — Type
struct NullMomentLaw <: AbstractOverlapStudentLaw

Reads the divisor and the degrees of freedom off the first two moments of the sum of the centred products under the null hypothesis of the test.

Under the null hypothesis each entry is the sum of window independent periods, sampled one period apart, so the correlation of two entries $j$ entries apart is $\max(1 - j / w, 0)$. That is the correlation of a no-skill score of overlapping windows, and of an equal-weight moving average of order $L$ when $w = L + 1$. The divisor makes the variance of the mean unbiased under that law, at every length, with every gap of the series. The degrees of freedom match the variance of $Q$ to the variance of a scaled chi-squared law, the rule of the source. Both are exact for a Gaussian series, and their only approximation is the Student law itself.

At the 5% level the test rejects a no-skill moving average of order four in 60 entries 4.9% of the time, and one of order nineteen in 120 entries 4.5% of the time. With gaps it holds the level the same way. The degrees of freedom are much smaller than $n - 2L - 1$, because the untapered sum varies much more than a sum of independent squares. The computation reads each entry of the band once through two prefix sums of the mask of the finite entries, so its cost is linear in the length of the series and in $L$, the order of the cost of $Q$.

Mathematical definition

\[\begin{align} \left( \Sigma_{0} \right)_{i j} &= \max\left( 1 - \frac{|t_{i} - t_{j}|}{w},\, 0 \right)\,, \quad A = M W M\,, \quad M = I - \frac{1}{n} \mathbf{1} \mathbf{1}^{\intercal}\,, \\ n_{d} &= \frac{n \operatorname{tr}\left( A \Sigma_{0} \right)}{\mathbf{1}^{\intercal} \Sigma_{0} \mathbf{1}}\,, \\ \nu &= \frac{\operatorname{tr}\left( A \Sigma_{0} \right)^{2}}{\operatorname{tr}\left( \left( A \Sigma_{0} \right)^{2} \right)}\,. \end{align}\]

Where:

  • $t_{i}$: The position in the series of finite entry $i$.
  • $w$: window.
  • $\Sigma_{0}$: The correlation of the finite entries under the null hypothesis.
  • $W$: The weights of the untapered sum, one when $|t_{i} - t_{j}| \leq L$ and zero after it.
  • $M$: The centring matrix of the $n$ finite entries.
  • $n_{d}$: The divisor. $\mathbb{E}[Q] = \operatorname{tr}(A \Sigma_{0})$ and $n^{2} \operatorname{Var}(\bar{c}) = \mathbf{1}^{\intercal} \Sigma_{0} \mathbf{1}$, so $Q / (n\, n_{d})$ is unbiased for the variance of the mean.
  • $\nu$: The degrees of freedom, $2 \mathbb{E}[Q]^{2} / \operatorname{Var}(Q)$ for a Gaussian series.

A span of at most $L + 1$ entries puts every pair in the band, so $Q$ is zero and the law gives $n_{d} = \nu = 0$.

Constructors

NullMomentLaw() -> NullMomentLaw

Examples

julia> nd, nu = PortfolioOptimisers.overlap_student_law(NullMomentLaw(), trues(60), 5, 60, Float64);julia> round(nd; digits = 3), round(nu; digits = 3)(51.174, 8.111)

Related

References

  • [12] F. E. Satterthwaite. An approximate distribution of estimates of variance components. Biometrics Bulletin 2, 110–114 (1946).
source
PortfolioOptimisers.overlap_student_law — Function
overlap_student_law(law::BandCountLaw, f::AbstractVector{Bool}, window::Real,
                    n::Integer, T::Type) -> Tuple
overlap_student_law(law::NullMomentLaw, f::AbstractVector{Bool}, window::Real,
                    n::Integer, T::Type) -> Tuple

Return the divisor of the long-run variance of an OverlapMeanTest, and the degrees of freedom of its Student law.

Arguments

  • law: The law.
  • f: Whether each entry of the span of the series is a finite observation.
  • window: Number of entries that the data of one entry spans.
  • n: The number of finite entries.
  • T: The type of the statistic. NullMomentLaw computes in the promotion of T and the type of window.

Returns

  • nd::Real: The divisor.
  • nu::Real: The degrees of freedom.

Related

source

Long-run kernels

PortfolioOptimisers.AbstractLongRunKernel — Type
abstract type AbstractLongRunKernel <: AbstractAlgorithm

Abstract supertype for the kernels that weight the autocovariances of a long-run variance.

The long-run variance of a series is its variance plus twice the weighted sum of its autocovariances. The kernel gives the weight of the autocovariance at lag $j$ as $k(j / B)$, where $B$ is the bandwidth. A kernel has $k(0) = 1$.

Interfaces

In order to implement a new kernel that works seamlessly with the library, subtype AbstractLongRunKernel and implement the following method:

Weight method

  • long_run_kernel_weight(kernel::AbstractLongRunKernel, x::Real) -> Real: The weight $k(x)$ at the lag $x$ in units of the bandwidth.

Arguments

  • kernel: Concrete subtype instance.
  • x: The lag over the bandwidth, x > 0.

Returns

  • w::Real: The weight. A weight of zero removes the lag from the sum.

A kernel that implements the weight alone takes the generic path. Its long-run variance reads every pair of the series. Under ObservationDraws its wild bootstrap does one matrix product for each block of draws, so the cost of a draw is quadratic in the length of the series. Under EigenSumDraws it factors the matrix of the weights once, and the cost of a draw is the rank of the factor. BartlettKernel has a form that is linear in the length, and QuadraticSpectralKernel one whose draws do not grow with it.

Related

source
PortfolioOptimisers.BartlettKernel — Type
struct BartlettKernel <: AbstractLongRunKernel

Weights the autocovariance at lag $j$ by $1 - j / B$ up to the bandwidth $B$, and by zero after it.

The Bartlett kernel gives a long-run variance that is never negative. Its fixed-bandwidth form is the one that the source recommends with the wild bootstrap. The library reads it off sums of windows of the series, so its cost is linear in the length of the series at every bandwidth.

Mathematical definition

\[k(x) = \max\left(1 - |x|,\, 0\right)\,.\]

Where:

  • $x$: The lag over the bandwidth.

Constructors

BartlettKernel() -> BartlettKernel

Examples

julia> PortfolioOptimisers.long_run_kernel_weight(BartlettKernel(), 0.25)0.75

Related

References

  • [14] W. K. Newey and K. D. West. A simple, positive semi-definite, heteroskedasticity and autocorrelation consistent covariance matrix. Econometrica 55, 703–708 (1987).
  • [13] M. Demetrescu, C. Hanck and R. Kruse-Becher. Robust fixed-b inference in the presence of time-varying volatility. Econometrics and Statistics 37, 154–173 (2026).
source
PortfolioOptimisers.QuadraticSpectralKernel — Type
struct QuadraticSpectralKernel <: AbstractLongRunKernel

Weights the autocovariance at every lag by the quadratic spectral kernel, which is positive near zero and decays with an oscillation.

The kernel has no finite support, so the long-run variance reads every lag of the series. Its estimate is never negative. The kernel is the cosine transform of a weight on a bounded band of frequencies, the second line below. So QuadratureSumDraws, its default draws, reads it through a few features whose number does not grow with the length of the series.

Mathematical definition

\[\begin{align} k(x) &= \frac{25}{12 \pi^{2} x^{2}} \left( \frac{\sin(z)}{z} - \cos(z) \right) = \frac{3 \left( \sin(z) - z \cos(z) \right)}{z^{3}}\,, \quad z = \frac{6 \pi x}{5}\,, \\ k(x) &= \frac{3}{4} \int_{-1}^{1} \left( 1 - u^{2} \right) \cos(z u)\, \mathrm{d}u\,. \end{align}\]

Where:

  • $x$: The lag over the bandwidth.
  • $z$: The angle of the lag.
  • $u$: The frequency over the edge of the band.

The closed form cancels near zero, so the weight reads its Taylor series in $z^{2}$ for $|z| < 1$, which is exact to round-off there.

Constructors

QuadraticSpectralKernel() -> QuadraticSpectralKernel

Examples

julia> PortfolioOptimisers.long_run_kernel_weight(QuadraticSpectralKernel(), 0.5)0.6869307300640595

Related

References

  • [15] D. W. K. Andrews. Heteroskedasticity and autocorrelation consistent covariance matrix estimation. Econometrica 59, 817–858 (1991). Equation 2.7.
  • [13] M. Demetrescu, C. Hanck and R. Kruse-Becher. Robust fixed-b inference in the presence of time-varying volatility. Econometrics and Statistics 37, 154–173 (2026).
source

Span rules

PortfolioOptimisers.AbstractMeanTestSpan — Type
abstract type AbstractMeanTestSpan <: AbstractAlgorithm

Abstract supertype for the rules that set the span of a series, which a fixed-fraction bandwidth and a history check read.

Interfaces

In order to implement a new span rule that works seamlessly with the library, subtype AbstractMeanTestSpan and implement the following method:

Length method

  • mean_test_span_length(span::AbstractMeanTestSpan, P::Integer, i1::Integer, i2::Integer) -> Integer: The span of the series.

Arguments

  • span: Concrete subtype instance.
  • P: The number of entries of the series.
  • i1, i2: The positions of its first and its last finite entry.

Returns

  • T::Integer: The span, at least i2 - i1 + 1.

Related

source
PortfolioOptimisers.FiniteEntrySpan — Type
struct FiniteEntrySpan <: AbstractMeanTestSpan

Sets the span of a series to the entries from its first finite entry to its last.

A run of missing entries at an end of the series, such as the dates whose forward window has not matured, does not widen the bandwidth. A missing entry inside the span keeps its position.

Constructors

FiniteEntrySpan() -> FiniteEntrySpan

Examples

julia> PortfolioOptimisers.mean_test_span_length(FiniteEntrySpan(), 10, 3, 8)6

Related

source
PortfolioOptimisers.mean_test_span_length — Function
mean_test_span_length(span::FiniteEntrySpan, P::Integer, i1::Integer, i2::Integer) -> Integer
mean_test_span_length(span::FullGridSpan, P::Integer, i1::Integer, i2::Integer) -> Integer

Return the span of a series under a span rule.

Arguments

  • span: The span rule.
  • P: The number of entries of the series.
  • i1, i2: The positions of its first and its last finite entry.

Returns

Related

source

Bootstrap draws

PortfolioOptimisers.AbstractBootstrapDraws — Type
abstract type AbstractBootstrapDraws <: AbstractAlgorithm

Abstract supertype for the algorithms that draw the null law of the statistic of a WildBootstrapMeanTest.

A draw multiplies each finite entry of the centred series by an independent standard normal draw, centres the product again, and computes its t-statistic with the kernel and the bandwidth of the observed one. The statistic of a draw reads the multipliers through two Gaussian quantities alone: the sum of the product, and its quadratic form under the matrix of the kernel weights. Every member draws the same law. The members differ in the cost of a draw, and in how they read the generator, so two members answer the same p-value in law and not draw for draw.

Interfaces

In order to implement a new draw algorithm that works seamlessly with the library, subtype AbstractBootstrapDraws and implement the following method:

Draw method

  • wild_bootstrap_statistics(kernel::AbstractLongRunKernel, alg::AbstractBootstrapDraws, M::Integer, d::VecNum, f::AbstractVector{Bool}, n::Integer, nd::Integer, B::Real, buf::VecNum, rng::Random.AbstractRNG) -> Tuple: The weighted sum of the observed series and the absolute t-statistics of M draws. The generic method reads the exact sum, and it draws through draw_statistics, which an algorithm that keeps the exact sum implements in place of this method.

Arguments

  • kernel: The kernel of the test.
  • alg: Concrete subtype instance.
  • M: The number of draws.
  • d: The centred series, with a zero at each missing observation. It must not be changed.
  • f: Whether each entry of d is a finite observation.
  • n: The number of finite entries.
  • nd: The divisor of the long-run variance, n - ddof.
  • B: The bandwidth, in entries.
  • buf: Work buffer of length length(d) + 1.
  • rng: The generator.

Returns

  • Q::Real: The weighted sum of the observed series, which the observed t-statistic reads.
  • ats::Vector{<:Real}: The M absolute t-statistics, empty when Q is not positive. A statistic that is not finite is Inf.

Validation method

  • assert_bootstrap_draws(kernel::AbstractLongRunKernel, alg::AbstractBootstrapDraws) -> Nothing: Refuses a kernel that the algorithm cannot read, in the constructor of WildBootstrapMeanTest. The default method accepts every kernel, so an algorithm that reads every kernel does not implement it.

Related

source

References

[12]
F. E. Satterthwaite. An Approximate Distribution of Estimates of Variance Components. Biometrics Bulletin 2, 110–114 (1946).
[13]
M. Demetrescu, C. Hanck and R. Kruse-Becher. Robust Fixed-b Inference in the Presence of Time-Varying Volatility. Econometrics and Statistics 37, 154–173 (2026).
[14]
W. K. Newey and K. D. West. A simple, positive semi-definite, heteroskedasticity and autocorrelation consistent covariance matrix. Econometrica 55, 703–708 (1987).
[15]
D. W. Andrews. Heteroskedasticity and Autocorrelation Consistent Covariance Matrix Estimation. Econometrica 59, 817–858 (1991).