Krach COVID 2020 : quatre coupe-circuits
Le krach COVID de 2020, sur pièces : les minutes manquantes de la coupure du 9 mars, quatre coupures en huit jours, et la carte du sommet au creux sur SPY.
Le krach COVID de 2020 a mené le S&P 500 d'une clôture record le 19 février à une perte de -34.2 % du sommet au creux en 23 séances — avec quatre coupe-circuits à l'échelle du marché en chemin, les premiers depuis 1997. Cette page rejoue tout l'arc à partir de la bande : la carte du krach, la séance de coupure du 9 mars minute par minute (y compris les minutes absentes des données, qui constituent la meilleure preuve de la page), les titres qui ont le plus chuté, et ce qu'ont fait les Treasuries et la bande d'options en parallèle. Chaque chiffre est une requête stockée ; déroulez n'importe quel panneau pour voir le SQL.
Tout le krach, sur une seule ligne
Avant la fameuse journée unique, la carte. Une seule requête sur les clôtures journalières de séance régulière de SPY fixe le sommet, le creux, la vitesse et la reprise — plus la même mesure appliquée au marché baissier de 2008 pour l'échelle.
Le SQL exact derrière chaque chiffre
WITH dailies AS (
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
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 c
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2020-02-01 00:00:00') AND window_start < toDateTime('2020-09-01 00:00:00')
GROUP BY d
),
peak AS (SELECT argMax(d, (c, -toInt32(d))) AS pd, max(c) AS pc FROM dailies WHERE d < toDate('2020-03-01')),
trough AS (SELECT argMin(d, (c, toInt32(d))) AS td, min(c) AS tc FROM dailies WHERE d < toDate('2020-04-01')),
gfc AS (
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
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 c
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2007-06-01 00:00:00') AND window_start < toDateTime('2009-01-01 00:00:00')
GROUP BY d
),
gpeak AS (SELECT argMax(d, (c, -toInt32(d))) AS pd, max(c) AS pc FROM gfc WHERE d < toDate('2008-01-01'))
SELECT
toString((SELECT pd FROM peak)) AS peak_date,
round((SELECT pc FROM peak), 2) AS peak_close,
toString((SELECT td FROM trough)) AS trough_date,
round((SELECT tc FROM trough), 2) AS trough_close,
round(((SELECT tc FROM trough) / (SELECT pc FROM peak) - 1) * 100, 1) AS decline_pct,
countIf(d > (SELECT pd FROM peak) AND d <= (SELECT td FROM trough)) AS sessions_peak_to_trough,
dateDiff('day', (SELECT pd FROM peak), (SELECT td FROM trough)) AS calendar_days,
countIf(d > (SELECT pd FROM peak) AND d <= (SELECT min(d) FROM dailies WHERE c <= 0.7 * (SELECT pc FROM peak))) AS sessions_to_minus_30,
(SELECT countIf(d > (SELECT pd FROM gpeak) AND d <= (SELECT min(d) FROM gfc WHERE c <= 0.7 * (SELECT pc FROM gpeak))) FROM gfc) AS gfc_2008_sessions_to_minus_30,
toString((SELECT min(d) FROM dailies WHERE d > (SELECT td FROM trough) AND c >= (SELECT pc FROM peak))) AS recovery_date,
countIf(d > (SELECT td FROM trough) AND d <= (SELECT min(d) FROM dailies WHERE d > (SELECT td FROM trough) AND c >= (SELECT pc FROM peak))) AS sessions_trough_to_recovery
FROM dailiesLa clôture au sommet de SPY était de $338.31 le 2020-02-19. La clôture au creux, $222.51 le 2020-03-23, se situe -34.2 % en dessous — un marché baissier comprimé en 23 séances, 33 jours calendaires. L'affirmation souvent citée du « repli de trente pour cent le plus rapide jamais enregistré » est attestée sur la même ligne : la clôture de SPY est passée pour la première fois 30 % sous le sommet après seulement 22 séances. Le marché baissier de 2008, mesuré à l'identique depuis sa clôture au sommet d'octobre 2007, a eu besoin de 250 séances pour perdre les mêmes 30 %. Ce qui a pris environ un an en 2008 a pris environ un mois en 2020.
Le squelette daté du krach, chaque chiffre provenant des panneaux de cette page :
- 19 février 2020 — la clôture record de SPY, $338.31.
- 9 mars — le premier coupe-circuit à l'échelle du marché depuis 1997 ; SPY clôture en baisse de -7.7 %. Attesté minute par minute ci-dessous.
- 12, 16 et 18 mars — trois autres coupures de niveau 1. Le 16 mars clôture à -11.6 %, la pire séance du krach.
- 23 mars — le plus bas en clôture : $222.51, -34.2 % sous le sommet.
- 24 mars — le retournement. Le rebond de relance du 24 mars porte cette bande.
- 2020-08-18 — SPY clôture de nouveau au-dessus du sommet de février, 103 séances après le plus bas.
9 mars 2020 : la séance qui a déclenché le coupe-circuit
Les coupe-circuits à l'échelle du marché se basent sur le S&P 500, ce panneau lit donc la coupure à travers SPY — l'ETF sur le S&P 500 — plutôt que par un autre indicateur. Au cours du week-end précédent, la revalorisation liée à la pandémie s'était heurtée à un choc d'offre pétrolière (nous y reviendrons plus bas), et le marché n'a jamais vraiment ouvert de façon ordonnée.
Le SQL exact derrière chaque chiffre
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('2020-03-06 00:00:00') AND window_start < toDateTime('2020-03-09 04:00:00')
) AS prior_rth_close,
(
SELECT (formatDateTime(toTimeZone(addMinutes(prev_bar, 1), 'America/New_York'), '%H:%i'), gap_minutes - 1)
FROM (
SELECT
lagInFrame(window_start) OVER (ORDER BY window_start ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_bar,
dateDiff('minute', prev_bar, window_start) AS gap_minutes
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2020-03-09 04:00:00') AND window_start < toDateTime('2020-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
)
WHERE prev_bar > toDateTime('2020-03-09 00:00:00')
ORDER BY gap_minutes DESC
LIMIT 1
) AS halt_gap
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,
halt_gap.1 AS halt_first_missing_et,
halt_gap.2 AS halt_missing_minutes,
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,
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('2020-03-09 04:00:00') AND window_start < toDateTime('2020-03-09 23:59:00')Deux chiffres d'entrée de jeu. D'abord, l'écart : SPY a ouvert à $275.3, -7.4 % sous la clôture de vendredi de $297.42 — et dès les premières minutes la baisse du S&P 500 a atteint le seuil de 7 % du niveau 1. Ensuite, et mieux encore : 376 barres minute de séance régulière au lieu des 390 habituelles. La bande s'arrête après 9 h 34 : à partir de 09:35 ET, 14 minutes consécutives n'impriment aucune barre. Rien ne s'est négocié nulle part. Le trou dans les données est le coupe-circuit. La séance a clôturé à $274.4, en baisse de -7.7 %, sur 304.6 millions de titres.
La forme d'une séance interrompue
Le SQL exact derrière chaque chiffre
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('2020-03-09 04:00:00') AND window_start < toDateTime('2020-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_timeL'intervalle d'ouverture contient à la fois le krach, la coupure et la reprise : son plus bas de $273.5 est à quelques centimes du plus bas de la journée entière de $273.45 — l'impression de l'après-midi à 14:44 ET n'a fait que retester le niveau du matin. Après la réouverture, la bande n'est allée presque nulle part : chaque clôture de demi-heure est restée à quelques dollars du prix de réouverture, et les dégâts du jour avaient été faits dans les premières minutes d'horloge. Le volume a raconté la même histoire à l'envers — la dernière demi-heure, à 46.7 millions de titres, a été l'intervalle le plus chargé de la journée à mesure que les flux de clôture se croisaient. Les coupe-circuits sont conçus pour produire exactement cette forme : arrêter la cascade, forcer un fixing de réouverture, et laisser la négociation continue reprendre au niveau revalorisé. L'horloge du marché a désormais cette mécanique intégrée de façon permanente.
Quatre coupures en huit séances
Le 9 mars n'était que la première.
Le SQL exact derrière chaque chiffre
SELECT
toString(et_date) AS session,
close_usd,
change_pct,
shares_m
FROM (
SELECT et_date, close_usd, shares_m,
round((close_usd / lagInFrame(close_usd) OVER (ORDER BY et_date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1) * 100, 1) AS change_pct
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,
round(toFloat64(sum(volume)) / 1e6, 1) AS shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2020-03-06 00:00:00') AND window_start < toDateTime('2020-03-19 00:00:00')
GROUP BY et_date
)
)
WHERE toString(et_date) IN ('2020-03-09', '2020-03-12', '2020-03-16', '2020-03-18')
ORDER BY et_dateDes coupures de niveau 1 se sont aussi déclenchées le 12 mars (clôture à -9.6 %), le 16 mars (clôture à -11.6 % à $239.41 — la plus forte baisse en pourcentage sur une journée du S&P depuis 1987), et le 18 mars (interrompu en séance, clôture à -5.2 %). Quatre coupures à l'échelle du marché en huit séances, après vingt-trois ans sans aucune. Notez ce qui n'est jamais arrivé : chaque coupure était de niveau 1, le palier de 7 %. Les paliers de 13 % et de 20 % n'ont jamais été atteints — même le 16 mars, la cascade a ralenti après la coupure et la séance s'est terminée en deçà de la ligne du niveau 2.
Qui a le plus chuté
Un chiffre d'indice masque la dispersion qu'il recouvre. La même arithmétique de clôture journalière, appliquée à une poignée de grandes capitalisations représentatives, montre où le krach a réellement frappé — à la fois le 9 mars lui-même et sur toute la glissade du 19 février au 23 mars.
Le SQL exact derrière chaque chiffre
WITH dailies AS (
SELECT
ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
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 c
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('UAL', 'CCL', 'XOM', 'JPM', 'AAPL', 'WMT', 'SPY')
AND window_start >= toDateTime('2020-02-18 00:00:00') AND window_start < toDateTime('2020-03-25 00:00:00')
GROUP BY ticker, d
)
SELECT
ticker,
round((anyIf(c, d = toDate('2020-03-09')) / anyIf(c, d = toDate('2020-03-06')) - 1) * 100, 1) AS mar9_pct,
round((anyIf(c, d = toDate('2020-03-23')) / anyIf(c, d = toDate('2020-02-19')) - 1) * 100, 1) AS crash_pct
FROM dailies
GROUP BY ticker
ORDER BY crash_pct ASCLe titre le plus touché du panneau, CCL (Carnival, l'opérateur de croisières), a perdu -19.9 % le 9 mars à lui seul et -72.3 % du sommet au creux. United Airlines a cédé -66.9 % sur le krach ; ExxonMobil -47.9 % ; JPMorgan -42.6 %. Face à eux, les -34.2 % de SPY paraissent presque doux, Apple a chuté à peu près comme le marché à -31 %, et Walmart — épicerie, produits essentiels, ouvert pendant les confinements — a terminé la même fenêtre à seulement -2.9 %. Le voyage et l'énergie se sont revalorisés pour un monde à l'arrêt ; la consommation de base a à peine bougé.
La guerre des prix du pétrole, en bref
La ligne de l'énergie ci-dessus mérite son explication d'un paragraphe, puisque la « guerre des prix du pétrole » porte l'autre moitié de l'histoire du 9 mars. Les discussions de production de l'OPEP+ entre l'Arabie saoudite et la Russie se sont terminées sans accord le vendredi 6 mars 2020. Au cours du week-end, l'Arabie saoudite a réduit ses prix de vente officiels et annoncé son intention d'augmenter sa production dans un monde où la demande de voyages s'arrêtait déjà — un choc d'offre empilé sur un choc de demande. L'ouverture actions du lundi a porté les deux à la fois, et la preuve est dans le panneau ci-dessus : ExxonMobil a chuté de -12.2 % ce lundi-là contre -7.7 % pour SPY.
La fuite vers la sécurité — et la semaine où elle s'est brisée
Les actions n'étaient que la moitié de l'histoire. L'autre moitié était le marché des Treasuries, où la classique fuite vers la sécurité a atteint un record — puis, pendant une semaine remarquable, s'est inversée.
Le SQL exact derrière chaque chiffre
SELECT
toString(date) AS date,
round(yield_10_year, 2) AS ten_year_pct,
round(yield_3_month, 2) AS three_month_pct
FROM global_markets.treasury_yields
WHERE date >= '2020-02-18' AND date <= '2020-03-31'
AND isNotNull(yield_10_year)
ORDER BY dateLe rendement du 10 ans se tenait à 1.56 % au sommet actions du 19 février. Au 9 mars — la séance de coupure — il a clôturé à 0.54 %, un plus bas historique, les acheteurs acceptant un demi pour cent par an pendant une décennie en échange de la sécurité. Puis le schéma s'est inversé : jusqu'au 18 mars le rendement du 10 ans a monté à 1.18 % tandis que les actions continuaient de baisser — la « ruée vers le cash », une semaine où fonds, entreprises et détenteurs étrangers ont vendu tout ce qui était liquide, Treasuries compris, pour se procurer des dollars. Pendant ce temps le bon à 3 mois a clôturé ce jour-là à 0.02 % — les équivalents de trésorerie collés à zéro. Quand l'actif le plus sûr et l'actif le plus risqué baissent ensemble, ce qui s'achète, c'est la liquidité elle-même. La courbe des taux porte cet épisode de façon permanente dans son histoire.
Ce que montre la bande d'options
Les options cotées de SPY — le lieu de couverture de référence du marché — ont laissé leur propre preuve de la panique, et son timing en est la partie intéressante.
Le SQL exact derrière chaque chiffre
SELECT
toString(toDate(toTimeZone(sip_timestamp, 'America/New_York'))) AS session,
round(sumIf(toFloat64(size), substring(ticker, 12, 1) = 'P') / 1e6, 2) AS put_contracts_m,
round(sumIf(toFloat64(size), substring(ticker, 12, 1) = 'C') / 1e6, 2) AS call_contracts_m,
round(sumIf(toFloat64(size), substring(ticker, 12, 1) = 'P') / sumIf(toFloat64(size), substring(ticker, 12, 1) = 'C'), 2) AS put_call_ratio
FROM global_markets.options_trades
WHERE ticker >= 'O:SPY2' AND ticker < 'O:SPY3'
AND sip_timestamp >= toDateTime('2020-03-02 00:00:00') AND sip_timestamp < toDateTime('2020-03-14 00:00:00')
GROUP BY session
ORDER BY sessionLe ratio de volume put/call a culminé à 1.95 — près de deux puts négociés pour chaque call — le vendredi 6 mars, avant la séance de coupure. Le 9 mars lui-même, 4.35 millions de puts se sont négociés contre 2.38 millions de calls, un ratio de 1.83. Au 12 mars — une séance à -9.6 % — le ratio s'était détendu à 1.32 à mesure que le volume de calls reprenait aux côtés des puts. Le plus fort biais vendeur de puts est venu au début de la cascade, pas à son creux : la protection a été achetée tôt, et les journées de baisse ultérieures, plus fortes, se sont négociées sur une bande d'options plus équilibrée.
Comment fonctionne réellement une coupure à l'échelle du marché
La mécanique, puisqu'elle se déclenche assez rarement pour être oubliée entre deux usages : les coupures à l'échelle du marché se basent sur la baisse du S&P 500 par rapport à la clôture précédente — 7 % (niveau 1) et 13 % (niveau 2) déclenchent chacun une interruption de 15 minutes si atteints avant 15 h 25 ET ; 20 % (niveau 3) met fin à la séance sur-le-champ. Pendant la coupure, rien ne se négocie sur aucune place ; les ordres s'accumulent en file pour un fixing de réouverture, qui concentre l'intérêt accumulé en un seul prix comme le fait chaque matin le fixing d'ouverture. Ce dispositif date des suites du flash crash de 2010, qui avait révélé que les anciens seuils étaient trop lâches pour se déclencher même dans une véritable cascade.
Mars 2020 a été le premier — et à ce jour le seul — test grandeur nature de ce dispositif, et le verdict est dans les panneaux ci-dessus : quatre coupures de niveau 1, chacune suivie d'une réouverture ordonnée, aucun niveau 2 ou niveau 3 jamais atteint, et un marché fonctionnel à chacune des 23 séances du repli important le plus rapide de l'histoire de l'indice. Les règles ont été maintenues ensuite : les mêmes seuils 7/13/20, référencés au S&P 500, restent en vigueur aujourd'hui. Le système a plié ; la tuyauterie a tenu.
FAQ krach COVID
Qu'est-ce qui a déclenché le coupe-circuit le 9 mars 2020 ?
Le S&P 500 tombant de 7 % par rapport à sa clôture précédente — le seuil de niveau 1 à l'échelle du marché — dans les premières minutes. La négociation s'est interrompue 15 minutes à l'échelle du marché, puis a rouvert par fixing. La coupure est visible dans la bande minute de cette page sous la forme de 14 barres manquantes consécutives à partir de 09:35 ET.
De combien le marché actions a-t-il chuté lors du krach COVID ?
Mesuré sur les clôtures journalières de SPY, -34.2 % — de $338.31 le 19 février 2020 à $222.51 le 23 mars 2020, sur 23 séances.
Combien de coupe-circuits ont été atteints en mars 2020 ?
Quatre coupures de niveau 1 à l'échelle du marché : les 9, 12, 16 et 18 mars. C'étaient les premières depuis octobre 1997.
Les coupe-circuits de niveau 2 ou de niveau 3 ont-ils été atteints en 2020 ?
Non. Les quatre coupures de 2020 étaient de niveau 1 (7 %). Aucune coupure à l'échelle du marché de niveau 2 (13 %) ou de niveau 3 (20 %) ne s'est jamais déclenchée sous le dispositif actuel — pas même le 16 mars, la pire séance du krach à -11.6 %.
Le marché s'est-il complètement remis du krach COVID ?
Oui. SPY a clôturé au-dessus de son sommet du 19 février 2020 le 2020-08-18 — 103 séances après le plus bas du 23 mars, l'une des reprises complètes les plus rapides après un marché baissier de cette profondeur.
Chaque panneau ci-dessus est une requête stockée et versionnée sur la bande historique — déroulez le SQL pour voir chaque mesure. Envie de ressentir cette journée plutôt que de la lire ? C'est l'un des scénarios jouables du simulateur de trading Strasmore Labs.