March 9, 2009: The Bottom, On the Tape
March 9, 2009 was the exact bottom of the financial crisis, and the tape shows a quiet, unremarkable Monday. What generational lows actually look like up close.
March 9, 2009 is one of the most important dates in modern market history: the closing low of the financial crisis, -56.5% below the October 2007 peak, and the first day of a bull market that ran for over a decade. The history books cite the index levels from that Monday: 676.53 on the S&P 500, 6,547 on the Dow. The receipts below use SPY, the S&P 500 ETF, whose minute-by-minute tape this database stores back to 2003. And here is the uncomfortable truth that tape preserves: nothing about the session announced it. No capitulation crescendo, no reversal fireworks, a quiet, grinding red Monday that happened to be the last one. Every number is a stored query; expand any panel for the SQL.
The road to the bottom
The crisis arrived in stages, and the dates matter for reading everything below. Bear Stearns was sold to JPMorgan in March 2008. Lehman Brothers filed for bankruptcy on Monday, September 15, 2008, a session with its own page here. Congress passed TARP, the $700 billion bank-rescue fund, on October 3. AIG's government rescue was expanded twice. Citigroup took its second federal backstop in November. A winter rally faded, and by late February 2009 the averages had broken their November lows and kept falling. One row compresses that seventeen-month run:
| peak_close | peak_date | trough_close | trough_date | decline_pct | recovered_date |
|---|---|---|---|---|---|
| 156.41 | 2007-10-09 | 68.07 | 2009-03-09 | -56.5 | 2013-03-14 |
The exact SQL behind every number
WITH daily AS (
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS close_usd
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2007-01-02 00:00:00') AND window_start < toDateTime('2013-07-01 00:00:00')
GROUP BY et_date
),
(SELECT max(close_usd) FROM daily WHERE et_date < toDate('2008-01-01')) AS peak_close_usd
SELECT
round(peak_close_usd, 2) AS peak_close,
toString(argMaxIf(et_date, (close_usd, et_date), et_date < toDate('2008-01-01'))) AS peak_date,
round(minIf(close_usd, et_date BETWEEN toDate('2008-07-01') AND toDate('2009-06-30')), 2) AS trough_close,
toString(argMinIf(et_date, (close_usd, et_date), et_date BETWEEN toDate('2008-07-01') AND toDate('2009-06-30'))) AS trough_date,
round((minIf(close_usd, et_date BETWEEN toDate('2008-07-01') AND toDate('2009-06-30')) / peak_close_usd - 1) * 100, 1) AS decline_pct,
toString(minIf(et_date, et_date > toDate('2009-03-09') AND close_usd >= peak_close_usd)) AS recovered_date
FROM dailyFrom a closing peak of $156.41 on 2007-10-09, SPY fell to $68.07 on 2009-03-09, a -56.5% decline, the deepest since the 1930s. The same row carries the number long-term investors ask about next: the round trip. SPY did not close above its 2007 peak again until 2013-03-14, four years after the low, five and a half after the top. Both halves of that arithmetic get their own receipts below.
The day, on one row
| prior_close | rth_open | gap_pct | rth_high | high_et | rth_low | low_et | rth_close | day_change_pct | day_shares_m | avg20_shares_m | avg60_shares_m | vol_vs_20d_pct | rth_minute_bars |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 68.84 | 67.95 | -1.3 | 70 | 10:13 | 67.73 | 15:17 | 68.07 | -1.1 | 357.4 | 406.3 | 337.9 | -12 | 390 |
The exact SQL behind every number
WITH
(
SELECT argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2009-03-06 00:00:00') AND window_start < toDateTime('2009-03-09 04:00:00')
) AS prior_rth_close,
(
SELECT round(avg(day_shares) / 1e6, 1)
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d, toFloat64(sum(volume)) AS day_shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2008-12-01 00:00:00') AND window_start < toDateTime('2009-03-09 04:00:00')
GROUP BY d
ORDER BY d DESC
LIMIT 20
)
) AS avg20_shares,
(
SELECT round(avg(day_shares) / 1e6, 1)
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d, toFloat64(sum(volume)) AS day_shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2008-12-01 00:00:00') AND window_start < toDateTime('2009-03-09 04:00:00')
GROUP BY d
ORDER BY d DESC
LIMIT 60
)
) AS avg60_shares
SELECT
round(prior_rth_close, 2) AS prior_close,
round(toFloat64(argMinIf(open, window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)), 2) AS rth_open,
round((toFloat64(argMinIf(open, window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)) / prior_rth_close - 1) * 100, 1) AS gap_pct,
round(maxIf(toFloat64(high), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 2) AS rth_high,
formatDateTime(toTimeZone(argMaxIf(window_start, (toFloat64(high), -toInt64(toUnixTimestamp(window_start))), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 'America/New_York'), '%H:%i') AS high_et,
round(minIf(toFloat64(low), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 2) AS rth_low,
formatDateTime(toTimeZone(argMinIf(window_start, (toFloat64(low), toInt64(toUnixTimestamp(window_start))), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 'America/New_York'), '%H:%i') AS low_et,
round(toFloat64(argMaxIf(close, window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)), 2) AS rth_close,
round((toFloat64(argMaxIf(close, window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)) / prior_rth_close - 1) * 100, 1) AS day_change_pct,
round(toFloat64(sum(volume)) / 1e6, 1) AS day_shares_m,
avg20_shares AS avg20_shares_m,
avg60_shares AS avg60_shares_m,
round((toFloat64(sum(volume)) / 1e6 / avg20_shares - 1) * 100, 0) AS vol_vs_20d_pct,
countIf((toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS rth_minute_bars
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2009-03-09 04:00:00') AND window_start < toDateTime('2009-03-09 23:59:00')SPY opened at $67.95, a -1.3% gap down from Friday's $68.84 close, touched $70 at 10:13 ET, sagged to a $67.73 low late in the day (15:17 ET), and closed at $68.07, -1.1% on the day. The whole session's range was about two dollars. The most consequential closing print of a generation arrived without a single dramatic minute.
Volume answers a question the raw number alone can't: were 357.4 million shares loud or quiet? For March 2009, quiet. The trailing twenty sessions had averaged 406.3 million SPY shares a day, the bottom printed -12% relative to that average, and the trailing sixty averaged 337.9 million. Capitulation lore says generational lows arrive on climactic, record-setting turnover. The most famous bottom of the modern era traded less than an ordinary day of its own month.
The shape of the session
| et_time | bucket_close | bucket_low | shares_m |
|---|---|---|---|
| 09:30 | 68.95 | 67.95 | 40.5 |
| 10:00 | 69.49 | 68.9 | 31.8 |
| 10:30 | 68.9 | 68.82 | 25.6 |
| 11:00 | 68.99 | 68.6 | 21.6 |
| 11:30 | 68.95 | 68.71 | 18.7 |
| 12:00 | 69.13 | 68.83 | 14.5 |
| 12:30 | 68.79 | 68.65 | 15.7 |
| 13:00 | 68.34 | 68.13 | 21.1 |
| 13:30 | 68.48 | 68.25 | 15.7 |
| 14:00 | 68.57 | 68.33 | 25.9 |
| 14:30 | 68.43 | 67.95 | 24.5 |
| 15:00 | 68.05 | 67.73 | 28.3 |
| 15:30 | 68.07 | 67.78 | 44.3 |
The exact SQL behind every number
SELECT
formatDateTime(toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 MINUTE), '%H:%i') AS et_time,
round(toFloat64(argMax(close, window_start)), 2) AS bucket_close,
round(min(toFloat64(low)), 2) AS bucket_low,
round(toFloat64(sum(volume)) / 1e6, 1) AS shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2009-03-09 04:00:00') AND window_start < toDateTime('2009-03-09 23:59:00')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY et_time
ORDER BY et_timeThe half-hour path corrects a detail most retellings flatten: March 9 was not a one-way slide. After the gap down, SPY rallied through mid-morning, the 10:00 ET bucket closed at $69.49, just under the $70 day high printed at 10:13, then spent the afternoon giving it back, drifting down to the $67.73 low at 15:17 and bouncing modestly into the close. Rally, fade, small bounce: an utterly ordinary shape. No waterfall, no panic volume signature, no v-bottom. Compare it with Lehman Monday's close-on-the-low urgency or the flash crash's air pocket: this is a third species entirely, the exhausted tape. The multi-percent crashes of that winter had all happened in the preceding weeks. The bottom itself was the day sellers simply ran out.
What turned the tape
Nothing in Monday's data explains Tuesday, the turn arrived with the news cycle, not the tape. Before Tuesday's open, an internal memo from Citigroup chief executive Vikram Pandit leaked to the press: the bank, it said, had been profitable in January and February 2009, its best two-month stretch since 2007. Citigroup, the crisis's epicenter, trading at $1.05 at Monday's close, had not produced a piece of primary-source good news in months. Here is what the tape records for the five sessions that followed the low:
| session | spy_close | spy_change_pct | spy_shares_m | citi_close | ten_year_pct |
|---|---|---|---|---|---|
| 2009-03-09 | 68.07 | -1.1 | 357.4 | 1.05 | 2.89 |
| 2009-03-10 | 72.21 | 6.1 | 401.3 | 1.44 | 2.99 |
| 2009-03-11 | 72.6 | 0.5 | 350.1 | 1.54 | 2.95 |
| 2009-03-12 | 75.51 | 4 | 407.4 | 1.66 | 2.89 |
| 2009-03-13 | 76.09 | 0.8 | 332.7 | 1.78 | 2.89 |
The exact SQL behind every number
WITH daily AS (
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
argMaxIf(toFloat64(close), window_start, ticker = 'SPY' AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS spy_close_raw,
round(argMaxIf(toFloat64(close), window_start, ticker = 'C' AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 2) AS citi_close,
round(toFloat64(sumIf(volume, ticker = 'SPY')) / 1e6, 1) AS spy_shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'C')
AND window_start >= toDateTime('2009-03-06 04:00:00') AND window_start < toDateTime('2009-03-14 00:00:00')
GROUP BY et_date
)
SELECT
toString(d.et_date) AS session,
round(d.spy_close_raw, 2) AS spy_close,
round((d.spy_close_raw / d.prev_close - 1) * 100, 1) AS spy_change_pct,
d.spy_shares_m,
d.citi_close,
t.ten_year_pct
FROM (
SELECT *, lagInFrame(spy_close_raw) OVER (ORDER BY et_date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close
FROM daily
) AS d
LEFT JOIN (
SELECT date, round(toFloat64(yield_10_year), 2) AS ten_year_pct
FROM global_markets.treasury_yields
WHERE date BETWEEN '2009-03-09' AND '2009-03-13'
) AS t ON d.et_date = t.date
WHERE d.et_date >= toDate('2009-03-09')
ORDER BY d.et_dateMarch 10 opened higher and never gave it back: SPY closed at $72.21, up 6.1%, on 401.3 million shares, heavier volume than the bottom day itself. Citigroup closed at $1.44. By Friday, SPY stood at $76.09 and Citigroup at $1.78. The 10-year Treasury yield rose from 2.89% to 2.99% over that same Tuesday, money moving out of the safest asset alongside the equity rally, the flight-to-quality trade running in reverse.
The honest caveat: several multi-percent rallies had already come and failed that winter, and nothing on March 10 certified this one as different. The Pandit memo is the marker historians attach to the turn; what the tape can show, and does, above, is the coincidence of timing.
Did the low hold?
A bottom is only a bottom if the market never goes back. This panel tracks SPY week by week through the end of June 2009, each week's lowest trade and final close, with the running minimum in the last column:
| week_of | week_low | week_close | lowest_low_after_mar9 |
|---|---|---|---|
| 2009-03-09 | 69.37 | 76.09 | 69.37 |
| 2009-03-16 | 75.45 | 76.71 | 69.37 |
| 2009-03-23 | 78.31 | 81.62 | 69.37 |
| 2009-03-30 | 77.96 | 84.25 | 69.37 |
| 2009-04-06 | 81.51 | 85.82 | 69.37 |
| 2009-04-13 | 83.61 | 87.11 | 69.37 |
| 2009-04-20 | 82.75 | 86.65 | 69.37 |
| 2009-04-27 | 84.76 | 87.87 | 69.37 |
| 2009-05-04 | 88.38 | 93.04 | 69.37 |
| 2009-05-11 | 88.15 | 88.7 | 69.37 |
| 2009-05-18 | 88.26 | 89.06 | 69.37 |
| 2009-05-25 | 88.32 | 92.65 | 69.37 |
| 2009-06-01 | 87.53 | 94.53 | 69.37 |
| 2009-06-08 | 93.04 | 95.12 | 69.37 |
| 2009-06-15 | 90.83 | 91.97 | 69.37 |
| 2009-06-22 | 88.85 | 91.78 | 69.37 |
The exact SQL behind every number
WITH daily AS (
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
minIf(toFloat64(low), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS day_low,
argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS day_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2009-03-10 04:00:00') AND window_start < toDateTime('2009-06-27 00:00:00')
GROUP BY et_date
)
SELECT
week_of,
week_low,
week_close,
round(min(week_low) OVER (), 2) AS lowest_low_after_mar9
FROM (
SELECT
toString(toMonday(et_date)) AS week_of,
round(min(day_low), 2) AS week_low,
round(argMax(day_close, et_date), 2) AS week_close
FROM daily
GROUP BY week_of
)
ORDER BY week_ofThe lowest SPY traded in the sixteen weeks after March 9 was $69.37, and that print came in the first week off the low (2009-03-09). SPY never traded below its March 9 close of $68.07 again, let alone the $67.73 intraday low. There was no retest, no second chance, no pullback to the old level: by the week of 2009-05-04 SPY closed at $93.04, a third above the bottom in nine weeks. Waiting for confirmation had a price, and the panel states it exactly.
Who led the year off the low
The banks at the center of the damage were also the center of the rebound. One year from the bottom close to March 9, 2010:
| ticker | close_mar9_2009 | close_mar9_2010 | pct_1yr | financial |
|---|---|---|---|---|
| BAC | 3.75 | 16.82 | 349 | 1 |
| C | 1.05 | 3.83 | 265 | 1 |
| WFC | 10 | 28.97 | 190 | 1 |
| AAPL | 83.15 | 223.17 | 168 | 0 |
| JPM | 15.9 | 42.39 | 167 | 1 |
| XLF | 6.35 | 15.3 | 141 | 1 |
| GS | 73.86 | 168.97 | 129 | 1 |
| SPY | 68.07 | 114.45 | 68 | 0 |
| XOM | 64.56 | 66.79 | 3 | 0 |
The exact SQL behind every number
SELECT
ticker,
round(b_close, 2) AS close_mar9_2009,
round(y_close, 2) AS close_mar9_2010,
round((y_close / b_close - 1) * 100, 0) AS pct_1yr,
fin AS financial
FROM (
SELECT
ticker,
argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) = toDate('2009-03-09') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS b_close,
argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) = toDate('2010-03-09') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS y_close,
max(ticker IN ('C', 'BAC', 'WFC', 'JPM', 'GS', 'XLF')) AS fin
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('C', 'BAC', 'WFC', 'JPM', 'GS', 'XLF', 'SPY', 'AAPL', 'XOM')
AND ((window_start >= toDateTime('2009-03-09 04:00:00') AND window_start < toDateTime('2009-03-10 04:00:00'))
OR (window_start >= toDateTime('2010-03-09 04:00:00') AND window_start < toDateTime('2010-03-10 04:00:00')))
GROUP BY ticker
)
ORDER BY pct_1yr DESCThe top of the board: BAC at +349%, C at +265% (from $1.05 a share), WFC at +190%, the most damaged large financials, tripling and quadrupling off prices that had assumed the worst. The board is not all banks, AAPL returned 168% over the same year, but the panel's bounded assertion is that the single best performer is a financial. Meanwhile the broad market (SPY) gained 68%, and XOM, the defensive giant that had held up best on the way down, gained just 3%. The rebound inverted the decline's leaderboard almost exactly.
How it compares with other bottoms
The minute tape here begins in September 2003, so the October 2002 dot-com low sits outside receipt range. Against the three deepest closing lows since, March 2009 looks like this:
| bottom_session | bottom_close | plus_3mo_pct | plus_1yr_pct |
|---|---|---|---|
| 2009-03-09 | 68.07 | 38.5 | 68.1 |
| 2011-10-03 | 109.92 | 16.1 | 31.4 |
| 2018-12-24 | 234.37 | 19.1 | 37.1 |
| 2020-03-23 | 222.51 | 39.6 | 75.1 |
The exact SQL behind every number
WITH daily AS (
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) AS close_usd
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND ((window_start >= toDateTime('2009-03-09 04:00:00') AND window_start < toDateTime('2010-03-17 00:00:00'))
OR (window_start >= toDateTime('2011-10-03 04:00:00') AND window_start < toDateTime('2012-10-10 00:00:00'))
OR (window_start >= toDateTime('2018-12-24 04:00:00') AND window_start < toDateTime('2019-12-31 00:00:00'))
OR (window_start >= toDateTime('2020-03-23 04:00:00') AND window_start < toDateTime('2021-03-30 00:00:00')))
GROUP BY et_date
)
SELECT
bottom_session,
round(argMin(close_usd, et_date), 2) AS bottom_close,
round((argMinIf(close_usd, et_date, et_date >= toDate(bottom_session) + 91) / argMin(close_usd, et_date) - 1) * 100, 1) AS plus_3mo_pct,
round((argMinIf(close_usd, et_date, et_date >= toDate(bottom_session) + 365) / argMin(close_usd, et_date) - 1) * 100, 1) AS plus_1yr_pct
FROM (
SELECT
multiIf(et_date >= toDate('2020-03-23'), '2020-03-23',
et_date >= toDate('2018-12-24'), '2018-12-24',
et_date >= toDate('2011-10-03'), '2011-10-03',
'2009-03-09') AS bottom_session,
et_date,
close_usd
FROM daily
)
GROUP BY bottom_session
ORDER BY bottom_sessionFrom the 2009 bottom, SPY gained 38.5% in three months and 68.1% in a year, the strongest twelve months most investors alive had ever seen, starting on the most ordinary-looking day of the crisis. Only the March 2020 COVID low is in the same class, at +75.1% in its first year, a turn whose 2020 stimulus rally anatomy has its own page. The 2011 and 2018 correction lows, genuine panics in the moment, returned 31.4% and 37.1% in their first years. The pattern across all four: the deeper the hole, the steeper the first leg out, and the first leg was always the steepest of the recovery.
Why bottoms are only visible backward
The honest mechanics: a bottom is defined by what doesn't happen afterward, no lower low, which is unknowable in real time by construction. Every quantitative "bottom signal" ever proposed fired repeatedly on the way down through late 2008; the March 9 session itself scored unremarkably on all of them, ordinary shape, below-average volume, a news catalyst that arrived only the next morning. Anyone claiming their indicator called this day is describing survivorship, and the many prior "bottoms" it also called are the receipt for that.
What the day does teach: position for ranges of outcomes rather than points. The investors who did well from March 2009 were, overwhelmingly, those who had been buying through the entire miserable winter on schedule, the approach return-measurement conventions quietly assume, not those who found the pixel-perfect low. The tape's role in that discipline is calibration, not prophecy: knowing what ordinary looks like is what keeps a quiet Monday from being mistaken for one more day of a fall that had, in fact, just ended.
March 2009 bottom FAQ
What was the exact bottom of the 2008-2009 crash?
The closing low printed Monday, March 9, 2009: SPY at $68.07, the S&P 500 index at its widely cited 676.53. The famous intraday "666" on the index had printed one session earlier, on the prior Friday, March 6.
How much did the stock market fall from 2007 to 2009?
SPY fell -56.5% on a closing basis, from $156.41 on 2007-10-09 to $68.07 on 2009-03-09, the deepest US equity drawdown since the 1930s.
What happened on March 10, 2009?
The first session after the bottom: SPY rose 6.1% following the overnight leak of a Citigroup internal memo stating the bank had been profitable in January and February. Citigroup itself closed at $1.44, up from $1.05 at the low.
How fast did the market recover from the 2009 bottom?
The first year was historic: SPY gained 68.1% from the bottom close. Recovering the entire crisis drawdown took much longer, the first close back above the October 2007 peak came on 2013-03-14.
Did anything signal the bottom in advance?
Nothing on the tape distinguished March 9 from the weeks around it, the session was quiet and volume ran below its own 20-day average. The bottom became a bottom retroactively, by never being undercut: the lowest trade of the following sixteen weeks stayed above even the March 9 close.
Every panel above is a stored, versioned query over the historical tape, expand the SQL to see each measurement. Want to feel this day instead of reading it? It is one of the playable scenarios in the Strasmore Labs trading simulator.