Skip to content

feat(factors): reproduce volume peak-minute-count factor (PR-F, weak-positive Reject) - #66

Merged
StackOverFlow11 merged 2 commits into
mainfrom
feat/pr-f-volume-peak-count
Jul 20, 2026
Merged

feat(factors): reproduce volume peak-minute-count factor (PR-F, weak-positive Reject)#66
StackOverFlow11 merged 2 commits into
mainfrom
feat/pr-f-volume-peak-count

Conversation

@StackOverFlow11

Copy link
Copy Markdown
Owner

Summary

Reproduce the volume peak-minute-count factor — the flagship of Kaiyuan Securities market-microstructure series #27 (volume peak/ridge/valley, 2025-07-20) — as loop reproduction 3/10 (PR-F). Outcome: sign transferred (+1 as pre-registered) but strength fails the pre-registered ICIR gate → honest Reject on both runs. Not a documented-negative (unlike PR-E): the signal is real, monotone and statistically significant, just weak on our cell.

Factor volume_peak_count_20: per-minute-slot eruptive/mild classification vs the STRICTLY-PRIOR 20 same-slot days' μ+1σ (rolling+shift(1), day excluded from its own baseline; <10 obs unclassifiable); peak = eruptive bar whose exact ±60s same-session neighbours both exist and are mild (lunch break / missing minutes / session boundaries auto-break adjacency); factor = count of peak minutes over trailing 20 VALID days (valid = ≥100 classifiable bars; <10 valid days → NaN). PIT: available_time <= d 14:50 uniformly before everything. Pre-registered sign +1 (informed-trading participation; report: full-market RankIC +10.62%, CSI500-domain L/S +14.96%/yr).

Result (CSI500 2021-07..2026-06, cache-only minutes 995/996, stk_mins_live_calls=0, 439.5s): prototype RankIC +0.0333 (sign PASS) → full run IC +0.0177, ICIR 0.210 (CI [0.151, 0.270]), NW-t 7.43, win rate 0.591, Q1→Q5 monotonicity 0.90, aligned spread +1.79%/yr; incremental ICIR 0.111 (< 0.15 gate). Predictive FAIL (ICIR lower CI 0.151 < 0.30) → Reject / Reject. The gate thresholds are the contract's pre-registered defaults (flagged UNVALIDATED-BY-DATA in the design doc); the honest weak-positive is on the record.

Components (all additive; frozen analytics/eval untouched): data/clean/intraday_volume_prv.py (vectorized day×slot pivot + rolling/shift baseline) · VolumePeakCountFactor · runner qt/eval_volume_peak_count.py + CLI + config/phase_f_volume_peak_count.yaml · 26 new tests (hand-computed peak counts, strictly-prior-baseline invariance, cross-session non-adjacency, post-14:50 invariance, gates, cache-only loader, two-run + dashboards).

Test plan

  • Full pytest: 1314 passed (baseline 1287 + 27; zero baseline disturbed) — rerun independently by orchestrator
  • ruff clean; phase0 regression ic 0.9600 / annual 0.8408 unchanged
  • Independent code review: APPROVE (0 CRIT/HIGH; reviewer independently re-derived all hand-computed test values and inspected run artifacts; 2 LOW informational)
  • Secret scan: 0 token values in diff + artifacts; verdicts confirmed Reject/Reject from artifacts

Reproduce the Kaiyuan market-microstructure series #27 flagship volume-peak-minute-count
factor as a daily PIT-safe column derived directly from the 1min cache. New
data/clean/intraday_volume_prv.py::compute_volume_peak_count classifies every visible
minute against its same-slot STRICTLY-PRIOR 20-day baseline (eruptive if vol > mu + sigma
else mild) and counts the eruptive minutes whose both 1-minute same-session neighbours
are mild (peaks) over the trailing 20 valid days; ridge / session-boundary /
unclassifiable-neighbour minutes are not peaks. Vectorized per symbol via a day x slot
volume pivot (rolling over the day axis + shift(1) for the strictly-prior baseline) and a
within-day 60s-gap neighbour test, so no per-(day,slot) python loop and no cross-day or
cross-symbol leakage. Additive VolumePeakCountFactor mirrors the three prior
minute-derived factors (is_intraday=False, close_to_close, pre-registered sign +1).
Add run-eval-volume-peak-count: the fourth real factor evaluation. New
qt/eval_volume_peak_count.py runs VolumePeakCountFactor through the frozen
StandardFactorEvaluator on real cached CSI500 data (2021-07..2026-06, daily, OOS split
2024-01-01), cache-only (minute read is provably live-call-free), twice (no book /
value_ep+value_bp+volatility_20 book). CLI subcommand + config mirror the PR-C/D/E cell.

Real run (995/996 covered, stk_mins_live_calls=0, 279M raw 1min rows, ~7.3min): IC mean
+0.0177 (sign matches pre-registered +1), NW-t 7.43, win-rate 0.591, Q1->Q5 monotonicity
Spearman 0.90, aligned Q5-Q1 spread +1.79%/yr; but ICIR 0.21 (CI lower 0.151) is below the
default 0.3 bar, so the Predictive axis FAILs and the deployment verdict is Reject.
Incremental beyond the book is +0.0074 (ICIR 0.111, CI lower 0.054 < 0.15) -> also Reject.
A weak-but-positive daily-CSI500 signal that does not clear the (uncalibrated default)
deployment bar; the report's monthly full-market ICIR 4.36 is a loose reference only.
@StackOverFlow11
StackOverFlow11 merged commit ed47d7c into main Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant