Strasmore Research
Deep Dives Matt ConnorBy Matt Connor

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.

March 9, 2009 is one of the most important dates in modern market history: the closing low of the financial crisis and the first day of a bull market that ran for over a decade. Here is the uncomfortable truth the minute 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 day, on one row

QuerySPY on March 9, 2009 — the generational low, receipted
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(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(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(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,
    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((minIf(toFloat64(low), (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 low_vs_prior_pct,
    round(toFloat64(sum(volume)) / 1e6, 1) AS day_shares_m,
    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, drifted to a $67.73 low late in the day (15:17 ET), and closed at $68.07-1.1% on the day, on 357.4 million shares. For scale: eighteen months earlier SPY had traded above $150. The whole day's range was about two dollars. The most consequential closing print of a generation arrived without a single dramatic minute.

The shape of the session

QuerySPY by half-hour — March 9, 2009 regular session
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_time

Bucket by bucket, the session just leaks lower — 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 dramatic sessions of that winter — the multi-percent crashes — had all happened in the preceding weeks. The bottom itself was the day sellers simply ran out.

What came after — the receipts

QuerySPY closes at the bottom, +3 months, and +1 year
The exact SQL behind every number
SELECT
    toString(et_date) AS session,
    close_usd
FROM (
    SELECT
        toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
        round(argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 2) AS close_usd
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND ((window_start >= toDateTime('2009-03-09 00:00:00') AND window_start < toDateTime('2009-03-10 00:00:00'))
        OR (window_start >= toDateTime('2009-06-09 00:00:00') AND window_start < toDateTime('2009-06-10 00:00:00'))
        OR (window_start >= toDateTime('2010-03-09 00:00:00') AND window_start < toDateTime('2010-03-10 00:00:00')))
    GROUP BY et_date
)
WHERE toString(et_date) IN ('2009-03-09', '2009-06-09', '2010-03-09')
ORDER BY et_date

From the $68.07 close: $94.66 three months later and $114.45 on the first anniversary — the strongest twelve months most investors alive had ever seen, starting on the most ordinary-looking day of the crisis. The rally's first leg was also its steepest, a pattern that repeated in March 2020's turn.

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. This is why the house style of these pages is receipts, not predictions: the tape can tell you exactly what the last day of a bear market looked like, and simultaneously that nothing in it would have identified the day in real time. Anyone claiming their indicator called this day is describing survivorship, and the eighteen 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 — sessions, ranges, volumes — is what makes the extraordinary legible when it arrives, and 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 March 9, 2009, with SPY at $68.07 — an intraday low of $67.73 that day. (The famous intraday "666" level on the S&P 500 index itself had printed three sessions earlier, on March 6.)

How fast did the market recover from the 2009 bottom?

The first year was historic: SPY closed at $114.45 one year to the day after the $68.07 bottom close. Recovering the entire crisis drawdown took until 2013.

Did anything signal the bottom in advance?

Nothing on the tape distinguished March 9 from the weeks around it — the session was quiet, the volume unexceptional. The bottom became a bottom retroactively, by never being undercut.


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.