factrix.multi_factor.partial_conjunction_across_metrics ¶
partial_conjunction_across_metrics(results: list[EvaluationResult], *, metrics: list[str], min_pass: int, family_size: int | Mapping[tuple[Any, ...], int] | None = None, q: float = 0.05, inactive_policy: InactivePolicy = 'count') -> CrossMetricPartialConjunctionResult
Test whether each factor identity passes at least k of m metrics.
Metric labels are the predeclared condition axis. For each result, the
Bonferroni-style partial-conjunction p-value is computed across the fixed
m endpoints, then BHY runs across factor identities. Inactive
endpoints (a data-shortage short-circuit or a degenerate_variance
result) are governed by inactive_policy: under the default
"count" they stay in m at an inert p = 1; under
"exclude" submitted inactive endpoints leave m. Identities with
fewer than min_pass computed plus declared-unsubmitted endpoints remain
in the audit output but do not enter the outer BHY family. min_pass
must be declared before the p-values
are seen — (m - k + 1) * p_((k)) is not monotone in k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
results
|
list[EvaluationResult]
|
Unique :class: |
required |
metrics
|
list[str]
|
At least two unique, predeclared inferential metric labels. |
required |
min_pass
|
int
|
|
required |
family_size
|
int | Mapping[tuple[Any, ...], int] | None
|
Complete metric-endpoint family size per factor identity.
A scalar applies to every identity; a mapping declares
heterogeneous sizes keyed like the returned |
None
|
q
|
float
|
Nominal FDR target for BHY across factor identities. |
0.05
|
inactive_policy
|
InactivePolicy
|
|
'count'
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
CrossMetricPartialConjunctionResult
|
class: |
CrossMetricPartialConjunctionResult
|
survivors and the underlying metric hypotheses retained for audit. |
Raises:
| Type | Description |
|---|---|
UserInputError
|
Inputs, metric p-values, or |
When to use it¶
Use this procedure for a predeclared factor-level claim such as "the factor has signal on at least two of IC, beta, and spread." Metric labels are the fixed condition axis: each factor identity receives one k-of-m partial-conjunction p-value, followed by BHY across identities.
screen = fx.multi_factor.partial_conjunction_across_metrics(
results,
metrics=["ic", "beta", "spread"],
min_pass=2,
q=0.05,
)
screen.to_frame()
# factor | forward_periods | <sorted params> | pc_p | adj_p
# | survived | eligible | family_size | n_passed_uncorr
This differs from bhy_across_metrics: pooled BHY
selects factor × metric cells, while partial conjunction returns factor
identities supported by at least k endpoints.
Inactive endpoints and m¶
The declared metric list fixes the endpoints you may claim on. An inactive
endpoint (insufficient_* short-circuit or degenerate_variance) never ran a
test, and inactive_policy says whether it still counts toward the k-of-m
denominator — the same declaration every other screening function takes, so
the same degenerate cell costs the same whichever verb sees it. See inactive
candidates.
Under the default "count" the endpoint stays in m at an inert p = 1.
Under "exclude" it leaves m; if fewer than min_pass endpoints remain,
that identity cannot support the claim: it stays visible with eligible=False
and empty PC/adjusted p-values, and does not enter the outer BHY family. Either
way the endpoint stays in hypotheses for audit and family reports the
counts.
min_pass must be declared before the p-values are seen — (m - k + 1) *
p_(k) is not monotone in k (see
partial_conjunction).
Descriptive endpoints and other invalid p-values fail loudly. The function does
not implement min_pass=1 any-metric promotion.
Result fields¶
| Field | Meaning |
|---|---|
entries |
Every tested factor identity, in input order |
hypotheses |
Underlying result × metric cells retained for audit |
pc_p_all |
Raw k-of-m p-value per identity; NaN when fewer than k endpoints are active |
adj_p_all |
BHY-adjusted PC p-value per identity |
survivors / adj_p |
Passing factor identities and their adjusted p-values |
metrics / min_pass |
Declared m endpoints and required k |
family_size |
The k-of-m denominator m per identity, including declared-unsubmitted endpoints |
family |
Declared / computed / inactive / unsubmitted / adjusted endpoint counts and the inactive_policy used |
n_identities |
Identities entering the outer BHY family |
The frame's identity prefix is complete: same-named factors at different horizons or parameter settings remain separate rows.
factrix.multi_factor.CrossMetricPartialConjunctionResult
dataclass
¶
CrossMetricPartialConjunctionResult(entries: list[EvaluationResult], hypotheses: list[MetricHypothesis], adj_p_all: ndarray, pc_p_all: ndarray, q: float, metrics: tuple[str, ...], min_pass: int, family_size: Mapping[tuple[Any, ...], int], n_identities: int, n_passed_uncorr_all: ndarray, family: FamilyAccounting)
Bases: _ScreenResultMixin
Factor-level k-of-m metric confirmation followed by BHY.