Skip to content

Phase 9 — per-stock baseline + L47 bug + news audit

Phase 9 had two threads: a per-stock harness diagnostic (9.A) and a hand-audit of the news-channel anti-edge from L46 (9.B).

9.A — the L47 bug

_per_stock_zscore used sigma.clamp(min=1e-8) which blew up for warmup-period features (vol_60d ≈ 0 for the first 60 days → tiny std → 10^7+ z-scores). LayerNorm inside StrategyNet absorbed the scaling for the honest run (so it looked OK at -0.4 Sharpe) but DROWNED the cheat column (~1.0 scale) inside look_ahead_cheat_test. Plus _run_per_stock passed already-z-scored features to leakage tests, causing transform_fn to corrupt the head columns.

Both fixed:

  • clamp(min=1e-3) — keeps warmup-period z-scores in a sane range.
  • Pass RAW features to cheat tests inside _run_per_stock so the cheat columns travel through the standardisation as designed.

Post-fix: look_ahead_cheat = +30 (was -2.28). The harness is now trustworthy for per-stock evaluation.

9.B — the news-channel audit (L48)

Hand-walked the L46 anti-edge cluster from raw GDELT row → feature_engineering_v2 → model input. Findings:

  • corr(gkg_avg_tone_t, next_ret) = -0.0164 overall (N=25,795)
  • Strengthens to -0.11 at |tone| > 5 and |tone| > 8
  • Per-ticker mean correlation = -0.023 (median -0.021)
  • Sign-alignment at strong-tone cells (|tone| > 8): 44.4% (vs 50% noise)

No code bugfeature_engineering_v2 preserves sign, magnitude, and date alignment (Audit 2 + Audit 4). The L46 -3.4 Sharpe cluster was the model correctly extracting this weak contrarian signal, just at a magnitude too large to be honest at this sample size.

Conclusion: GDELT daily news on Indian large-caps is a weak contrarian signal, not momentum. Plausible mechanism: news reports react to returns rather than predict them — by the time GDELT indexes a story, the move has already happened, so the next day mean-reverts.

Practical implication: explicit -1 * tone features would produce honest Sharpe ~0.0-0.1 after costs, in the noise band. Not enough to be the project's edge, but a real signed finding worth preserving as a feature transform when news is used downstream.

What it produced

L47 (harness bug now closed) and L48 (the news channel characterised). The per-stock harness diagnostic also produced one of the two leakage-clean noise-band results documented on Best candidates: nifty_50_per_stock_momentum at Sharpe -0.51.

OpenBracket v0.6 — methodology release-ready; v1 forecaster in active build.