Signal-shuffle cross-sectional null
Permutes signal values inside each rebalance cross-section. It preserves the return environment and breaks only the proposed signal-to-return alignment.
SignalResearcher proposed six economically motivated alpha candidates. One survivor — vol_adj_reversal — passed all pre-registered gates and entered the traded book with IC weight 0.462. Five were rejected. The gates have teeth: LLM output is not rubber-stamped into the strategy registry.
The pre-registered validation stack used two nulls - a signal-shuffle cross-sectional null and a block-bootstrap time-ordering null - plus a Bonferroni correction that splits the family-wise alpha across the candidate batch (each null threshold estimated from 1,000 resampling draws) and an internal holdout. The 2013-2015 OOS window remained untouched.
proposed_signals.json failed schema validation
✖ Invalid input: expected object, received undefined → at proposals[2].validation.discovery ✖ Invalid input: expected object, received undefined → at proposals[2].validation.synthetic_null ✖ Invalid input: expected object, received undefined → at proposals[2].validation.signal_shuffle_null ✖ Invalid input: expected object, received undefined → at proposals[2].validation.holdout ✖ Invalid input: expected object, received undefined → at proposals[3].validation.discovery ✖ Invalid input: expected object, received undefined → at proposals[3].validation.synthetic_null ✖ Invalid input: expected object, received undefined → at proposals[3].validation.signal_shuffle_null ✖ Invalid input: expected object, received undefined → at proposals[3].validation.holdout ✖ Invalid input: expected object, received undefined → at proposals[4].validation.discovery ✖ Invalid input: expected object, received undefined → at proposals[4].validation.synthetic_null ✖ Invalid input: expected object, received undefined → at proposals[4].validation.signal_shuffle_null ✖ Invalid input: expected object, received undefined → at proposals[4].validation.holdout
Candidates proposed
6
Candidates accepted
1
Null draws
N=1000
OOS contamination
0
Each row records the proposed economic mechanism and the gate outcome. One candidate survived; five were rejected.
| Name | Mechanism | Family | Reason | Gate | Threshold |
|---|---|---|---|---|---|
| vol_adj_reversal | Short-horizon reversal scaled by 21-day realized volatility: z_score(mean_reversion * rolling_std(ret(divAdjClose, 1), 21)). Survived with 0.462 IC weight. | volatility-adjusted reversal | Passed all pre-registered gates; admitted to the traded book with IC weight 0.462. | survived | signal-shuffle + block-bootstrap + holdout |
| liq_screen_reversal | Plain mean-reversion signal (equivalent to the base mean_reversion factor without volatility scaling). | screened reversal | Rejected at the coverage gate: signal coverage was only ~20% of the universe (~122 names per rebalance), below the proposal-type threshold — it never reached the null tests. | failed | coverage screen |
| earnings_yield_norm | Earnings yield winsorized cross-sectionally: winsorize(safe_div(eps_diluted, close), 0.01, 0.99). | fundamental value | Rejected at formula validation: the winsorize function takes 2 arguments but the proposal passed 3, so it was rejected before any statistical test. | failed | DSL arity check |
| net_margin_quality | Net margin winsorized cross-sectionally: winsorize(safe_div(net_income, revenue), 0.01, 0.99). | quality | Rejected at formula validation: the winsorize function takes 2 arguments but the proposal passed 3, so it was rejected before any statistical test. | failed | DSL arity check |
| contrarian_short_mom | Short-window contrarian momentum: winsorize(-1.0 * z_score(ret(divAdjClose, 21)), 0.01, 0.99). | contrarian momentum | Rejected at formula validation: the winsorize function takes 2 arguments but the proposal passed 3, so it was rejected before any statistical test. | failed | DSL arity check |
| rev_mom_quality_blend | Composite: z_score(1.5 * mean_reversion - 1.0 * quality - 0.5 * value). Blends reversal with fundamental quality and value tilts. | multifactor composite | Rejected at the coverage gate: some monthly rebalances had fewer than 100 valid names (min 0), below the coverage threshold. | failed | coverage screen |
Permutes signal values inside each rebalance cross-section. It preserves the return environment and breaks only the proposed signal-to-return alignment.
Resamples time blocks to test whether the apparent IC survives disrupted ordering while preserving local time-series structure.
The family-wise alpha budget is split across the candidate batch, so a larger creative batch makes each individual gate harder to clear; each null threshold is estimated from 1,000 resampling draws.
Discovery-period creativity is checked against a separate 2011-2012 holdout before anything can reach the strategy registry.