factrix.stats ¶
Statistical tooling shared across the library.
The slice-test selection classes carry pure identity semantics
(name / description, no compute); their numerics live in
the slice-test dispatch path and the factrix._stats kernels.
Series-mean HAC inference lives in factrix.inference.
WaldNWCluster / WaldTwoWayCluster — cluster-robust Wald χ²
selection-only instances for slice contrasts.
DriscollKraay — Driscoll-Kraay (1998)
cross-section-robust HAC SE for pooled-panel slopes; selection-only
identity handle, numerics consumed by pooled_beta.
multiple_testing — BHY false-discovery plus Holm and Romano-Wolf
family-wise error-rate adjustments across a declared search family.
bootstrap — stationary-bootstrap resampling + CI for dependent series.
DriscollKraay ¶
Driscoll & Kraay (1998) cross-section-robust heteroskedasticity-and-autocorrelation-consistent (HAC) SE for a pooled-panel slope.
Aggregates the per-observation OLS scores cross-sectionally within
each period, then runs a Bartlett-kernel HAC on the resulting time
series of cross-sectional sums and sandwiches with (X'X)⁻¹. The
result is robust to arbitrary contemporaneous cross-sectional
correlation — the gap a one-way cluster-on-date SE leaves open,
which understates SE for small, cross-sectionally correlated panels
(Petersen (2009)). Numerics live in
factrix._stats.hac._driscoll_kraay_cov; pooled_beta drives
them directly.
Pass an instance to a function to make the inference choice explicit.
Constructor takes no arguments in this release. pooled_beta resolves
the Bartlett bandwidth, finite-sample covariance scale, and effective
degrees of freedom from the period count and overlap horizon; an
explicit-lag override lives on the metric call rather than on this
identity handle.
WaldNWCluster ¶
Cluster-robust Wald χ² with Newey-West (NW) Bartlett heteroskedasticity-and-autocorrelation-consistent (HAC) + 1-way slice cluster.
Backs the slice test on a per-date metric panel: K parallel
per-slice metric series (information coefficient (IC), FM λ, etc.) are stacked and a Wald
contrast tests the equality of slice means under joint NW HAC of
the K-vector. Numerics live in
factrix._stats.wald._wald_nw_cluster_means.
Applicability is restricted to (INDIVIDUAL, DENSE) — the
PANEL inference cells whose per-date scalars feed the stacked
panel. COMMON cells produce one number per date by definition
of the scope and have no within-cell cross-section to slice over.
This is the sole analytic estimator the slice tests run; it is applied internally (the slice-test functions take no estimator argument). The class names that inference path for documentation and introspection.
Constructor takes no arguments in this release; the Bartlett-kernel
bandwidth is resolved by _wald_nw_cluster_means
(auto_bartlett(T) default, floored at overlap_periods - 1 by
the slice tests to cover overlapping-return autocorrelation).
WaldTwoWayCluster ¶
Two-way cluster Wald χ² on (date, asset) — Cameron-Gelbach-Miller (2011).
Backs the raw asset-date panel inference path (factor × slice
interaction with full panel SE). Numerics live in
factrix._stats.wald._wald_two_way_cluster.
Reserved interface; no function consumes it until
factor_decomposition lands later.
bhy_adjust ¶
Benjamini-Hochberg-Yekutieli (BHY) step-up rejection mask.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p_values
|
ArrayLike
|
1-D array of p-values in [0, 1]. Each must come from the same test family (e.g. all information coefficient (IC) p-values or all CAAR p-values). Public screening helpers enforce family consistency before calling this primitive. |
required |
fdr
|
float
|
Target false discovery rate (FDR) (default 0.05). |
0.05
|
n_tests
|
int | None
|
Full candidate family size for two-stage screening. If
caller already pre-filtered from a larger pool (e.g. 1000
candidates → 50 submitted), pass the pre-filter size here.
Must be |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Boolean mask of length |
ndarray
|
is rejected. Order matches the input. |
References
- Benjamini & Yekutieli (2001). "The
Control of the False Discovery Rate in Multiple Testing under
Dependency." Annals of Statistics, 29(4), 1165–1188. The
c(m) = Σ 1/icorrection underlying this step-up rule.
bhy_adjusted_p ¶
Per-hypothesis Benjamini-Hochberg-Yekutieli (BHY)-adjusted p-values (clipped at 1).
Formula: scale p_(k) by (m * c(m)) / k then cummin from the
right to enforce monotonicity in ranked order. Gives a stable
per-factor "how significant under false discovery rate (FDR) control" number.
n_tests follows the same contract as bhy_adjust — pass the
pre-filter size when the submitted p's are survivors of a larger
candidate family.
References
- Benjamini & Yekutieli (2001). "The
Control of the False Discovery Rate in Multiple Testing under
Dependency." Annals of Statistics, 29(4), 1165–1188. The
per-hypothesis adjusted-p mapping derived from the same
step-up rule used by
bhy_adjust.
bootstrap_mean_ci ¶
bootstrap_mean_ci(values: ndarray, *, n_resamples: int = 999, ci: float = 0.95, block_length: float | None = None, rng: Rng = None, statistic: Callable[[ndarray], float] | None = None, method: Literal['studentized', 'percentile'] = 'studentized') -> BootstrapCI
Stationary-bootstrap confidence interval for a statistic.
Default statistic is the arithmetic mean (matches the parametric
t-test's H₀ null). Pass a callable taking a 1-D array and returning
a scalar to CI other statistics (e.g. Sharpe, median, skewness);
those require method="percentile" (see below).
Studentized by default. The interval is the bootstrap-t
$$\left[\bar x - t^*_{1-\alpha}\,\widehat{se},\;
\bar x - t^*_{\alpha}\,\widehat{se}
\right],\qquad
t^*_b = \frac{\bar x^*_b - \bar x}{\widehat{se}^*_b}$$
with \(\widehat{se}\) the batch-means block SE
(:func:factrix._stats.bootstrap._batch_means_se) at the resolved
block length. The percentile interval is first-order accurate only
(DiCiccio-Efron (1996)), and under dependence
it compounds the block bootstrap's finite-sample long-run-variance
shortfall — which is exactly the regime this module's docstring
reaches for it.
Measured two-sided coverage at nominal 95% on an AR(1) mean (500 sims, B=999):
| φ | T | percentile | studentized |
|---|---|---|---|
| 0.0 | 100 | 0.940 | 0.942 |
| 0.0 | 500 | 0.946 | 0.954 |
| 0.5 | 100 | 0.862 | 0.916 |
| 0.5 | 500 | 0.924 | 0.940 |
| 0.8 | 100 | 0.792 | 0.890 |
| 0.8 | 500 | 0.902 | 0.934 |
Studentizing removes roughly half the under-coverage; it does not remove it. A short, strongly persistent series still under-covers, and no resampling scheme fixes that — read the last row as the disclosed limit, not as a residual bug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
ndarray
|
1-D array of the original series, at least 2 finite observations. |
required |
n_resamples
|
int
|
Resample count. Must be at least
|
999
|
ci
|
float
|
Two-sided coverage, e.g. |
0.95
|
block_length
|
float | None
|
See |
None
|
rng
|
Rng
|
An |
None
|
statistic
|
Callable[[ndarray], float] | None
|
Scalar function applied to each resample. Defaults
to |
None
|
method
|
Literal['studentized', 'percentile']
|
|
'studentized'
|
Returns:
| Type | Description |
|---|---|
BootstrapCI
|
class: |
BootstrapCI
|
|
Raises:
| Type | Description |
|---|---|
UserInputError
|
|
References
- Politis & Romano (1994). "The Stationary Bootstrap." Journal of the American Statistical Association, 89(428), 1303–1313. Underlying resampling scheme.
- DiCiccio & Efron (1996). "Bootstrap Confidence Intervals." Statistical Science 11(3), 189–228. Accuracy ordering that makes the studentized interval the default here.
- Götze & Künsch (1996). Second-order correctness of the blockwise bootstrap for a studentized root.
holm_adjusted_p ¶
Holm (1979) step-down FWER-adjusted p-values.
Holm controls the probability of at least one false rejection within a declared family under arbitrary dependence. It is appropriate when a search produces one selected winner or when every retained hypothesis must be protected from any false positive. Use BHY instead when the goal is to retain a batch while controlling the expected false-discovery proportion.
The submitted p-values are ordered from smallest to largest and scaled by
m, m - 1, ..., m - n + 1 before a cumulative maximum enforces the
step-down rejection order. m is n_tests when supplied and
otherwise len(p_values).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p_values
|
ArrayLike
|
One-dimensional, finite p-values in |
required |
n_tests
|
int | None
|
Full number of hypotheses tried when |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Adjusted p-values in input order as a NumPy array, clipped to |
ndarray
|
|
References
- Holm (1979). "A Simple Sequentially Rejective Multiple Test Procedure." Scandinavian Journal of Statistics, 6(2), 65-70.
partial_conjunction_p ¶
partial_conjunction_p(p_values: ArrayLike, *, min_pass: int) -> float
Bonferroni-style partial conjunction p-value (Benjamini-Heller (2008)).
Tests H_0^{k/m}: at most k - 1 of the m alternatives are
true, against H_1^{k/m}: at least k are true. The combined
p-value is
``p_PC = min(1, (m - k + 1) * p_((k)))``
where p_((k)) is the k-th smallest of the m p-values
(1-indexed). k = m reduces to max(p) (full conjunction);
k = 1 reduces to Bonferroni-corrected min(p).
min_pass must be declared before the p-values are seen. The
combined p-value is not monotone in k: the multiplier
m - k + 1 falls as the order statistic p_((k)) rises, so
demanding more passing conditions can lower p_PC — for
p = [0.01, 0.02, 0.9], k = 2 gives 0.04 while k = 3
gives 0.9, and for p = [0.01, 0.4, 0.5] the ordering reverses.
Choosing k after inspecting the p-values is a selection effect that
no downstream step-up corrects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p_values
|
ArrayLike
|
1-D array of m per-condition p-values for a single hypothesis (e.g. one factor across m universes). |
required |
min_pass
|
int
|
|
required |
Returns:
| Type | Description |
|---|---|
float
|
The PC p-value, clipped to |
References
- Benjamini & Heller (2008). "Screening for Partial Conjunction Hypotheses." Biometrics, 64(4), 1215–1222. The partial-conjunction test implemented here.
romano_wolf_adjusted_p ¶
romano_wolf_adjusted_p(statistics: ArrayLike, bootstrap_statistics: ArrayLike, *, one_sided: bool = False, expected_warnings: tuple[str, ...] = ()) -> ndarray
Romano-Wolf (2005) step-down max-t adjusted p-values.
Romano-Wolf controls the family-wise error rate while using the joint
bootstrap distribution to account for dependence among hypotheses. Each
bootstrap row must be one joint draw across all m hypotheses. Building
columns with independent resampling would destroy that dependence and
invalidate the method's power advantage over Holm.
This is an expert-level adjusted-p primitive, not a resampling workflow.
The caller is responsible for generating bootstrap statistics under the
joint null, centring them at the null, and using the same studentization as
the observed statistics. Every hypothesis tried in the search must occupy
one column; unlike holm_adjusted_p(n_tests=...), this function cannot
account for omitted hypotheses without their joint bootstrap statistics.
The empirical p-value grid has resolution 1 / (B + 1) because the
calculation uses add-one smoothing. Bootstrap values tied with the
observed statistic count as exceedances (>=), a conservative tie rule
for discrete bootstrap distributions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
statistics
|
ArrayLike
|
Finite one-dimensional observed test statistics of length
|
required |
bootstrap_statistics
|
ArrayLike
|
Finite |
required |
one_sided
|
bool
|
|
False
|
expected_warnings
|
tuple[str, ...]
|
:class: |
()
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Adjusted p-values in input order as a NumPy array, each in |
References
- Romano & Wolf (2005). "Stepwise Multiple Testing as Formalized Data Snooping." Econometrica, 73(4), 1237-1282.
- Romano & Wolf (2016). "Efficient Computation of Adjusted P-Values for Resampling-Based Stepdown Multiple Testing." Statistics & Probability Letters, 113, 38-40.
simes_p ¶
simes_p(p_values: ArrayLike) -> float
Simes (1986) global-null p-value for a group of tests.
Formula: p_Simes = min_{k=1..m} (m / k) * p_((k)) where
p_((k)) is the k-th smallest of the m p-values
(1-indexed). Tests the global null "all m nulls hold" against
"at least one alternative is true"; valid under independence and
positive regression dependence on a subset (PRDS).
Yekutieli (2008) uses Simes as the default group representative
in hierarchical false discovery rate (FDR) procedures — it dominates Bonferroni
(m * min(p)) and preserves group-level FDR control when fed
to an outer Benjamini-Hochberg-Yekutieli (BHY) step-up.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p_values
|
ArrayLike
|
1-D array of |
required |
Returns:
| Type | Description |
|---|---|
float
|
The Simes combined p-value, clipped to |
Raises:
| Type | Description |
|---|---|
UserInputError
|
|
References
- Simes (1986). "An Improved Bonferroni Procedure for Multiple Tests of Significance." Biometrika, 73(3), 751–754. The combined-test formula implemented here.
- Yekutieli (2008). "Hierarchical False Discovery Rate-controlling Methodology." Journal of the American Statistical Association, 103(481), 309–316. Uses Simes as the group representative in hierarchical FDR procedures fed to an outer BHY step-up.
stationary_bootstrap_resamples ¶
stationary_bootstrap_resamples(values: ndarray, n_resamples: int = 999, *, block_length: float | None = None, rng: Rng = None) -> ndarray
Draw n_resamples stationary-bootstrap resamples of values.
Each resample has the same length T as the input. One-dimensional
input returns (B, T); two-dimensional (T, m) input returns
(B, T, m) and applies the same sampled row indices to every column.
The latter preserves cross-hypothesis dependence for joint bootstrap
procedures such as Romano-Wolf. Blocks have geometric lengths with mean
block_length and sampling is circular.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
ndarray
|
Finite |
required |
n_resamples
|
int
|
Number of resamples to draw. |
999
|
block_length
|
float | None
|
Mean geometric block length. Defaults to the
Politis-White (2004) automatic spectral
plug-in (falling back to the practical |
None
|
rng
|
Rng
|
An |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
ndarray
|
|
Notes
This function returns resamples, not inference. Forming a
percentile interval or an empirical p directly from the returned
array gives a first-order accurate interval
(DiCiccio-Efron (1996)) — it forgoes the
studentization :func:bootstrap_mean_ci applies by default, and
under dependence it compounds the block bootstrap's finite-sample
long-run-variance shortfall. The measured cost is the
percentile column of the AR(1) coverage table in
:func:bootstrap_mean_ci: at phi=0.8, T=100 percentile covers
0.792 against studentized 0.890 (nominal 0.95).
This is the default path for a paired custom statistic, not an
edge case. Joint resampling of aligned columns is only available
here (2-D input), and :func:bootstrap_mean_ci takes 1-D input
and requires method="percentile" for any custom
statistic — the studentized root needs a block SE of the
statistic on every resample, which this module has only for the
mean. So a paired, non-mean statistic reaches percentile accuracy
from either entry point. Prefer :func:bootstrap_mean_ci whenever
the statistic is a mean of a 1-D series; when it is not, read the
resulting interval as first-order accurate and size the sample
accordingly.
References
- Politis & Romano (1994). "The Stationary Bootstrap." Journal of the American Statistical Association, 89(428), 1303–1313. Stationary block bootstrap with geometric block lengths — the resampling scheme this function implements.
- Politis & White (2004). "Automatic Block-
Length Selection for the Dependent Bootstrap." Econometric
Reviews, 23(1), 53–70. Source of the spectral plug-in
block_length=Noneresolves to.
Inference-method instances + standalone statistical helpers under factrix.stats.
Estimator catalogue¶
The selection-only estimator classes under factrix.stats:
| Class | Algorithm family | Description |
|---|---|---|
WaldNWCluster |
Cluster-Wald \(\chi^2\) (1-way cluster on slice) | 1-way cluster-robust Wald contrast test |
WaldTwoWayCluster |
Cluster-Wald \(\chi^2\) (two-way cluster on (date, asset)) | 2-way cluster-robust Wald contrast test |
DriscollKraay |
Driscoll-Kraay cross-section-robust HAC SE | Selection-only base Estimator for Driscoll-Kraay robust standard errors |
Multiplicity / bootstrap utilities¶
bhy_adjust(p_values, fdr=0.05, *, n_tests=None): Benjamini-Yekutieli step-up rejection mask. Returns a boolean array.bhy_adjusted_p(p_values, *, n_tests=None): BHY-adjusted p-values (clipped at 1.0).holm_adjusted_p(p_values, *, n_tests=None): Holm step-down FWER-adjusted p-values under arbitrary dependence. Use FWER when a search selects one winner or every retained hypothesis must avoid any false positive; use FDR when retaining a batch and controlling its expected false-discovery proportion.romano_wolf_adjusted_p(statistics, bootstrap_statistics, *, one_sided=False, expected_warnings=()): Dependence-aware step-down max-t FWER-adjusted p-values. This expert primitive requires every searched hypothesis and each bootstrap row to be a joint, null-centred draw with the same studentization as the observed statistics; independently resampled or omitted columns are invalid. Its empirical p-value resolution is1 / (B + 1). An off-centre bootstrap and fewer than 99 resamples emit the declarableromano_wolf_uncentred_bootstrapandromano_wolf_few_resamplescodes. Use Holm when a valid joint bootstrap family is unavailable.simes_p(p_values): Simes (1986) global-null p-value for a group of tests —min_k (m / k) * p_((k)). Valid under independence and positive regression dependence on a subset (PRDS); the default group representative in hierarchical FDR.partial_conjunction_p(p_values, *, min_pass): Benjamini-Heller (2008) partial conjunction p-value for "at leastmin_passof themalternatives are true" —min(1, (m - min_pass + 1) * p_((min_pass))).stationary_bootstrap_resamples(values, n_resamples, ...): Politis-Romano (1994) bootstrap resamples. An aligned(T, m)per-period statistic matrix is resampled with common row indices and returns(B, T, m), preserving cross-hypothesis dependence for Romano-Wolf; separate per-column calls do not.bootstrap_mean_ci(values, *, n_resamples, ci, ...): Stationary-bootstrap CI for a statistic.
Holm and BHY adjust p-values as supplied; they neither validate nor repair
producer calibration. The caller must decide whether warning-coded results are
suitable for the declared family. A family may contain a documented mix of
two-sided, greater, and less alternatives because the procedures do not
reinterpret tails. Factrix provides no generic tail-conversion helper because
that conversion depends on the producer's null distribution and contract.
romano_wolf_adjusted_p remains an expert primitive: the caller must provide
the complete joint, H0-centred, correctly studentized (B, m) matrix. Factrix
does not currently expose a multi_factor.romano_wolf or panel-aware bootstrap
workflow; use Holm unless that joint bootstrap contract is available.