Mean test
Tests of a zero mean
PortfolioOptimisers.AbstractMeanTestEstimator — Type
abstract type AbstractMeanTestEstimator <: AbstractEstimatorAbstract 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 ofcagainst zero.
Arguments
mt: Concrete subtype instance.c: The series. ANaNentry is an observation with no value.window: Number of entries that the data of one entry spans, from the grid of the series,horizon / stepfor a forward window. A window above one means that consecutive entries share data. A test can ignore it.rng: The random number generator thatmean_test_rngresolves, ornothing.
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 answersnothing. A test that draws random numbers implements it, and resolves its generator withresolve_rng.
Related
PortfolioOptimisers.OverlapMeanTest — Type
struct OverlapMeanTest{__T_law, __T_q, __T_min_obs, __T_min_periods} <: AbstractMeanTestEstimatorTests 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
lawsets,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
lawsets. - $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, ornothingfor no rule.
min_periods: Least number of windows that the span of a series needs before the test answers, the span overwindow, ornothingfor 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,) -> OverlapMeanTestKeywords 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 aDomainError.min_obs >= 2andmin_periods > 0, when given. Raise aDomainError.
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
AbstractMeanTestEstimatorWildBootstrapMeanTestAbstractOverlapStudentLawNullMomentLawBandCountLawforecast_ic_lagsmean_test
References
- [12] F. E. Satterthwaite. An approximate distribution of estimates of variance components. Biometrics Bulletin 2, 110–114 (1946).
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} <: AbstractMeanTestEstimatorTests 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
spansets. - $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 default0is 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_capgives 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 andmin_periodsread.
ddof: Number that the divisor of the long-run variance subtracts from the count of finite entries,0for 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, ornothingfor no rule.
min_periods: Least number of windows that the span of a series needs before the test answers, the span overwindow, ornothingfor 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 ofrngseeded with it, sorngdoes not advance and every call draws the same values. Ifnothing, the draws come fromrngitself.
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,) -> WildBootstrapMeanTestKeywords 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
algreadskernel, byassert_bootstrap_draws. Raises aConflictingArgumentError.0 < b <= 1. Raises aDomainError.ddof >= 0. Raises aDomainError.n_sim > 0, andn_simat most themax_n_simofRESOURCE_LIMITS. Raises aDomainError.0 < q < 1, and1 / (n_sim + 1) <= q, so the interval has an order statistic. Raises aDomainError.min_obs >= 2andmin_periods > 0, when given. Raise aDomainError.
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_uppertrueRelated
AbstractMeanTestEstimatorOverlapMeanTestBartlettKernelQuadraticSpectralKernelFiniteEntrySpanFullGridSpanAbstractBootstrapDrawsmean_testmean_test_rng
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.
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) -> NamedTupleReturn 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 / stepfor a forward window, fromforecast_ic_window.OverlapMeanTestreads the order of its long-run variance off it. Both tests read it in the rule ofmin_periods.rng: The generator ofmean_test_rng.OverlapMeanTestdoes not read it.
Validation
window > 0. Raises aDomainError.
Returns
res::NamedTuple:(; t_stat, p_value, mean_ci_lower, mean_ci_upper).
Related
PortfolioOptimisers.mean_test_rng — Function
mean_test_rng(mt::AbstractMeanTestEstimator) -> Nothing
mean_test_rng(mt::WildBootstrapMeanTest) -> Random.AbstractRNGReturn 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 thatresolve_rngresolves from therngand theseedof the test, ornothing.
Related
Laws of the overlap test
PortfolioOptimisers.AbstractOverlapStudentLaw — Type
abstract type AbstractOverlapStudentLaw <: AbstractAlgorithmAbstract 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 aNaNtest.nu::Real: The degrees of freedom. A value that is not positive gives aNaNtest.
Related
PortfolioOptimisers.BandCountLaw — Type
struct BandCountLaw <: AbstractOverlapStudentLawDivides 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() -> BandCountLawExamples
julia> PortfolioOptimisers.overlap_student_law(BandCountLaw(), trues(60), 5, 60, Float64)(51, 51)Related
PortfolioOptimisers.NullMomentLaw — Type
struct NullMomentLaw <: AbstractOverlapStudentLawReads 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() -> NullMomentLawExamples
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).
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) -> TupleReturn 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.NullMomentLawcomputes in the promotion ofTand the type ofwindow.
Returns
nd::Real: The divisor.nu::Real: The degrees of freedom.
Related
Long-run kernels
PortfolioOptimisers.AbstractLongRunKernel — Type
abstract type AbstractLongRunKernel <: AbstractAlgorithmAbstract 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
PortfolioOptimisers.BartlettKernel — Type
struct BartlettKernel <: AbstractLongRunKernelWeights 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() -> BartlettKernelExamples
julia> PortfolioOptimisers.long_run_kernel_weight(BartlettKernel(), 0.25)0.75Related
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).
PortfolioOptimisers.QuadraticSpectralKernel — Type
struct QuadraticSpectralKernel <: AbstractLongRunKernelWeights 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() -> QuadraticSpectralKernelExamples
julia> PortfolioOptimisers.long_run_kernel_weight(QuadraticSpectralKernel(), 0.5)0.6869307300640595Related
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).
PortfolioOptimisers.long_run_kernel_weight — Function
long_run_kernel_weight(kernel::BartlettKernel, x::Real) -> Real
long_run_kernel_weight(kernel::QuadraticSpectralKernel, x::Real) -> RealReturn the weight of a kernel at the lag x, in units of the bandwidth.
Arguments
kernel: The kernel.x: The lag over the bandwidth.
Returns
w::Real: $k(x)$. The quadratic spectral kernel is1atx = 0.
Related
Span rules
PortfolioOptimisers.AbstractMeanTestSpan — Type
abstract type AbstractMeanTestSpan <: AbstractAlgorithmAbstract 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 leasti2 - i1 + 1.
Related
PortfolioOptimisers.FiniteEntrySpan — Type
struct FiniteEntrySpan <: AbstractMeanTestSpanSets 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() -> FiniteEntrySpanExamples
julia> PortfolioOptimisers.mean_test_span_length(FiniteEntrySpan(), 10, 3, 8)6Related
PortfolioOptimisers.FullGridSpan — Type
struct FullGridSpan <: AbstractMeanTestSpanSets the span of a series to every entry of its grid, the missing entries at its ends included.
Constructors
FullGridSpan() -> FullGridSpanExamples
julia> PortfolioOptimisers.mean_test_span_length(FullGridSpan(), 10, 3, 8)10Related
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) -> IntegerReturn 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
T::Integer:i2 - i1 + 1underFiniteEntrySpan, andPunderFullGridSpan.
Related
Bootstrap draws
PortfolioOptimisers.AbstractBootstrapDraws — Type
abstract type AbstractBootstrapDraws <: AbstractAlgorithmAbstract 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 ofMdraws. The generic method reads the exact sum, and it draws throughdraw_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 ofdis 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 lengthlength(d) + 1.rng: The generator.
Returns
Q::Real: The weighted sum of the observed series, which the observed t-statistic reads.ats::Vector{<:Real}: TheMabsolute t-statistics, empty whenQis not positive. A statistic that is not finite isInf.
Validation method
assert_bootstrap_draws(kernel::AbstractLongRunKernel, alg::AbstractBootstrapDraws) -> Nothing: Refuses a kernel that the algorithm cannot read, in the constructor ofWildBootstrapMeanTest. The default method accepts every kernel, so an algorithm that reads every kernel does not implement it.
Related
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).