Does Sell in May and Go Away Work?
Sell in May and Go Away, tested on two decades of S&P 500 seasons. See the size of the summer gap and what the seasonal switch actually costs in practice.
Sell in May and go away is the best known calendar rule in the stock market: sell at the end of April, sit in cash through the summer, buy back at the end of October. Measured on S&P 500 tracker prices from the last April 2005 close through the last April 2026 close, the November to April half of the year does average a higher return than the May to October half. The gap is real, and it is smaller than the saying implies. The summer half also averages a gain, which is where the rule breaks down as a plan.
What the rule says, and how you test it
The phrase comes from an old London habit of leaving town after the spring race meetings and returning in the autumn. In its modern, testable form it is a switching rule with two dates. You hold a broad stock index from the last trading day of October through the last trading day of April. You hold nothing for the other six months.
Testing it needs two things the adage never supplies: a price series and a stated window. Every number below uses SPY, the oldest S&P 500 exchange traded fund, priced from regular-hours minute bars in the global_markets.delayed_stocks_minute_aggs table, from the final April 2005 close through the final April 2026 close. A month's return here is its last regular-hours price against the prior month's, price only. Dividends get their own section further down, and how monthly returns are measured covers why that distinction changes the answer.
Does sell in May and go away work? The 2005 to 2026 record
The exact SQL behind every number
WITH monthly AS (
SELECT toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
argMax(close, window_start) AS month_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2005-04-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-04-30')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY month_start
)
SELECT toYear(apr_m.month_start) AS year,
round(100 * (toFloat64(oct_m.month_close) / toFloat64(apr_m.month_close) - 1), 2) AS may_oct_pct,
round(100 * (toFloat64(apr_next.month_close) / toFloat64(oct_m.month_close) - 1), 2) AS nov_apr_pct
FROM monthly AS apr_m
INNER JOIN monthly AS oct_m ON oct_m.month_start = addMonths(apr_m.month_start, 6)
INNER JOIN monthly AS apr_next ON apr_next.month_start = addMonths(apr_m.month_start, 12)
WHERE toMonth(apr_m.month_start) = 4
ORDER BY yearEach point pairs one summer with the winter that follows it. The chart holds 21 complete pairs, opening with the summer of 2005 and closing with the winter that ended in April 2026.
The two lines disagree in most individual years and agree in the worst one. Between the end of April and the end of October 2008 the summer half measured -29.81%, the deepest reading in the run. The winter that followed measured -10.03%. A holder who sold that April stepped out of a heavy fall and then stepped back in for the final leg down. The calendar and the damage lined up for only half the trip.
Has the summer gap faded since 2015?
Averages are what the adage is really claiming, and the window is what those averages rest on. Splitting the run at 2015 gives two halves of comparable length, computed the same way.
The exact SQL behind every number
WITH monthly AS (
SELECT toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
argMax(close, window_start) AS month_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2005-04-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-04-30')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY month_start
),
pairs AS (
SELECT toYear(apr_m.month_start) AS season_year,
toFloat64(oct_m.month_close) / toFloat64(apr_m.month_close) - 1 AS may_oct,
toFloat64(apr_next.month_close) / toFloat64(oct_m.month_close) - 1 AS nov_apr
FROM monthly AS apr_m
INNER JOIN monthly AS oct_m ON oct_m.month_start = addMonths(apr_m.month_start, 6)
INNER JOIN monthly AS apr_next ON apr_next.month_start = addMonths(apr_m.month_start, 12)
WHERE toMonth(apr_m.month_start) = 4
),
tagged AS (
SELECT may_oct,
nov_apr,
arrayJoin(['All seasons 2005-2025',
if(season_year <= 2014, 'First half 2005-2014', 'Second half 2015-2025')]) AS era
FROM pairs
)
SELECT era,
count() AS season_count,
round(100 * avg(may_oct), 2) AS avg_may_oct_pct,
round(100 * avg(nov_apr), 2) AS avg_nov_apr_pct,
round(100 * (avg(nov_apr) - avg(may_oct)), 2) AS winter_minus_summer_pct,
countIf(may_oct > 0) AS summers_positive
FROM tagged
GROUP BY era
ORDER BY eraAcross all 21 seasons, May to October averaged 3.88% and November to April averaged 6.06%, a spread of 2.18 percentage points. That spread is the entire case for the rule. Read the summer column beside it: 16 of those summers finished higher than they started, so the average sit-out skipped a gain rather than a loss.
The halves separate. The earlier block shows a spread of 4.84 points, the later one -0.24. Popular retellings quote a gap without naming the years behind it, and the years are the argument. Any seasonal statistic is a claim about one span of history, and the span is a choice made by whoever repeats it.
Is it really an August and September effect?
Six months is a blunt instrument. Breaking the calendar into months asks whether the summer window is uniformly soft or whether one part of it carries the whole result.
The exact SQL behind every number
WITH monthly AS (
SELECT toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
argMax(close, window_start) AS month_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2005-04-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-04-30')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY month_start
),
month_returns AS (
SELECT m1.month_start AS month_start,
100 * (toFloat64(m1.month_close) / toFloat64(m0.month_close) - 1) AS ret_pct
FROM monthly AS m1
INNER JOIN monthly AS m0 ON m0.month_start = addMonths(m1.month_start, -1)
)
SELECT formatDateTime(month_start, '%b') AS label,
count() AS readings,
round(avg(ret_pct), 2) AS avg_return_pct,
round(quantileDeterministic(0.5)(ret_pct, cityHash64(month_start)), 2) AS median_return_pct,
countIf(ret_pct > 0) AS positive_readings
FROM month_returns
GROUP BY label
ORDER BY min(toMonth(month_start))September is where the weakness sits. It averaged -0.75% and finished higher in 12 of 21 years, with a median of 0.38%. August averaged 0.28%. July, sitting in the middle of the stretch a seller skips, averaged 2.63%, and October, the last month before the rule buys back, averaged 0.97%.
The shape of the effect in this window is narrow: one soft patch late in the summer, with the months around it looking much like the rest of the calendar. An exit at the end of April to miss September also misses May, June, July and August.
What the switch actually costs
The seasonal gap is a gross number. A rule has to survive its own frictions.
The exact SQL behind every number
WITH monthly AS (
SELECT toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
argMax(close, window_start) AS month_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2005-04-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-04-30')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY month_start
),
pairs AS (
SELECT toYear(apr_m.month_start) + 1 AS year,
toFloat64(oct_m.month_close) / toFloat64(apr_m.month_close) AS summer_ratio,
toFloat64(apr_next.month_close) / toFloat64(oct_m.month_close) AS winter_ratio
FROM monthly AS apr_m
INNER JOIN monthly AS oct_m ON oct_m.month_start = addMonths(apr_m.month_start, 6)
INNER JOIN monthly AS apr_next ON apr_next.month_start = addMonths(apr_m.month_start, 12)
WHERE toMonth(apr_m.month_start) = 4
)
SELECT year,
round(exp(sum(log(summer_ratio * winter_ratio)) OVER (ORDER BY year)), 2) AS buy_and_hold_growth,
round(exp(sum(log(winter_ratio)) OVER (ORDER BY year)), 2) AS winter_only_growth
FROM pairs
ORDER BY yearA dollar held through every season from the end of April 2005 grew to $6.21 by the end of April 2026. The same dollar in the market only from November through April, idle the rest of the time, grew to $3.14. Both lines are price only with nothing deducted, which flatters the switching rule. Here is what the chart leaves out.
- Two trades every year, in every one of the 21 seasons. The ticket is free at most brokers now. The bid ask spread paid on each round trip is not.
- Tax. In a taxable account the April sale realizes whatever gain built up since November. A November to April holding period runs under a year by construction, which places the gain at short-term rates for a US taxpayer.
- Idle cash. The winter-only line credits the sidelined money with zero. A real holder would park it, and where to park idle cash covers the instruments people use for that.
- Dividends, which the next panel prices out.
The exact SQL behind every number
SELECT toYear(ex_dividend_date) AS year,
round(sumIf(cash_amount, toMonth(ex_dividend_date) >= 5 AND toMonth(ex_dividend_date) <= 10), 3) AS may_oct_dividends_usd,
round(sumIf(cash_amount, toMonth(ex_dividend_date) < 5 OR toMonth(ex_dividend_date) > 10), 3) AS nov_apr_dividends_usd
FROM global_markets.stocks_dividends
WHERE ticker = 'SPY'
AND cash_amount > 0
AND ex_dividend_date >= toDate('2005-01-01')
AND ex_dividend_date <= toDate('2025-12-31')
GROUP BY year
ORDER BY yearSPY's ex-dividend dates land in March, June, September and December, so two of the four fall inside the six months a seller sits out. In 2025, $3.592 per share of distributions carried a May to October ex-date, against $3.689 in the other six months. The two columns track each other across the whole chart. Sitting out half the calendar forgoes roughly half the fund's income every year, on top of whatever the price does in those months. The ex-dividend date is the cutoff that decides who gets paid.
One more cost carries no line item. Index returns arrive in clusters, and missing the best days puts numbers on what a handful of absent sessions does to a long-run balance. Six months out of every year is a lot of absent sessions. That is the same arithmetic behind dollar cost averaging as a discipline about time in the market rather than timing.
Why a famous calendar rule deserves suspicion
Twelve months admit 4,095 non-empty ways to pick a subset to be invested in. Search that space against one price history and something will look striking. That is a property of the search.
Sell in May has one honest advantage over a rule mined last week: it was famous long before this sample began, so the years on this page work as an out-of-sample test rather than a fitted result. The test returns a modest gap, concentrated in one month, attached to a switching rule that trails buying and holding over the same span. Look-ahead bias walks through the ways a backtest quietly learns its answer in advance, and calendar rules are the textbook case: the months get picked after the returns are known.
FAQ
Does sell in May and go away still work?
On SPY prices from April 2005 through April 2026, November to April averaged 6.06% against 3.88% for May to October, so the seasonal gap survives in the full sample. The summer half still averaged a gain, with 16 of the 21 summers finishing higher than they started.
Which months are actually the weak ones?
In this window the weakness concentrates in September, which averaged -0.75% and finished higher in 12 of 21 years. July, another month the rule sits out, averaged 2.63% over the same span.
Does selling in May beat buying and holding?
Not over this sample. A dollar held continuously from the end of April 2005 grew to $6.21 by April 2026, against $3.14 for the winter-only switch, and that comparison counts no trading costs, no tax, and no dividends.
What happens to dividends if you sell in May?
A fund's ex-dividend dates do not pause for the summer. Two of SPY's four quarterly ex-dates fall inside the May to October window, and a holder who is out of the fund on an ex-date does not receive that distribution.
Is a seasonal pattern the same as a prediction?
No. A historical average across 21 seasons describes what happened over a stated window. Individual years scatter widely around that average, as the first chart shows, and the window itself is a choice.
Every panel here is a stored query with its SQL attached. Change the ticker, move the window, and check whether the seasonal gap holds on the Strasmore terminal.