Skip to content

Warning codes

Structured WarningCode payloads attached to every EvaluationResult.warnings. Use these as the SSOT when you need to filter, route, or trigger downstream behaviour from factrix output without parsing free-text strings.

  • WarningCode — risk flags surfaced on EvaluationResult.warnings. Does not affect MetricResult.p_value; the user decides whether to pre-filter on warnings before multi-factor Benjamini-Hochberg-Yekutieli (BHY).

Each member's trigger / meaning is sourced from factrix._codes.WarningCode.description (single source of truth, also surfaced at runtime on each result's warnings). For the per-procedure breakdown of which codes a given pipeline can emit, see Architecture § Procedure pipelines.

The scalar statistics that populate EvaluationResult.metrics are not enum-keyed — each MetricResult exposes its statistic on MetricResult.stat with stat_type / h0 / method in MetricResult.metadata; see Stat keys by metric.

WarningCode

WarningCode Trigger / meaning
unreliable_se_short_periods n_periods is below the WARN floor (~30); NW HAC SE may be biased. Reused across panel time-series guards (MIN_PERIODS_WARN) and primitive inference (MIN_FM_PERIODS_WARN); both default to 30.
event_window_overlap Adjacent events sit within forward_periods; AR windows overlap.
persistent_regressor ADF p exceeds the configured threshold on the continuous factor; beta may carry Stambaugh bias.
serial_correlation_detected Ljung-Box p < 0.05 on residuals; NW lag may be under-set.
few_assets Cross-section asset count is below the relevant WARN floor (panel-wide MIN_ASSETS_WARN=30, per-date MIN_IC_ASSETS_WARN=10, or per-date MIN_FM_ASSETS_WARN=10). The statistic is returned, but small n_assets inflates critical values or leaves minimal residual degrees of freedom. Severity scales with n_assets; read the relevant n_assets metadata. A by-design few-asset study declares the regime once via evaluate(..., expected_warnings=('few_assets',)): the record is kept and marked expected=True, and the per-run UserWarning echo stops.
thin_quantile_groups quantile_spread with the median cross-section split into n_groups buckets leaving < MIN_GROUP_ASSETS (5) assets per bucket; each bucket mean rests on a handful of names so the spread can be dominated by individual assets. Advisory only — reduce n_groups (the warning suggests a value) or treat the spread as a fragile small-cross-section diagnostic. Distinct from few_assets, which keys off the absolute cross-section size.
sparse_magnitude_weighted Sparse factor column is mixed-sign and not a clean ±1 ternary; statistic is magnitude-weighted (Sefcik-Thompson) rather than textbook MacKinlay signed CAAR — apply .sign() before calling for sign-flip semantics.
few_events CAAR significance test with MIN_EVENTS_HARD ≤ n_event_periods < MIN_EVENTS_WARN (4..29). caar is an equal-weight calendar-time portfolio across event periods, so this counts the number of periods with an event, not events; a sub-30 series is power-thin for the asymptotic t-distribution — read borderline p-values cautiously.
borderline_portfolio_periods top_concentration with MIN_PORTFOLIO_PERIODS_HARD ≤ n_periods < MIN_PORTFOLIO_PERIODS_WARN (3..19); one-sided t-test on the per-date diversification ratio is returned but df=n-1 inflates t_crit relative to the asymptotic cutoff.
few_directional_pairs directional_hit_rate with MIN_DIRECTIONAL_PAIRS_HARD ≤ n_pairs < MIN_DIRECTIONAL_PAIRS_WARN (10..29); the Pesaran-Timmermann hit rate is returned but n counts pooled non-overlapping (date, asset) directional trials, and the normal approximation to S_n is power-thin below ~30 pooled pairs — read borderline p-values cautiously. Below the HARD floor the metric short-circuits to NaN.
few_ordering_pairs directional_pair_accuracy with MIN_PAIR_ACCURACY_PAIRS_HARD ≤ n_pairs < MIN_PAIR_ACCURACY_PAIRS_WARN (10..29); the descriptive ordering accuracy is returned but n counts pooled non-overlapping within-date asset pairs after factor/return ties are removed. Below the HARD floor the metric short-circuits to NaN.
rect_kernel_negative_variance Rectangular-kernel HAC variance-of-mean came out negative (no PSD guarantee, Andrews 1991); clamped to 0 → SE=0, t=0, p=1.0. Fires only on short / mildly anti-correlated samples.
bmp_return_vol_fallback bmp_z ran without a price column: the estimation-window volatility falls back to the per-asset rolling std of forward_return, lagged by forward_periods so it ends before the event's forward window. This is a coarser, horizon-overlapping vol proxy than a daily-price std — supply price for the clean BMP standardiser.
upstream_unavailable DAG-executor consumer skipped because an upstream producer short-circuited. The downstream MetricResult carries metadata['upstream'] / ['upstream_reason'] for the original cause.
metric_unavailable Metric short-circuited on its own precondition (missing input column / config, or insufficient sample at its own floor); the NaN MetricResult's metadata['reason'] carries the specific cause. Distinct from UPSTREAM_UNAVAILABLE, which flags a dependency failure.
structure_mismatch Metric's declared factor cell (scope / density / data structure) does not match the detected factor cell; under strict=False the metric short-circuits to NaN instead of executing.
low_cardinality_dense_signal Dense factor has few distinct non-null values but no sparse event contract. Sparse event metrics require the {0, R} zero-value event contract and a sparse_ratio above the routing threshold; always-in-market states such as {-1, +1} stay dense and should use dense / directional metrics.
frequent_event_signal Sparse event metric explicitly ran on a factor with zero-valued rows but sparse_ratio below the automatic SPARSE routing threshold. The metric treats zeros as non-events; confirm that zero encodes the intended event contract. Events are frequent, so read event-study inference cautiously and inspect clustering / overlap diagnostics.
cross_factor_density_mismatch Factor columns carry inconsistent FactorDensity (dense and sparse mixed).
cross_factor_scope_mismatch Factor columns carry inconsistent FactorScope (individual and common mixed).
single_asset_event_data Single-asset event-shaped data (TIMESERIES + SPARSE, n_assets=1): event-axis metrics run over the event cross-section (n_events) and are usable on a single name. Metrics that need the asset cross-section — same-date event clustering (clustering_hhi) is degenerate at one event per date — need n_assets>=2 and are unavailable. Do not pool unrelated assets to clear this; that mixes return-generating processes.
excessive_period_drops An upstream PANEL→SERIES primitive dropped more than DROP_RATE_WARN_THRESHOLD of dates at its cross-sectional filter; the metric was computed on a shortened sample. Exact counts are in MetricResult.metadata (n_periods_in / n_periods_out / dropped_periods / drop_rate / drop_reason).
excessive_asset_drops An upstream primitive dropped more than DROP_RATE_WARN_THRESHOLD of assets at its per-asset filter (e.g. compute_common_betas dropping assets with insufficient history or zero factor variance); the cross-asset aggregate was computed on a shortened sample. Exact counts are in MetricResult.metadata (n_assets_in / n_assets_out / dropped_assets / drop_rate / drop_reason).
slice_boundary_truncation by_slice partitioned a panel on a date-axis column (one whose value varies within an asset over time, e.g. calendar year or regime label) while the metric declares MetricSpec.slice_boundary_sensitive (a capability of the estimator, not inferred from its aggregation category). Each slice is evaluated on its own rows, so a rolling window / per-asset time-series regression / event window sees truncated history at the slice boundary — the per-slice value differs from the full-sample value decomposed by period. Metrics that don't declare the flag and cross-sectional partitions (constant within an asset, e.g. sector) are unaffected and do not trigger.

Bases: StrEnum

Procedure-degradation flags.

Each value carries a one-line description gloss used by API docs, MetricResult.warning_codes, and EvaluationResult.warnings.