{"slug":"buy-when-others-are-fearful","qid":"mood_returns","label":"Average S&P 500 forward return after fearful, greedy, and ordinary days (2024-2026)","post_title":"Buy When Others Are Fearful: The Data","post_url":"/blog/buy-when-others-are-fearful#q-mood_returns","columns":["market_mood","days","fwd_5d_pct","fwd_20d_pct","fwd_60d_pct"],"rows":[{"market_mood":"Extreme fear (least upbeat)","days":45,"fwd_5d_pct":0.08,"fwd_20d_pct":1.47,"fwd_60d_pct":6.35},{"market_mood":"In between","days":359,"fwd_5d_pct":0.38,"fwd_20d_pct":1.24,"fwd_60d_pct":4.03},{"market_mood":"Extreme greed (most upbeat)","days":45,"fwd_5d_pct":0.13,"fwd_20d_pct":1.53,"fwd_60d_pct":2.85}],"shape":"table","sql":"WITH sent AS (\n    SELECT toDate(published_utc) AS d,\n           (countIf(s='positive') - countIf(s='negative')) / (countIf(s='positive') + countIf(s='negative')) AS net\n    FROM (SELECT published_utc, JSONExtractString(ins,'sentiment') AS s\n          FROM global_markets.stocks_news ARRAY JOIN insights AS ins\n          WHERE JSONExtractString(ins,'sentiment') != '')\n    GROUP BY d HAVING countIf(s='positive') + countIf(s='negative') >= 20\n),\nspyd AS (\n    SELECT toDate(toTimeZone(window_start,'America/New_York')) AS d,\n           argMax(toFloat64(close), toTimeZone(window_start,'America/New_York')) AS c\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE ticker='SPY' AND window_start >= '2024-01-01'\n      AND (toHour(toTimeZone(window_start,'America/New_York'))*60 + toMinute(toTimeZone(window_start,'America/New_York'))) BETWEEN 570 AND 959\n    GROUP BY d\n),\nspy AS (\n    SELECT d, c, leadInFrame(c,5) OVER w AS c5, leadInFrame(c,20) OVER w AS c20, leadInFrame(c,60) OVER w AS c60\n    FROM spyd WINDOW w AS (ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 60 FOLLOWING)\n),\nj AS (\n    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\n    FROM sent s INNER JOIN spy ON s.d = spy.d WHERE spy.c60 > 0\n),\nqt AS (SELECT quantile(0.1)(net) AS p10, quantile(0.9)(net) AS p90 FROM j)\nSELECT multiIf(net <= (SELECT p10 FROM qt), 'Extreme fear (least upbeat)',\n               net >= (SELECT p90 FROM qt), 'Extreme greed (most upbeat)',\n               'In between') AS market_mood,\n       count() AS days,\n       round(avg(f5),2)  AS fwd_5d_pct,\n       round(avg(f20),2) AS fwd_20d_pct,\n       round(avg(f60),2) AS fwd_60d_pct\nFROM j GROUP BY market_mood\nORDER BY multiIf(market_mood='Extreme fear (least upbeat)',0, market_mood='In between',1, 2)","computed_at":"2026-07-16T10:34:59.461910+00:00","elapsed":3.844571341}