ID: S001
Slug: 52w-high-volume-confirm-v1
Failed at: Stage 1 (Quick-screen)
Fail reason: magnitude
Date: 2026-05-29
What we tested
The setup combines two old ideas. The first is that stocks at fresh 52-week highs tend to keep climbing (academic literature going back to George & Hwang 2004). The second is that adding a volume filter — only counting breakouts where the trading volume is well above average — should separate real institutional buying from random retail noise.
We required the close to be within 0.5% of the trailing 52-week high, combined with volume at least 1.8× the 50-day average. We then held each trade for 20 trading days (roughly one month) and compared the return to a matched random sample of stocks drawn from the same universe in the same month, to control for general market drift.
The pre-set criterion we wrote down before running: the trades needed to average at least +1.2% over 20 days, hit rate at least 56%, the effect had to be statistically significant (Welch p < 0.05), and needed to hold up in both the 2010-2017 and 2018-2026 halves of the sample.
What we found
Strategy failed on most criteria. The result is essentially "no effect, possibly slightly negative."
| Criterion | We needed | We got | |
|---|---|---|---|
| Average 20-day return | ≥ +1.2% | +0.75% | ✗ |
| Signal beats matched random baseline | yes | +0.75% vs +0.95% baseline | ✗ |
| Hit rate (positive return) | ≥ 56% | 55.4% | ✗ |
| Number of trade signals | ≥ 200 | 3,109 | ✓ |
| Statistical significance (Welch t-test) | p < 0.05 | p = 0.33 | ✗ |
| Effect in both 2010-2017 and 2018-2026 halves | both ≥ +1.2% mean | h1 +0.95%, h2 +0.55% | ✗ |
The two numbers that matter most: the signal didn't beat its random baseline (the breakouts didn't outperform a random draw of stocks on the same days), and the difference is well within statistical noise. With over 3,000 trades, this is a clean negative result, not a borderline call.
Why this matters / what surprised us
The volume filter didn't help, and may have actively hurt. Our intuition was that 1.8× volume separates big-institution accumulation from low-conviction retail. In a universe of liquid mega-caps, that intuition breaks: high volume on a new-high day is often the distribution event — institutions selling into retail buyers who chase the breakout. The filter selects exactly the moments when smart money is exiting at the highs, not entering.
The result aligns with what's known about classic momentum. The 52-week-high effect is one of the most-studied anomalies in equity markets, which also makes it one of the most-arbitraged. By 2026, any naive "buy new highs" strategy in liquid US stocks has been front-run to death by hedge funds, market-makers, and the systematic crowd.
The 2018-2026 sub-period was weaker than 2010-2017 (+0.55% vs +0.95%). This is consistent with the broader literature on post-2010 momentum decay, but in our case neither half was strong enough to clear the bar anyway.
What this doesn't tell us yet
- We tested a specific operationalisation, not the broad concept. A different volume threshold (1.2× instead of 1.8×), a different distance-from-high (0.1% instead of 0.5%), or a different holding period (5 days instead of 20) might produce different results. We chose one specific configuration up front, on purpose — testing many configurations and reporting the best would be cheating.
- We tested on the S&P 500 + NASDAQ-100 (large-caps). Less liquid small-caps may show different behaviour around 52-week highs because the institutional-exit dynamic is weaker there. That would be a separate setup to pre-register.
- We didn't combine this signal with anything else. Combined with stops, sector filters, or earnings overlays the result might differ. But those would be different strategies, not rescues of this one.
What happens next
This specific setup is closed. The relevant lessons for future breakout-style strategies:
- Volume filters in liquid universes can select for the wrong moment (distribution rather than accumulation). A breakout strategy that works in this universe probably needs something else — perhaps a pullback after the initial breakout, a tighter time-window, or a small-cap focus where the institutional dynamic differs.
- Pre-registered gates work as intended: this setup ran, the numbers came in, and there was no temptation to declare partial victory or sweep parameters until something passed. The discipline is what makes the failure credible.
For the specialist — methodology details (click to expand)
Setup (verbatim from spec)
Stocks closing within 0.5% of the trailing 52-week high accompanied by daily volume ≥ 1.8× the 50-day average predict positive 20-day forward returns above the universe median in the liquid US equity universe (top 2,000 by dollar volume) over 2010-present.
Test setup
- Universe: monthly point-in-time top-200 from the SP500+NDX candidate pool (~516 names), reconstructed from the index membership as it stood on each historical date (not as it stands today — this prevents survivorship bias).
- Data: Tiingo Power EOD, 2010-01-04 → 2026-05-28, 1.98M bars.
- Signal:
close[t] ≥ 0.995 × max(close[t-252:t-1])ANDvolume[t] ≥ 1.8 × mean(volume[t-50:t-1]). Both rolling windows use.shift(1)to enforce trailing-only computation (the bar of day t itself never appears in the window). - Dedupe: per ticker, max 1 signal per 20 trading days.
- Forward measure:
(close[t+21] − open[t+1]) / open[t+1]— buy the day after the signal at the open, exit 20 trading days later at the close. - Baseline: for each signal event, 5 matched random (ticker, date) pairs drawn from the eligible universe that month. Baseline mean absorbs market-wide drift in the same period.
Pre-registered gate (all required)
mean_20d_return ≥ +1.2%
mean_vs_baseline signal > matched random
hit_rate ≥ 56%
n_trades_min ≥ 200 (post-dedupe)
sharpe_annualised > 0.8 (× √(252/20))
max_drawdown < 30% on cumulative trade-return curve
half1_mean ≥ +1.2% (2010-2017)
half2_mean ≥ +1.2% (2018-present)
half1_hit ≥ 56%
half2_hit ≥ 56%
welch_p_value < 0.05 (signal vs baseline)
bootstrap_95pct_ci lower bound > 0
Detailed numbers
- Mean 20d return: +0.752% (signal) vs +0.945% (baseline) → diff −0.193pp
- Sharpe annualised: 0.27 (gate > 0.8)
- Welch t-test on signal vs baseline: p = 0.331
- Bootstrap 95% CI on the mean difference: [−0.582%, +0.166%] — straddles zero, confirming no significant edge
- Half-1 (2010-2017): mean +0.947%, hit 56.9% (hit-rate gate alone passed)
- Half-2 (2018-2026): mean +0.549%, hit 53.8% (both gates failed)
- Max drawdown of cumprod curve hit 100% — note this metric is misleading at this sample size; it isn't the reason for the cut, the Welch p-value and baseline-comparison are
Artifacts
- Trades:
lab/postmortem/52w-high-volume-confirm-v1/trades.parquet(3,109 rows: ticker, signal_date, entry/exit prices, ret_20d) - Matched baseline:
lab/postmortem/52w-high-volume-confirm-v1/baseline.parquet(15,541 rows) - Histogram bins:
chart_data.jsonin same directory - Setup spec:
lab/setups/52w-high-volume-confirm-v1.md - Pre-registered gate:
lab/setups/gates.md§52w-high-volume-confirm-v1
Rewritten 2026-05-30 for broader accessibility. No claims, gates, or methodology changed — only presentation.