| Title: | Mean-Variance Spanning Tests |
|---|---|
| Description: | Provides a comprehensive suite of portfolio spanning tests for asset pricing, such as Huberman and Kandel (1987) <doi:10.1111/j.1540-6261.1987.tb03917.x>, Gibbons et al. (1989) <doi:10.2307/1913625>, Kempf and Memmel (2006) <doi:10.1007/BF03396737>, Pesaran and Yamagata (2024) <doi:10.1093/jjfinec/nbad002>, and Gungor and Luger (2016) <doi:10.1080/07350015.2015.1019510>. |
| Authors: | David Ardia [aut, cre] (ORCID: <https://orcid.org/0000-0003-2823-782X>), Benjamin Seguin [aut], Rosnel Sessinou [ctb], Richard Luger [ctb] |
| Maintainer: | David Ardia <[email protected]> |
| License: | GPL-3 |
| Version: | 1.3-0 |
| Built: | 2026-07-13 23:39:29 UTC |
| Source: | https://github.com/ardiad/spantest |
Computes robust p-values for linear spanning restrictions using a residual-based
subseries procedure with Cauchy Combination Test (CCT) aggregation. Supports high-dimensional
inference for (variance/spread slopes), (intercepts),
and the joint null .
span_as(bench, test, control = list())span_as(bench, test, control = list())
bench |
Numeric matrix of benchmark returns, dimension |
test |
Numeric matrix of test-asset returns, dimension |
control |
Optional list passed to internal computation:
|
For each k in ks, data are partitioned into overlapping subseries of length floor(T^k).
Residual perturbations controlled by L generate test statistics robust to serial and
cross-sectional dependence and conditional heteroskedasticity. Resulting sub-p-values are aggregated
by the Cauchy Combination Test (CCT), which remains valid under dependence and retains power in high dimensions.
A named list of global (combined) p-values. Names encode hypothesis and settings:
CCTd_L{L}_k{i} — variance (slope) spanning, ;
CCTa_L{L}_k{i} — alpha spanning, ;
CCTad_L{L}_k{i} — joint mean–variance spanning, .
Ardia D, Sessinou R (2025).
“Robust Inference in Large Panels and Markowitz Portfolios.”
doi:10.2139/ssrn.5033399.
Working paper.
Other Alpha Spanning Tests:
span_bj(),
span_f1(),
span_gl_a(),
span_grs(),
span_py()
Other Variance Spanning Tests:
span_f2(),
span_km()
Other Joint Mean-Variance Spanning Tests:
span_gl_ad(),
span_hk()
set.seed(123) bench <- matrix(rnorm(300), 100, 3) test <- matrix(rnorm(200), 100, 2) out <- span_as(bench, test) out$CCTa_L0_k1; out$CCTd_L0_k1; out$CCTad_L0_k1set.seed(123) bench <- matrix(rnorm(300), 100, 3) test <- matrix(rnorm(200), 100, 2) out <- span_as(bench, test) out$CCTa_L0_k1; out$CCTd_L0_k1; out$CCTad_L0_k1
Tests whether the tangency (maximum Sharpe) portfolio of the augmented
universe (benchmarks + test assets) is spanned by the benchmark assets
alone. Following Britten–Jones (1999), the statistic arises from a
regression of a constant on the raw asset returns (without an intercept)
and yields an test of the tangency-spanning restriction.
span_bj(R1, R2)span_bj(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
Following Britten–Jones (1999), the (unnormalized) tangency-portfolio weights
are obtained by regressing a vector of ones on the raw asset returns without an
intercept. The null that the benchmarks span the tangency portfolio is the
restriction that the test assets carry zero weight, tested by comparing the
residual sums of squares of the full and benchmark-only regressions. The
statistic has an reference distribution; finite-sample
feasibility requires .
A named list with components:
pvalP-value for the -statistic under the null.
statBritten–Jones -statistic.
H0Null hypothesis description, "alpha = 0" (the test
assets do not expand the tangency portfolio spanned by the benchmarks).
Britten-Jones M (1999).
“The Sampling Error in Estimates of Mean-Variance Efficient Portfolio Weights.”
The Journal of Finance, 54(2), 655–671.
Other Alpha Spanning Tests:
span_as(),
span_f1(),
span_gl_a(),
span_grs(),
span_py()
set.seed(321) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_bj(R1, R2) out$stat; out$pval; out$H0set.seed(321) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_bj(R1, R2) out$stat; out$pval; out$H0
Tests the null that the intercepts of the test assets
are jointly zero when regressed on the benchmark assets, i.e., benchmarks
span the mean of the test assets. This is the F1 test of Kan & Zhou (2012).
span_f1(R1, R2)span_f1(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
Under standard assumptions (i.i.d. returns, full-rank covariances), the
reference distribution is . Finite-sample feasibility
requires .
A named list with components:
pvalP-value for the -statistic under the null.
statF1 -statistic.
H0Null hypothesis description, "alpha = 0".
Kan R, Zhou G (2012). “Tests of Mean-Variance Spanning.” Annals of Economics and Finance, 13(1), 145–193.
Other Alpha Spanning Tests:
span_as(),
span_bj(),
span_gl_a(),
span_grs(),
span_py()
set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_f1(R1, R2) out$stat; out$pval; out$H0set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_f1(R1, R2) out$stat; out$pval; out$H0
Tests the null that adding test assets does not
improve the minimum-variance frontier spanned by the benchmarks (variance
spanning). The statistic compares frontier-defining quantities of the
augmented (benchmark + test) universe to those of the benchmark subset.
span_f2(R1, R2)span_f2(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
Under standard conditions (i.i.d. returns, full-rank covariances), the reference
distribution is . Finite-sample feasibility requires
.
A named list with components:
pvalP-value for the -statistic under the null.
statF2 -statistic.
H0Null hypothesis description, "delta = 0".
Kan R, Zhou G (2012). “Tests of Mean-Variance Spanning.” Annals of Economics and Finance, 13(1), 145–193.
Other Variance Spanning Tests:
span_as(),
span_km()
set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_f2(R1, R2) out$stat; out$pval; out$H0set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_f2(R1, R2) out$stat; out$pval; out$H0
Tests the null that benchmark assets span the mean
(intercepts) of the test assets. Following Gungor & Luger (2016), the
procedure uses a Monte Carlo (MC) test based on an statistic
with residual sign-flip simulations, yielding Least-Favorable (LMC) and
Balanced (BMC) MC p-values and a three-way decision rule.
span_gl_a(R1, R2, control = list())span_gl_a(R1, R2, control = list())
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
control |
List of options:
|
Accept if pval_LMC > alpha; Reject if pval_BMC <= alpha;
otherwise Inconclusive. The subseries sign-flip MC approach is robust to
heteroskedasticity, serial dependence, and heavy tails, making it suitable
for high-dimensional settings where classical alpha tests (e.g., GRS) may
suffer from size distortions.
A list with components:
pval_LMCLeast-Favorable MC p-value.
pval_BMCBalanced MC p-value.
statObserved statistic.
DecisionsDecision code: 1 = Accept, 0 = Reject, NA = Inconclusive.
Decisions_stringText label: "Accept", "Reject", or "Inconclusive".
H0Null hypothesis description, "alpha = 0".
Gungor S, Luger R (2016).
“Multivariate Tests of Mean-Variance Efficiency and Spanning With a Large Number of Assets and Time-Varying Covariances.”
Journal of Business & Economic Statistics, 34(2), 161–175.
Other Alpha Spanning Tests:
span_as(),
span_bj(),
span_f1(),
span_grs(),
span_py()
set.seed(1234) R1 <- matrix(rnorm(300), 100, 3) R2 <- matrix(rnorm(200), 100, 2) out <- span_gl_a(R1, R2, control = list(totsim = 100, do_trace = FALSE)) out$Decisions_string; out$pval_LMC; out$pval_BMCset.seed(1234) R1 <- matrix(rnorm(300), 100, 3) R2 <- matrix(rnorm(200), 100, 2) out <- span_gl_a(R1, R2, control = list(totsim = 100, do_trace = FALSE)) out$Decisions_string; out$pval_LMC; out$pval_BMC
Tests the joint null that benchmark assets
span both intercepts and slopes of the test assets, allowing for
heteroskedasticity, serial dependence, and time-varying covariances.
Following Gungor & Luger (2016), the procedure uses a Monte Carlo (MC)
test based on an statistic with residual sign-flip simulations,
yielding Least-Favorable (LMC) and Balanced (BMC) MC p-values and a
three-way decision rule.
span_gl_ad(R1, R2, control = list())span_gl_ad(R1, R2, control = list())
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
control |
List of options:
|
LMC/BMC follow Gungor & Luger’s MC framework with residual sign-flip draws under
the null. The rule is: Accept if pval_LMC > alpha; Reject if
pval_BMC <= alpha; otherwise Inconclusive. This approach is robust in
high-dimensional and time-varying volatility settings where classical joint
spanning tests can be unreliable.
A list with components:
pval_LMCLeast-Favorable MC p-value.
pval_BMCBalanced MC p-value.
statObserved statistic.
DecisionsDecision code: 1 = Accept, 0 = Reject, NA = Inconclusive.
Decisions_stringText label: "Accept", "Reject", or "Inconclusive".
H0Null hypothesis description, "alpha = 0 and delta = 0".
Gungor S, Luger R (2016).
“Multivariate Tests of Mean-Variance Efficiency and Spanning With a Large Number of Assets and Time-Varying Covariances.”
Journal of Business & Economic Statistics, 34(2), 161–175.
Other Joint Mean-Variance Spanning Tests:
span_as(),
span_hk()
set.seed(123) R1 <- matrix(rnorm(300), 100, 3) R2 <- matrix(rnorm(200), 100, 2) out <- span_gl_ad(R1, R2, control = list(totsim = 100, do_trace = FALSE)) out$Decisions_string; out$pval_LMC; out$pval_BMCset.seed(123) R1 <- matrix(rnorm(300), 100, 3) R2 <- matrix(rnorm(200), 100, 2) out <- span_gl_ad(R1, R2, control = list(totsim = 100, do_trace = FALSE)) out$Decisions_string; out$pval_LMC; out$pval_BMC
Implements the GRS test of the joint null in the
multivariate regression of test-asset returns on benchmark portfolios
(with an intercept). The statistic assumes homoskedastic, normally
distributed errors and is most reliable when is large relative
to (benchmarks) and (test assets).
span_grs(R1, R2)span_grs(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
Under standard conditions, the reference distribution is
. Finite-sample feasibility requires .
A named list with components:
pvalP-value for the -statistic under the null.
statGRS -statistic.
H0Null hypothesis description, "alpha = 0".
Gibbons MR, Ross SA, Shanken J (1989).
“A Test of the Efficiency of a Given Portfolio.”
Econometrica, 57(5), 1121–1152.
Other Alpha Spanning Tests:
span_as(),
span_bj(),
span_f1(),
span_gl_a(),
span_py()
set.seed(42) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_grs(R1, R2) out$stat; out$pval; out$H0set.seed(42) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_grs(R1, R2) out$stat; out$pval; out$H0
Tests the joint null that the benchmark
assets span the mean–variance frontier of the augmented (benchmark + test)
universe. Following Huberman & Kandel (1987), the statistic compares the
frontiers with and without the additional assets.
span_hk(R1, R2)span_hk(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
The test evaluates whether adding the test assets changes the efficient
frontier implied by the benchmarks. Under standard regularity conditions,
the statistic has an reference with degrees of
freedom. Finite-sample feasibility requires .
A named list with components:
pvalP-value for the -statistic under the null.
stat-statistic value.
H0Null hypothesis description, "alpha = 0 and delta = 0".
Huberman G, Kandel S (1987).
“Mean-Variance Spanning.”
The Journal of Finance, 42(4), 873–888.
Other Joint Mean-Variance Spanning Tests:
span_as(),
span_gl_ad()
set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_hk(R1, R2) out$stat; out$pval; out$H0set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_hk(R1, R2) out$stat; out$pval; out$H0
Tests whether the Global Minimum Variance Portfolio (GMVP) of the combined (benchmark + test) universe equals the GMVP of the benchmark assets alone. Following Kempf & Memmel (2006), the null assesses whether adding new assets improves the minimum-variance frontier.
span_km(R1, R2)span_km(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
The null hypothesis is that augmenting the benchmark set with the
test assets does not change the GMVP weights (), i.e.,
the GMVP of the full universe coincides with that of the benchmark subset.
The test is implemented via a linear restriction on coefficients in an
equivalent regression representation, yielding an -statistic.
A named list with components:
pvalP-value for the F-statistic under the null.
statF-statistic value.
H0Null hypothesis description, "delta = 0" (equivalently,
GMVP of the benchmark set equals GMVP of the full universe).
Kempf A, Memmel C (2006).
“Estimating the Global Minimum Variance Portfolio.”
Schmalenbach Business Review, 58(4), 332–348.
Other Variance Spanning Tests:
span_as(),
span_f2()
set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # test assets: T=100, N=2 ans <- span_km(R1, R2) ans$pval; ans$stat; ans$H0set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # test assets: T=100, N=2 ans <- span_km(R1, R2) ans$pval; ans$stat; ans$H0
Implements the Pesaran–Yamagata test for the joint null that all intercepts are zero in a multi-factor spanning regression with possible cross-sectional dependence across test assets.
span_py(R1, R2)span_py(R1, R2)
R1 |
Numeric matrix of benchmark returns, dimension |
R2 |
Numeric matrix of test-asset returns, dimension |
The null hypothesis is that all intercepts are zero (), meaning
the benchmark assets span the expected returns of the test assets. The statistic
adjusts for cross-sectional dependence via the residual covariance and has an
asymptotic reference under large . Finite-sample
safeguards require and at least two test assets ();
otherwise pval and stat are returned as NA.
A named list with components:
pvalP-value under the standard normal reference distribution.
statStandardized test statistic.
H0Null hypothesis description, "alpha = 0".
Pesaran MH, Yamagata T (2024). “Testing for alpha in linear factor pricing models with a large number of securities.” Journal of Financial Econometrics, 22(2), 407–460.
Other Alpha Spanning Tests:
span_as(),
span_bj(),
span_f1(),
span_gl_a(),
span_grs()
set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_py(R1, R2) out$pval; out$stat; out$H0set.seed(123) R1 <- matrix(rnorm(300), 100, 3) # benchmarks: T=100, K=3 R2 <- matrix(rnorm(200), 100, 2) # tests: T=100, N=2 out <- span_py(R1, R2) out$pval; out$stat; out$H0
Generates a panel of benchmark returns () and
test-asset returns () from a factor model with a
controllable mean-variance spanning violation, matching the data-generating
processes used in the size/power study of Ardia and Sessinou (2025). It is a
fast, self-contained replacement for ad-hoc fGarch::garchSim() loops:
the innovations are drawn in one vectorised call and the AR / GARCH dynamics
are applied with a lightweight recursion.
span_simulate( n, K, N, ncp = 0, rho_factor = 0.8, rho_error = 0.5, innovation = c("normal", "t", "skew-t"), dynamics = c("iid", "ar", "garch", "ar-garch"), sparse = FALSE, df = 5, xi = 0.9, ar = 0.2, garch = c(omega = 0.1, alpha = 0.1, beta = 0.8), standardize = TRUE, dgp = NULL, burnin = 500L )span_simulate( n, K, N, ncp = 0, rho_factor = 0.8, rho_error = 0.5, innovation = c("normal", "t", "skew-t"), dynamics = c("iid", "ar", "garch", "ar-garch"), sparse = FALSE, df = 5, xi = 0.9, ar = 0.2, garch = c(omega = 0.1, alpha = 0.1, beta = 0.8), standardize = TRUE, dgp = NULL, burnin = 500L )
n |
Integer, number of time periods (sample size). |
K |
Integer, number of benchmark assets. |
N |
Integer, number of test assets. |
ncp |
Non-centrality controlling the spanning violation (0 = null). |
rho_factor, rho_error
|
Toeplitz correlation decays for the factors and
the idiosyncratic terms, in |
innovation |
Marginal law of the innovations: |
dynamics |
Serial structure: |
sparse |
Logical; if |
df |
Degrees of freedom for the Student-/skew- |
xi |
Skewness parameter for the skew- |
ar |
AR(1) coefficient (used by |
garch |
Named numeric vector |
standardize |
Logical; standardise |
dgp |
Optional integer in |
burnin |
Integer, number of initial observations discarded to remove the AR/GARCH transient. |
The latent factors are innovation series, cross-sectionally
correlated through the Cholesky factor of a Toeplitz matrix with decay
rho_factor; the idiosyncratic terms are innovation series with
Toeplitz decay rho_error. Test assets are
and the benchmarks are . Under
ncp = 0 the benchmarks span the test assets (); larger
|ncp| moves the intercepts and loadings away from the spanning null.
With sparse = TRUE the first intercepts are
set to zero (a sparse alternative); is added column-wise, i.e.
asset receives .
Each innovation series is defined by innovation (marginal law) and
dynamics (serial structure): "iid", an AR(1) with coefficient
ar, a GARCH(1,1) with parameters garch, or their
"ar-garch" combination. Student- innovations are standardised to
unit variance when standardize = TRUE; skew- innovations
(standardised Fernandez-Steel skew-) are always unit-variance, so
standardize has no effect on them.
dgp is a convenience argument selecting one of the twelve processes of
Ardia and Sessinou (2025); when supplied it overrides innovation,
dynamics, df, xi and standardize:
| 1 | normal, iid | 7 | normal, AR-GARCH |
| 2 | Student-t(5), iid (raw) | 8 | Student-t(4), AR-GARCH |
| 3 | skew-t(4, 0.9), iid | 9 | skew-t(4, 0.9), AR-GARCH |
| 4 | normal, GARCH | 10 | normal, AR |
| 5 | Student-t(4), GARCH | 11 | Student-t(5), AR (raw) |
| 6 | skew-t(4, 0.9), GARCH | 12 | skew-t(4, 0.9), AR |
DGPs 2 and 11 use raw (non-standardised) innovations, as in
the original study; all other heavy-tailed processes are standardised.
A list with components R1 ( benchmark returns)
and R2 ( test-asset returns), suitable as the
R1/R2 arguments of the spanning tests in this package.
Set the RNG state with set.seed beforehand for
reproducibility.
Ardia D, Sessinou R (2025).
“Robust Inference in Large Panels and Markowitz Portfolios.”
doi:10.2139/ssrn.5033399.
Working paper.
Gungor S, Luger R (2016).
“Multivariate Tests of Mean-Variance Efficiency and Spanning With a Large Number of Assets and Time-Varying Covariances.”
Journal of Business & Economic Statistics, 34(2), 161–175.
span_grs(), span_gl_ad(), span_as()
set.seed(1) sim <- span_simulate(n = 250, K = 3, N = 10, ncp = 0) # spanning null span_grs(sim$R1, sim$R2)$pval sim2 <- span_simulate(n = 250, K = 3, N = 10, ncp = 0.2) # alternative span_grs(sim2$R1, sim2$R2)$pvalset.seed(1) sim <- span_simulate(n = 250, K = 3, N = 10, ncp = 0) # spanning null span_grs(sim$R1, sim$R2)$pval sim2 <- span_simulate(n = 250, K = 3, N = 10, ncp = 0.2) # alternative span_grs(sim2$R1, sim2$R2)$pval