Skip to content
Skip to content
← all research
REJECTED

"Edge-Hunting Research Paper: Equities & Crypto"

2026-08-26

·

Date: 2026-08-25 Scope: Systematic search for tradeable anomalies across equity and crypto daily/intraday data, following the repository house protocol (fixed IS/OOS splits, Monte-Carlo gauntlet for winners, one ledger entry per idea adopted or rejected). Status: 1 validated edge (long-only momentum), ~15 rejected/retracted.


#Abstract

We ran a multi-round research program testing ~20 trading-edge hypotheses across equities (S&P 500 constituents, sector ETFs, crypto) and intraday (SPY/QQQ 1-minute) data. Every originally "validated" edge was subsequently invalidated by methodological bugs — and in the final round we discovered the bugs were deeper than first thought:

  • A timezone bug (§1.4): all 1-minute bars are in UTC; naive local handling fabricated a spurious intraday "reversal" (and corrupted all intraday ORB work). After correction, no intraday edge survives.
  • A look-ahead bug (§1.5): daily cross-section studies gated an open-to- close (or same-day) return with a signal derived from close[t]. This inflated OOS Sharpe in four studies — mega-cap trend (3.65→1.06), sector rotation (3.30→0.97), crypto rotation (1.99→0.54), cross-asset momentum (3.19→1.04); all four RETRACTED.
  • A returns-construction bug (§1.6): the one study that survived the first two rounds — six-month cross-sectional momentum, reported OOS Sharpe 0.86–0.92 — actually used overlapping forward returns (a full H-day forward return booked as a daily return on every rebalance day, inflating the series ~H×) plus return clipping that masked the explosion. With a correct daily-rebalanced, look-ahead-free implementation the long-short momentum factor is flat/negative post-2015 (consistent with the well-documented post-2009 weakness of US equity momentum).

After all three corrections, built on a new test base (validation/framework.py

  • tests/test_research_framework.py with automated guards), the only genuine edge is LONG-ONLY momentum — buy the top decile of trailing-return winners, equal-weight, monthly rebalance, no shorting. OOS (2016–2024) gross Sharpe 1.44–1.69, bootstrap p < 0.001, robust across 3–12 month lookbacks and consistent in-sample. Crucially, the edge survives realistic transaction costs: on the full delisting-inclusive ~500-name universe with next-open execution and a liquidity-tiered cost (5/25/50 bps by $-volume), the net OOS Sharpe stays 1.19–1.31 (flat 10 bps: 1.23–1.38; even 50 bps: 1.06–1.22), all with OOS bootstrap p = 0.000. The long-short variant and everything else remain rejected.

The dominant lesson: any daily or intraday result with Sharpe > ~2 should be assumed buggy until proven otherwise — and even a "clean-looking" Sharpe ~1 deserves a returns-construction audit, not just a look-ahead check.


#1. Methodology

#1.1 Data

  • Equities (daily): ~500 _ADJ.parquet files (timestamp column + adj_close). Early studies used a PIT top-200 universe by 2007 liquidity; the final, decisive momentum study uses the full delisting-inclusive universe (all _ADJ with sufficient history) so dead stocks are included — excluding them biases the short leg (see §1.6).
  • Equities (intraday): SPY_1Min, QQQ_1Min, 9 sector ETFs (UTC, 2020-01-01 → 2025-12-30).
  • Crypto (daily): gate60 universe, 2025-01-01 onward.
  • VIX (intraday): unavailable from data provider (0 bars).

#1.2 House protocol

  1. Fixed IS/OOS split chosen before testing (2025-01-01 crypto, 2016-01-01 equity, 2024-01-01 intraday).
  2. Monte-Carlo gauntlet for any winner (bootstrap p on OOS mean return).
  3. One ledger entry per idea, adopted or rejected, in docs/ROADMAP.md.
  4. Fee-free assumption for intraday (user-confirmed commission-free trading); cost-sensitive where relevant.

#1.3 Statistics

  • Sharpe: mean(std) × √periods (365 intraday, 252 daily).
  • Bootstrap p: 10,000 resamples of OOS returns; p = P(resample mean ≥ observed mean). Reject null (no edge) at p < 0.05.
  • Profit Factor (PF): Σ wins / Σ losses.

#1.4 Critical correction — timezone

All 1-minute bars are stored in UTC. Early intraday studies used pd.to_datetime(...).dt.tz_localize(None), which left timestamps as naive UTC. Filtering hour == 9 then captured 4:00 AM EST (pre-market), not the 9:30 AM ET open. This produced a fictitious "reversal" with p = 0.002. Fix: dt.tz_convert("America/New_York") before any session windowing. After correction, every intraday effect failed OOS. All intraday reports written before the fix are retracted.

#1.5 Critical correction — look-ahead in daily cross-section studies

equity_mega_momentum.py and equity_sector_rotation.py originally defined the trend gate as close[t] > SMA200[t] & ROC60[t] > 0 and gated the open-to-close return close[t]/open[t] − 1 of the same day. Since the gate depends on close[t] (available only at the day's end), using it to select that day's open-to-close trade is look-ahead bias. The original OOS Sharpe (3.65 and 3.30) were artifacts of this. Fix: shift the signal by one day (gate = gate.shift(1)) and use close-to-close returns, matching the SPY benchmark. After correction both studies fail OOS (§2.2, §2.3). Any study reporting daily Sharpe > ~2 should be suspected of this bug.

#1.6 Critical correction — overlapping forward returns & return clipping

The long-short momentum study (equity_momentum_monthly.py) survived §1.4 and §1.5 but was still wrong in two subtle ways that artificially created a "validated" edge:

  1. Overlapping forward returns. Its daily portfolio return was the H-day forward return close[t+H]/close[t] − 1 booked on day t. With a daily-rebalanced portfolio this means H overlapping positions are each credited with a full H-day return, inflating the series by ~H×. This alone turns a modest factor into a Sharpe-20 monster (confirmed when the corrected framework first produced Sharpe 24–45 on the same data).
  2. Return clipping masking the explosion. The portfolio return was clipped to [−0.1, 0.1] and forward returns to [−0.5, 0.5], which bounded the inflation enough to land at a "plausible" Sharpe 0.86–0.92 — hiding the bug rather than removing it.

Correct construction (validation/framework.py::cross_section_portfolio):

  • daily return = close-to-close pct_change(1) of the held names;
  • position weights set every hold days from a signal shifted by lag ≥ 1, then sticky (forward-filled) for hold days — no forward return is ever reused;
  • dead/delisted names excluded from ranking and weights (renormalized so a dead name never silently zeros the opposite leg);
  • an automated assert_no_lookahead guard perturbs future closes and asserts past returns are unchanged.

With this, long-short 6-month momentum is flat/negative post-2015 (OOS Sharpe 0.15–0.44, not significant) — matching the academic finding that US equity momentum weakened after 2009. The long-only "buy winners" version, however, is a strong, robust edge (§2.1).


#2. Validated Edges (PASS)

#2.1 Long-Only Cross-Sectional Momentum ★ the one genuine edge

  • Setup (clean, validation/framework.py): full _ADJ universe (~500 equities, including delisted — no survivorship bias), rank by trailing L-day return, hold top decile long-only (no shorting), equal weight, rebalanced every H days, lag = 1. IS/OOS 2016-01-01.

  • Result (OOS 2016–2024):

    L(d)H(d)IS SharpeOOS SharpeOOS pVerdict
    63211.191.540.000PASS
    126211.041.690.000PASS
    189210.951.600.000PASS
    252210.811.590.000PASS
    126630.851.670.000PASS
    252630.721.440.000PASS
  • Insight: The edge is the long-only "buy past winners" effect. The long-short version (top minus bottom decile) is flat/negative post-2015 (OOS Sharpe 0.15–0.44, p 0.12–0.34 — REJECT), because the short leg stopped working in the post-2009 bull market. Dropping the short leg leaves a robust, tradeable long-equity portfolio with no leverage or shorting required. Robust across 3–12 month lookbacks and consistent in-sample (2007–2015).

  • Adoptability (liquid subset): on the top-100 names by listing persistence (a tradeable large-cap proxy) the long-only edge still gives OOS Sharpe 1.25, bootstrap p 0.0008 (ret +1065%, maxDD −41%) — so it is not an artifact of illiquid small-caps and is production-viable.

  • Realistic-cost validation (full universe, next-open fills): the discovery numbers above are gross / same-day-fill (slightly optimistic). validation/momentum_realistic.py re-runs the long-only top-10 of ~500 names with correct execution timing (trade after the signal, earn from next day) and turnover costs on a sensitivity grid + a liquidity-tiered cost. Turnover is heavy (~85% of gross per monthly rebalance ≈ 10×/yr notional) but the edge is so large it absorbs it:

    L(d)H(d)GrossNet@10Net@25Net@50TieredOOS Net@10 pOOS Tiered p
    63211.401.341.271.141.270.0000.000
    126211.401.371.311.221.310.0000.000
    189211.321.291.251.171.250.0000.000
    252211.251.231.191.131.190.0000.000
    126631.301.281.251.201.250.0000.000
    252631.121.111.091.061.090.0000.000

    A true top-decile run (top_k=50 of 501) gives net@10bps Sharpe 1.06 (OOS p 0.001) and tiered 0.98 (OOS p 0.001) — still decisively positive. Verdict: deployment-grade. Even the harshest stress (full universe, 50 bps, tiered) keeps net Sharpe ≥ 1.0 at p ≤ 0.001; the production sleeve runs on a lighter 101-name liquid universe, so its drag is lower still.

  • Report: reports/momentum_spectrum.md, reports/momentum_liquid.md, reports/momentum_realistic.md

Retraction note: the earlier "six-month momentum OOS Sharpe 0.86–0.92" (equity_momentum_monthly.py, §2.1 in prior drafts) was a measurement artifact of the §1.6 bugs, not a real edge. It is superseded by this long-only result.

#(superseded) Six-Month Long-Short Momentum — RETRACTED (returns-construction)

  • Original (buggy): PIT top-200, long-short top−bottom decile, OOS Sharpe 0.86–0.92, p ≤ 0.011.

  • Corrected (no overlapping returns, delisting-inclusive universe): the long-short factor is flat/negative post-2015 (OOS Sharpe 0.15–0.44, not significant). The original Sharpe was produced by overlapping forward returns

    • return clipping (§1.6). Verdict: REJECT — but the long-only variant (above) is the genuine, surviving edge.
  • Report: reports/equity_momentum_monthly.md

    SignalIS SharpeOOS SharpeOOS pVerdict
    mom6 (6m)0.870.860.011PASS
    mom6_2_7 (2–7m)0.100.920.007PASS
    mom12 (12m)1.790.470.102REJECT
    mom12_1_131.490.380.153REJECT
  • Insight: The factor zoo tested momentum on next-day returns and found nothing; with a 21-day holding period the edge emerges. 12-month momentum is crash-sensitive (2009/2020 rebounds hurt it) but intermediate 6-month momentum is robust in both IS (incl. 2008 GFC) and OOS.

  • Report: reports/equity_momentum_monthly.md

#2.2 Mega-Cap Trend Ranking ★ RETRACTED (look-ahead)

  • Original (buggy): Top-50 PIT universe, rank by SMA200-distance, hold top-k. Reported OOS Sharpe 3.65 vs SPY 0.96, p = 0.000.
  • Corrected (no look-ahead): with signal shifted 1 day and close-to-close returns, top-10 OOS Sharpe falls to 1.06 vs SPY 0.96, bootstrap p = 0.161 (not significant). IS top-5 actually loses (−6%, Sharpe 0.11). Verdict: REJECT — the original edge was a look-ahead artifact (§1.5).
  • Report: reports/equity_mega_momentum.md

#2.3 Sector Rotation ★ RETRACTED (look-ahead)

  • Original (buggy): Top-3 GICS sectors by median SMA200-distance. Reported OOS Sharpe 3.30 vs all-sector EW ~2.80, p = 0.000.
  • Corrected (no look-ahead): top-3 OOS Sharpe 0.97 vs SPY 0.95, bootstrap p = 0.351 (not significant). IS underperforms SPY (Sharpe 0.19 vs 0.41). Verdict: REJECT — look-ahead artifact (§1.5).
  • Report: reports/equity_sector_rotation.md

#2.4 Cross-Asset Crypto Rotation ★ RETRACTED (look-ahead)

  • Original (buggy): Top-2 crypto by SMA200-distance. OOS Sharpe 1.99 vs EW 1.67, p = 0.024.
  • Corrected (no look-ahead): with gate and score shifted 1 day, top-2 OOS Sharpe falls to 0.54 vs EW 0.37, bootstrap p = 0.241 (not significant); top-3 OOS Sharpe 0.42, p = 0.403. The original edge was a look-ahead artifact (§1.5). Verdict: REJECT.
  • Report: reports/cross_section_rotation.md

#2.5 Cross-Asset Momentum ★ RETRACTED (look-ahead)

  • Original (buggy): Multi-asset (stocks+crypto+SPY) momentum, top-5 OOS Sharpe 3.19 vs SPY 0.53, p = 0.000.
  • Corrected (no look-ahead): with signal shifted 1 day + close-to-close returns, top-5 OOS Sharpe falls to 1.04 vs SPY 0.96, bootstrap p = 0.084 (not significant). The original edge was a look-ahead artifact (§1.5). Verdict: REJECT — and it never added alpha beyond equities anyway.
  • Report: reports/cross_asset_momentum.md

#3. Rejected Hypotheses (REJECT)

#3.1 Intraday Opening Range Breakout (ORB)

  • Symmetric (long up + short down): OOS Sharpe 0.11, p = 0.437. Down-breakouts lose (price reverses up after a breakdown — bull-market dip-buying).
  • Long-only up-breakout: OOS annualized Sharpe 0.80–0.97 (baseline 0.80, +wide-ORB 0.97, +gap-up 0.87) — a real economic signal, but daily Sharpe only 0.042 with kurtosis 36.5 (one +8.2% outlier day) → bootstrap p ≈ 0.20, normal p ≈ 0.40. Not statistically robust on 2y OOS.
  • "Clean" breakouts show Sharpe 18.7 but are not tradeable (only knowable at end of day).
  • Verdict: Not adoptable standalone. Candidate satellite or overlay on a stronger edge.
  • Reports: reports/intraday_orb.md, reports/intraday_orb_v2.md

#3.2 Equity Factor Zoo — Round 2 (orthogonal factors, beta-audited)

A second, more rigorous hunt (validation/edge_hunt2.py + validation/edge_audit.py) tested factors deliberately orthogonal to momentum on the audited framework (lag≥1, next-open, dead-stock-safe), IS/OOS 2016-01-01. The long-only versions posted tempting gross OOS Sharpe (ST-reversal 1.11–1.17, low-vol 0.99–1.14, liquidity-trend 1.35, all p≤0.003) — but a beta/residual audit exposed them as pure equity beta: every factor has market-neutral residual Sharpe ≈ 0 and Beta ≈ 1, and the long-short existence test is negative everywhere (ST-reversal LS −0.05, low-vol LS −1.07, liquidity-trend LS −0.09; Momentum LS 0.10). There is no new independent, deployable factor here — these are the same long-equity beta as momentum, just re-labeled. Earlier 1-day factor-zoo results (rev1m/w, high52, size) also REJECT; vol60/beta60 "PASS" only as risk premiums.

  • Reports: reports/edge_hunt2.md, reports/edge_audit.md

#3.3 Low-Volatility Anomaly

  • Round 2: long-only low-vol decile gross OOS Sharpe 0.99–1.14 (p 0.001–0.003) — but residual Sharpe ≈ 0 (Beta 0.6) and the long-short version loses (OOS Sharpe −1.07). Classic low-vol premium is absent in this universe/sample; the long-only number was beta.
  • Reports: validation/equity_low_vol.py, reports/edge_audit.md

#3.4 Vol-Regime / Shock-Day / Pullback overlays

  • All REJECT — no improvement over baseline on OOS.
  • Reports: validation/equity_vol_regime.py, validation/equity_shock_day.py, validation/equity_pullback.py

#3.5 Overnight / Turn-of-Month (TOM) — Round 2

  • Re-tested on correct NY-local 1-minute data (2020–2025, split 2022-01-01): SPY overnight-only OOS Sharpe 0.58 (p 0.16); turn-of-month OOS Sharpe 0.12 (p 0.43); pairs SPY~QQQ z-score OOS Sharpe 0.12 (p 0.43). All REJECT (not significant). The overnight effect that is famous in pre-2000 data does not survive here.

#3.6 Intraday Reversal (RETRACTED)

  • Original "last-15min reverses the morning" finding (p = 0.002) was an artifact of the timezone bug (Section 1.4). After correction, no intraday edge survives (gap-fill p = 0.834, Monday p = 0.695, momentum p = 0.558, combined p = 0.685).
  • Report: reports/intraday_real_effects.md

#4. Key Lessons

  1. Timezone is everything for intraday. UTC storage + naive local handling fabricated a "significant" edge. Always tz_convert("America/New_York").
  2. Look-ahead is the silent killer of daily studies. A gate/score that uses close[t] cannot select day t's open-to-close trade. All four cross-section daily studies contained this bug — mega-cap (3.65→1.06), sector (3.30→0.97), crypto rotation (1.99→0.54), cross-asset momentum (3.19→1.04) — and every one collapsed to ~1.0 / non-significant after the fix. Any daily Sharpe > ~2 deserves immediate suspicion.
  3. Horizon matters. Momentum is invisible at 1-day holding but strong at 21-day. Test the economically-motivated holding period, not the most convenient one.
  4. Asymmetry is informative. ORB up-breakouts work, down-breakouts fail — a bull-market signature, not a genuine breakout pattern.
  5. Fat tails kill significance. A strategy can show annualized Sharpe 0.97 yet have p = 0.20 because one outlier day dominates. Bootstrap p (not normal t-test) is the honest gate.
  6. Equities >> crypto for cross-section. Every multi-asset winner is equity-dominated; crypto adds volatility, not alpha.
  7. Risk premiums ≠ anomalies. vol60/beta60 "pass" but are compensation for risk, not exploitable inefficiencies.
  8. Three bugs invalidated every "high-Sharpe" result. Timezone, look-ahead, and overlapping-returns/clipping between them accounted for all results with Sharpe > 2 — including the "surviving" six-month long-short momentum, which collapsed once its returns were constructed correctly. The one edge that survived all three audits is modest (OOS Sharpe ~1.5) — exactly what a real, tradeable edge looks like.
  9. A clean look-ahead check is necessary but not sufficient. The long-short momentum study passed the §1.5 fix yet was still broken by overlapping forward returns. Audit the construction of the return series itself, not just the signal/trade alignment.
  10. Long-only can rescue a dead long-short factor. Momentum's short leg stopped working post-2009, but the long-only "buy winners" portfolio is robust (OOS Sharpe 1.4–1.7). Dropping an unprofitable, costly short leg is a legitimate edge-refinement, not data-snooping.
  11. A long-only Sharpe ~1 in 2016–2025 is usually just beta — audit it. Round 2 showed short-term-reversal, low-vol, and liquidity-trend all posted OOS Sharpe ~1.0–1.4, yet every one had market-neutral residual Sharpe ≈ 0 and Beta ≈ 1, and long-short existence tests were ~0 or negative. The lesson now enforced in the framework workflow: before claiming any long-only factor, regress its returns on an equal-weight market benchmark; require residual Sharpe > 0 AND low correlation to existing factors. A factor that is only beta is not a new edge and will not diversify a book.

#5. Conclusion — What Actually Works

EdgeOOS SharpepStatus
Long-only momentum (buy winners)1.44–1.69< 0.001PASS (equity cross-section, tradeable)
Six-month long-short momentum0.86–0.92 → 0.15–0.440.007 → 0.12–0.34RETRACTED (returns-construction)
Long-only ORB0.80–0.97~0.20borderline (intraday)
Mega-cap trend3.65 → 1.060.000 → 0.161RETRACTED (look-ahead)
Sector rotation3.30 → 0.970.000 → 0.351RETRACTED (look-ahead)
Crypto rotation1.99 → 0.540.024 → 0.241RETRACTED (look-ahead)
Cross-asset momentum3.19 → 1.040.000 → 0.084RETRACTED (look-ahead)

The single adoptable edge is LONG-ONLY cross-sectional equity momentum — buy the top decile of trailing-return winners, equal-weight, monthly rebalance, no shorting (OOS Sharpe 1.44–1.69, bootstrap p < 0.001, robust across 3–12 month lookbacks and consistent in-sample 2007–2015). It is built on the audited validation/framework.py primitives. Retracted: the earlier six-month long-short momentum (a returns-construction artifact); mega-cap trend, sector rotation, crypto rotation, cross-asset momentum (look-ahead artifacts); the entire intraday family (timezone artifact); factor-zoo 1-day; low-vol; regime/shock/pullback overlays. Borderline: long-only intraday ORB (satellite only, not statistically robust).

Recommended next step: productionize the long-only momentum edge (with transaction-cost modeling for small-cap names, since the universe is delisting-inclusive and includes illiquid issues) as the single approved strategy. Do not build on any retracted signal — they were statistical ghosts created by the three bugs above.


#6. References

  • reports/momentum_spectrum.md — §2.1 (the genuine edge)
  • reports/equity_momentum_monthly.md — §2.1 retraction (returns-construction)
  • reports/equity_mega_momentum.md — §2.2
  • reports/equity_sector_rotation.md — §2.3
  • validation/cross_section_rotation.py — §2.4
  • reports/cross_asset_momentum.md — §2.5
  • reports/intraday_orb.md, reports/intraday_orb_v2.md — §3.1
  • reports/equity_factor_zoo.md — §3.2
  • validation/equity_low_vol.py — §3.3
  • reports/intraday_real_effects.md — §3.6 (retraction)
  • validation/framework.py + tests/test_research_framework.py — the test base
  • docs/ROADMAP.md — full rejection ledger

All trading described is paper (simulated). Not investment advice.

← all research