COVID Crash 2020: Empat Halt dan Peak to Trough
Analisis crash COVID dua ribu dua puluh: menit yang hilang pada halt sembilan Maret, empat circuit breaker dalam delapan hari, dan peta peak-to-trough pada SPY.
Kejatuhan akibat COVID pada tahun dua ribu dua puluh membawa S&P 500 dari penutupan rekor pada tanggal sembilan belas Februari menuju kerugian peak-to-trough sebesar -34.2% dalam 23 hari trading — dengan empat penghentian circuit-breaker di seluruh pasar selama proses tersebut, yang pertama kali terjadi sejak tahun seribu sembilan ratus sembilan puluh tujuh. Halaman ini memutar ulang seluruh rangkaian peristiwa dari data tape: peta kejatuhan tersebut, sesi penghentian tanggal sembilan Maret menit demi menit (termasuk menit-menit yang hilang dari data, yang merupakan bukti terbaik di halaman ini), nama-nama yang jatuh paling dalam, serta pergerakan Treasuries dan options tape secara bersamaan. Setiap angka adalah query tersimpan; perluas panel apa pun untuk melihat SQL.
Seluruh crash, dalam satu baris
Sebelum hari tunggal yang terkenal itu, lihatlah petanya. Satu query terhadap harga penutupan sesi reguler harian SPY menetapkan titik puncak, titik terendah, kecepatan, dan pemulihan — ditambah pengukuran yang sama pada bear market 2008 sebagai skala perbandingan.
SQL tepat di balik setiap angka
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 dailiesPenutupan puncak SPY adalah $338.31 pada 2020-02-19. Penutupan terendah, $222.51 pada 2020-03-23, berada -34.2% di bawahnya — sebuah bear market yang terkompresi menjadi 23 sesi perdagangan, atau 33 hari kalender. Klaim "drawdown tiga puluh persen tercepat dalam sejarah" yang sering dikutip terbukti dalam baris yang sama: penutupan SPY pertama kali menembus 30% di bawah puncak hanya dalam 22 sesi. Bear market 2008, yang diukur secara identik dari penutupan puncak Oktober 2007, membutuhkan 250 sesi untuk kehilangan 30% yang sama. Apa yang membutuhkan waktu sekitar satu tahun pada 2008 terjadi dalam waktu sekitar satu bulan pada 2020.
Kerangka kronologis dari crash tersebut, setiap angka bersumber dari panel di halaman ini:
- 19 Februari 2020 — penutupan rekor SPY, $338.31.
- 9 Maret — circuit breaker seluruh pasar pertama sejak 1997; SPY ditutup turun -7.7%. Buktinya tercatat menit demi menit di bawah.
- 12, 16, dan 18 Maret — tiga lagi penghentian Level-1. 16 Maret ditutup -11.6%, sesi tunggal terburuk selama crash.
- 23 Maret — titik terendah penutupan: $222.51, -34.2% dari puncak.
- 24 Maret — titik balik. Rally stimulus 24 Maret melanjutkan tren tersebut.
- 2020-08-18 — SPY ditutup di atas puncak Februari lagi, 103 sesi setelah titik terendah.
9 Maret 2020: sesi yang memicu circuit breaker
Circuit breaker seluruh pasar dipicu oleh S&P 500, jadi panel ini membaca penghentian perdagangan melalui SPY — ETF S&P 500 — bukan proksi lainnya. Selama akhir pekan sebelumnya, penyesuaian harga akibat pandemi berbenturan dengan guncangan pasokan minyak (penjelasan lebih lanjut di bawah), dan pasar tidak pernah benar-benar dibuka secara teratur.
SQL tepat di balik setiap angka
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')Dua angka di awal. Pertama, gap: SPY dibuka pada $275.3, -7.4% di bawah penutupan Jumat sebesar $297.42 — dan dalam beberapa menit pertama penurunan S&P 500 mencapai ambang batas Level-1 sebesar 7%. Kedua, dan lebih penting: 376 minute bars sesi reguler alih-alih 390 yang biasanya. Data berhenti setelah pukul 09:34 am: dimulai pada 09:35 ET, 14 menit berturut-turut tidak mencetak bar sama sekali. Tidak ada yang diperdagangkan di mana pun. Gap dalam data tersebut adalah circuit breaker. Sesi ditutup pada $274.4, turun -7.7%, dengan volume 304.6 juta saham.
Bentuk sesi yang terhenti
SQL tepat di balik setiap angka
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_timeBucket pembukaan mencakup crash, penghentian, dan pemulihan secara bersamaan: level terendahnya di $273.5 hanya selisih beberapa sen dari level terendah harian di $273.45 — cetakan sore hari pada 14:44 ET hanya menguji kembali level pagi hari. Setelah pembukaan kembali, pergerakan harga hampir tidak terjadi: setiap penutupan setengah jam berada dalam rentang beberapa dolar dari harga pembukaan kembali, dan kerusakan hari itu terjadi pada menit-menit pertama. Volume menunjukkan cerita yang sama secara terbalik — setengah jam terakhir, dengan 46.7 juta saham, menjadi bucket terberat hari itu saat aliran penutupan bersilangan. Circuit breaker dirancang untuk menghasilkan bentuk tepat seperti ini: menghentikan penurunan tajam, memaksa lelang pembukaan kembali, dan membiarkan perdagangan kontinu berlanjut pada level harga yang telah disesuaikan. Jam pasar kini memiliki mekanisme ini tertanam secara permanen.
Empat penghentian dalam delapan sesi
9 Maret hanyalah yang pertama.
SQL tepat di balik setiap angka
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_dateBreaker Level-1 juga terpicu pada 12 Maret (tutup -9.6%), 16 Maret (tutup -11.6% pada $239.41 — penurunan persentase satu hari terbesar S&P sejak 1987), dan 18 Maret (dihentikan intraday, tutup -5.2%). Empat penghentian pasar dalam delapan hari perdagangan, setelah dua puluh tiga tahun tanpa satu pun penghentian. Perhatikan apa yang tidak pernah terjadi: setiap penghentian adalah Level 1, tingkatan 7%. Tingkatan 13% dan 20% tidak pernah tercapai — bahkan pada 16 Maret, penurunan melambat setelah penghentian dan sesi berakhir di dalam garis Level-2.
Siapa yang jatuh paling dalam
Angka indeks menyembunyikan dispersi di bawahnya. Perhitungan penutupan harian yang sama, jika dijalankan pada beberapa saham large-cap yang representatif, menunjukkan di mana crash sebenarnya terjadi — baik pada tanggal sembilan Maret itu sendiri maupun sepanjang penurunan dari sembilan belas Februari hingga dua puluh tiga Maret.
SQL tepat di balik setiap angka
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 ASCSaham yang paling terpukul dalam panel tersebut, CCL (Carnival, operator kapal pesiar), kehilangan -19.9% pada sembilan Maret saja dan -72.3% dari puncak ke titik terendah. United Airlines turun -66.9% selama crash; ExxonMobil -47.9%; JPMorgan -42.6%. Dibandingkan dengan mereka, penurunan SPY sebesar -34.2% terlihat hampir ringan, Apple turun kurang lebih mengikuti pasar sebesar -31%, dan Walmart — bahan makanan, kebutuhan pokok, tetap buka selama lockdown — mengakhiri periode yang sama hanya pada -2.9%. Sektor perjalanan dan energi mengalami repricing karena dunia yang terhenti; sektor staples hampir tidak bergerak.
Perang harga minyak secara singkat
Perselisihan energi di atas memerlukan penjelasan satu paragraf, karena "perang harga minyak" membawa sisi lain dari cerita tanggal 9 Maret. Pembicaraan produksi OPEC+ antara Arab Saudi dan Rusia berakhir tanpa kesepakatan pada Jumat, 6 Maret 2020. Selama akhir pekan, Arab Saudi memotong harga jual resminya dan mengumumkan rencana untuk meningkatkan output ke dunia di mana permintaan perjalanan sudah terhenti — sebuah supply shock yang bertumpuk di atas demand shock. Pembukaan ekuitas pada hari Senin membawa keduanya sekaligus, dan hasilnya terlihat pada panel di atas: ExxonMobil turun -12.2% pada hari Senin tersebut dibandingkan dengan SPY yang turun -7.7%.
Pelarian ke aset aman — dan minggu saat tren itu patah
Ekuitas hanyalah setengah dari cerita. Setengah lainnya adalah pasar Treasury, di mana fenomena klasik flight to safety mencapai rekor — dan kemudian, selama satu minggu yang luar biasa, berbalik arah.
SQL tepat di balik setiap angka
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 dateYield 10-tahun berada di level 1.56% pada puncak ekuitas tanggal 19 Februari. Pada 9 Maret — sesi penghentian perdagangan — yield ditutup pada 0.54%, level terendah sepanjang masa, dengan pembeli menerima imbal hasil setengah persen per tahun selama satu dekade demi keamanan. Kemudian pola tersebut terbalik: hingga 18 Maret yield 10-tahun naik menjadi 1.18% sementara ekuitas terus turun — fenomena "dash for cash," sebuah minggu di mana dana, perusahaan, dan pemegang asing menjual apa pun yang likuid, termasuk Treasury, untuk mendapatkan dolar. Sementara itu, bill 3-bulan ditutup pada hari itu di level 0.02% — ekivalen kas tertahan di angka nol. Ketika aset teraman dan aset paling berisiko turun bersamaan, hal yang dibeli adalah likuiditas itu sendiri. Kurva imbal hasil mencatat episode ini secara permanen dalam sejarahnya.
Apa yang ditunjukkan oleh data opsi
Opsi terdaftar SPY — tempat lindung nilai utama pasar — meninggalkan jejak kepanikan tersebut, dan waktunya adalah bagian yang menarik.
SQL tepat di balik setiap angka
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 sessionRasio volume put/call mencapai puncaknya pada 1.95 — hampir dua put diperdagangkan untuk setiap call — pada Jumat, 6 Maret, sebelum sesi penghentian perdagangan. Pada 9 Maret sendiri, 4.35 juta put diperdagangkan dibandingkan 2.38 juta call, dengan rasio 1.83. Pada 12 Maret — sesi -9.6% — rasio tersebut menurun menjadi 1.32 seiring meningkatnya volume call bersamaan dengan put. Skew put terberat terjadi pada awal penurunan, bukan di titik terendah: perlindungan dibeli lebih awal, dan hari-hari penurunan yang lebih besar setelahnya diperdagangkan pada data opsi yang lebih dua sisi.
Cara kerja penghentian perdagangan seluruh pasar
Mekanismenya jarang terjadi sehingga sering terlupakan: market-wide breakers dipicu oleh penurunan S&P 500 dari penutupan sebelumnya — 7% (Level 1) dan 13% (Level 2) masing-masing memicu penghentian selama lima belas menit jika terjadi sebelum pukul 15:25 ET; 20% (Level 3) mengakhiri sesi sepenuhnya. Selama penghentian, tidak ada perdagangan di bursa mana pun; pesanan mengantre untuk lelang pembukaan kembali. Hal ini memusatkan minat yang terakumulasi menjadi satu harga seperti yang dilakukan lelang pembukaan setiap pagi. Desain ini berasal dari dampak flash crash 2010, yang menunjukkan bahwa ambang batas lama terlalu longgar untuk terpicu bahkan dalam penurunan berantai yang nyata.
Maret dua ribu dua puluh adalah uji coba langsung pertama — dan sejauh ini satu-satunya — dari desain tersebut, dan hasilnya terlihat pada panel di atas: empat penghentian Level 1, yang masing-masing diikuti oleh pembukaan kembali yang tertib, tidak ada Level 2 atau Level 3 yang pernah tercapai, dan pasar tetap berfungsi pada setiap satu dari 23 sesi penurunan besar tercepat dalam sejarah indeks tersebut. Aturan tersebut tetap dipertahankan setelahnya: ambang batas 7/13/20 yang sama, mengacu pada S&P 500, tetap berlaku hingga saat ini. Sistem tersebut tertekan; namun infrastrukturnya tetap bertahan.
FAQ crash COVID
Apa yang memicu circuit breaker pada 9 Maret 2020?
S&P 500 turun 7% dari penutupan sebelumnya — ambang batas Level-1 seluruh pasar — dalam beberapa menit pembukaan. Perdagangan dihentikan selama lima belas menit di seluruh pasar, kemudian dibuka kembali melalui lelang. Penghentian ini terlihat pada minute tape di halaman ini sebagai 14 bar yang hilang secara berturut-turut mulai pukul 09:35 ET.
Seberapa besar penurunan pasar saham dalam crash COVID?
Diukur berdasarkan penutupan harian SPY, sebesar -34.2% — dari $338.31 pada 19 Februari 2020 menjadi $222.51 pada 23 Maret 2020, selama 23 sesi perdagangan.
Berapa banyak circuit breaker yang terpicu pada Maret 2020?
Empat penghentian Level-1 seluruh pasar: 9, 12, 16, dan 18 Maret. Ini adalah yang pertama sejak Oktober 1997.
Apakah circuit breaker Level 2 atau Level 3 pernah terpicu pada 2020?
Tidak. Keempat penghentian tahun 2020 adalah Level 1 (7%). Tidak ada penghentian seluruh pasar Level-2 (13%) atau Level-3 (20%) yang pernah terpicu di bawah desain saat ini — bahkan pada 16 Maret, sesi terburuk dalam crash tersebut pada -11.6%.
Apakah pasar pulih sepenuhnya dari crash COVID?
Ya. SPY ditutup di atas puncak 19 Februari 2020 pada 2020-08-18 — 103 sesi perdagangan setelah titik terendah 23 Maret, salah satu pemulihan penuh tercepat dari bear market sedalam ini.
Setiap panel di atas adalah query tersimpan dan terversi atas historical tape — perluas SQL untuk melihat setiap pengukuran. Ingin merasakan hari ini daripada membacanya? Ini adalah salah satu skenario yang dapat dimainkan dalam simulator perdagangan Strasmore Labs.