Buy When Others Are Fearful: The Data
Average S&P 500 forward return after fearful, greedy, and ordinary days (2024-2026)table ·
2026-07-16 · 3×5
News sentiment coverage by year: how many tagged insights, and the share downbeatranking ·
2026-07-16 · 3×3
Average S&P 500 forward return after fearful, greedy, and ordinary days (2024-2026)
Average S&P 500 forward return after fearful, greedy, and ordinary days (2024-2026)
| market_mood | days | fwd_5d_pct | fwd_20d_pct | fwd_60d_pct |
|---|---|---|---|---|
| Extreme fear (least upbeat) | 45 | 0.08 | 1.47 | 6.35 |
| In between | 359 | 0.38 | 1.24 | 4.03 |
| Extreme greed (most upbeat) | 45 | 0.13 | 1.53 | 2.85 |
the exact SQL behind every number
WITH sent AS (
SELECT toDate(published_utc) AS d,
(countIf(s='positive') - countIf(s='negative')) / (countIf(s='positive') + countIf(s='negative')) AS net
FROM (SELECT published_utc, JSONExtractString(ins,'sentiment') AS s
FROM global_markets.stocks_news ARRAY JOIN insights AS ins
WHERE JSONExtractString(ins,'sentiment') != '')
GROUP BY d HAVING countIf(s='positive') + countIf(s='negative') >= 20
),
spyd AS (
SELECT toDate(toTimeZone(window_start,'America/New_York')) AS d,
argMax(toFloat64(close), toTimeZone(window_start,'America/New_York')) AS c
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker='SPY' AND window_start >= '2024-01-01'
AND (toHour(toTimeZone(window_start,'America/New_York'))*60 + toMinute(toTimeZone(window_start,'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
spy AS (
SELECT d, c, leadInFrame(c,5) OVER w AS c5, leadInFrame(c,20) OVER w AS c20, leadInFrame(c,60) OVER w AS c60
FROM spyd WINDOW w AS (ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 60 FOLLOWING)
),
j AS (
SELECT s.net AS net, (spy.c5/spy.c-1)*100 AS f5, (spy.c20/spy.c-1)*100 AS f20, (spy.c60/spy.c-1)*100 AS f60
FROM sent s INNER JOIN spy ON s.d = spy.d WHERE spy.c60 > 0
),
qt AS (SELECT quantile(0.1)(net) AS p10, quantile(0.9)(net) AS p90 FROM j)
SELECT multiIf(net <= (SELECT p10 FROM qt), 'Extreme fear (least upbeat)',
net >= (SELECT p90 FROM qt), 'Extreme greed (most upbeat)',
'In between') AS market_mood,
count() AS days,
round(avg(f5),2) AS fwd_5d_pct,
round(avg(f20),2) AS fwd_20d_pct,
round(avg(f60),2) AS fwd_60d_pct
FROM j GROUP BY market_mood
ORDER BY multiIf(market_mood='Extreme fear (least upbeat)',0, market_mood='In between',1, 2)
More from this analysisBuy When Others Are Fearful: The Data
News sentiment coverage by year: how many tagged insights, and the share downbeat
ranking 3×3
→
The S&P 500's underwater curve: worst drawdown from a prior high, by month
series 127×2
→
SPY's 20 best and 20 worst days since 2016, counted by year
ranking 11×3
→
S&P 500 worst intra-year drawdown vs the year's price return, since 2016
ranking 11×3
→
See all 2,173 queries →