feat(factors): reproduce minute ideal-amplitude factor + eval run (PR-D) - #64
Merged
Merged
Conversation
Kaiyuan report §30 分钟理想振幅因子: pool the 1min bars of a symbol's trailing N=10 trading days (PIT-truncated at 14:50 per bar via the I3 filter path), rank the pooled minutes by RAW close, and return V_high - V_low where V_high/V_low are the mean per-minute amplitude (high/low - 1) of the top / bottom floor(0.25*n) minutes by close. >= 1150 valid pooled minutes required else NaN (honest missing). - data/clean/intraday_amplitude.py: compute_minute_ideal_amplitude + LOCKED definition constants (N=10, lambda=0.25, min_minutes=1150). Pure, per-symbol isolated, never touches a forward return; ranking tie-break (close, bar_end) is a deterministic total order. - factors/compute/intraday_derived.py: additive MinuteIdealAmplitudeFactor (column-select, is_intraday=False daily close-to-close, expected_ic_sign=-1 pre-registered). - tests: hand-computed formula (n=4/n=8/two-day pool), 14:50 PIT truncation + post-cutoff perturbation invariance, trailing-window drop, min_minutes gate, deterministic tie-break, per-symbol isolation, amplitude guards, empty/no-mutate, spec validity, bad-params.
…PR-D) Second real StandardFactorEvaluator run, mirroring PR-C. Cache-only per-symbol minute aggregation -> raw -> process -> two evaluations (no-book / with-book value book) with md/json/dashboard outputs. Eval cell IDENTICAL to PR-C (CSI500 000905.SH, 2021-07-01..2026-06-30, OOS split 2024-01-01, book value_ep/value_bp/volatility_20, fee 0.001); the only substantive difference is the subject factor, computed by the runner from the intraday cache (not a config-listed daily factor). - qt/eval_minute_ideal_amplitude.py: cache-only minute loader (stk_mins live calls provably 0), evaluate_two_runs, metric extraction, honest EvalConfig provenance. - qt/cli.py: run-eval-minute-ideal-amplitude subcommand. - config/phase_d_minute_ideal_amp.yaml: PR-D eval config. - tests: cache-only loader (discloses empty, blocks when nothing cached), two-run evaluation core with dashboard PNGs, no-book never-Adopt structural guarantee.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reproduce the minute ideal amplitude factor from Kaiyuan Securities market-microstructure series #30 (2025-08-09) as the second report-reproduction factor (PR-D, loop 1/10), mirroring the accepted PR-C (jump_amount_corr) machinery end to end.
Factor
minute_ideal_amp_10: pool the trailing N=10 trading days of 1min bars (PIT-filteredavailable_time <= d 14:50BEFORE aggregation), per-bar amplitude = high/low − 1 (guards low>0, high>=low), require pooled n>=1150 else NaN, rank by raw minute close ((close, bar_end) tie-break), k=floor(0.25n); factor = mean(amp of top-k closes) − mean(amp of bottom-k closes). Pre-registered sign −1 (report: full-market IC −0.059 / ICIR −3.1). Daily signal traded close-to-close (is_intraday=False, same rationale as PR-C).Components (all additive; frozen
analytics/evaluntouched):data/clean/intraday_amplitude.py(new, 200L) ·MinuteIdealAmplitudeFactorinfactors/compute/intraday_derived.py· runnerqt/eval_minute_ideal_amplitude.py+ CLI subcommand ·config/phase_d_minute_ideal_amp.yaml(only substantive diff vs phase_c: the factor) · 23 new tests (hand-computed values, post-14:50 perturbation leakage tests, cross-symbol isolation, tie determinism, NaN gate, cache-only loader, two-run runner + dashboards).Real run (CSI500 2021-07..2026-06, OOS split 2024-01-01, cache-only minutes: covered=995/996, stk_mins_live_calls=0, 486.6s): IC mean −0.02915, ICIR −0.4644, NW-t −16.33, N_eff 1205, IC win rate 0.687. Verdict Watch / Watch (exploratory cap): Predictive PASS (sign held both OOS subperiods); Incremental PASS vs value_ep/value_bp/volatility_20 book (orth. ICIR lower CI +0.195 > 0.15); Tradable NOT_ASSESSED. Prototype sanity pre-run: mean daily RankIC −0.0236 (sign matched pre-registration). Not a return/deployment claim.
Test plan