2020년 코로나19 폭락장 서킷브레이커와 SPY 하락 기록
2020년 코로나19 당시 8일간 네 차례 발생한 서킷브레이커와 SPY의 고점 대비 저점 하락 경로를 분석합니다. 3월 9일 장중 분 단위 기록을 포함하여 당시 시장의 궤적과 국채 및 옵션 시장의 움직임을 상세히 재구성합니다.
-34.2% 2020년 코로나19 폭락장은 S&P 500 지수를 2월 19일 사상 최고 종가에서 23 거래일 만에 고점 대비 저점까지 하락하게 만들었으며, 그 과정에서 1997년 이후 처음으로 네 차례의 시장 전체 서킷브레이커(circuit-breaker) 발동이 있었습니다. 본 페이지는 당시의 기록을 통해 전체 궤적을 재구성합니다. 폭락의 경로, 3월 9일 서킷브레이커가 발동된 장중 분 단위 기록(데이터에서 누락된 분까지 포함하며, 이는 본 페이지에서 가장 중요한 증거입니다), 가장 큰 폭으로 하락한 종목들, 그리고 당시 국채(Treasuries)와 옵션(options) 시장의 움직임을 다룹니다. 모든 수치는 저장된 쿼리에서 추출되었으며, 각 패널을 확장하면 SQL을 확인할 수 있습니다.
폭락의 전 과정, 한눈에 보기
유명한 단 하루의 기록 이전에, 전체 지도가 있습니다. SPY의 정규장 일일 종가를 기준으로 한 쿼리 하나가 고점, 저점, 속도, 회복세를 포착하며, 비교를 위해 2008년 약세장(bear market)에 대해서도 동일한 측정을 수행했습니다.
| 고점 날짜 | 고점 종가 | 저점 날짜 | 저점 종가 | 하락률(%) | 고점-저점 세션 | 달력 일수 | -30% 도달 세션 | 2008 GFC -30% 도달 세션 | 회복 날짜 | 저점-회복 세션 |
|---|---|---|---|---|---|---|---|---|---|---|
| 2020-02-19 | 338.31 | 2020-03-23 | 222.51 | -34.2 | 23 | 33 | 22 | 250 | 2020-08-18 | 103 |
모든 수치 뒤에 숨겨진 정확한 SQL
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 dailiesSPY의 고점 종가는 2020-02-19에 기록된 $338.31였습니다. 2020-03-23에 기록된 저점 종가 $222.51는 고점 대비 -34.2% 하락한 수치로, 약세장이 23 거래일, 즉 33의 달력 일수 동안 압축적으로 진행되었음을 보여줍니다. 흔히 언급되는 "역사상 가장 빠른 30% 하락"이라는 주장은 같은 행에서 증명됩니다. SPY 종가가 고점 대비 30% 하락을 처음으로 돌파한 것은 불과 22 거래일 만이었습니다. 2007년 10월 고점 종가부터 동일하게 측정한 2008년 약세장은 같은 30% 하락을 기록하는 데 250 거래일이 소요되었습니다. 2008년에는 약 1년이 걸렸던 과정이 2020년에는 약 한 달 만에 일어난 것입니다.
이 페이지의 패널에서 모든 수치를 추출하여 구성한 폭락장의 연대기입니다.
- 2020년 2월 19일, SPY의 사상 최고 종가, $338.31.
- 3월 9일, 1997년 이후 첫 시장 전체 서킷브레이커(circuit breaker) 발동; SPY는 -7.7% 하락 마감. 아래에서 분 단위로 확인 가능.
- 3월 12일, 16일, 18일, 세 차례의 추가적인 1단계 거래 중단. 3월 16일은 -11.6% 하락하며 폭락장 중 최악의 단일 세션을 기록.
- 3월 23일, 종가 기준 저점: $222.51, 고점 대비 -34.2% 하락.
- 3월 24일, 전환점. 3월 24일의 부양책 랠리가 해당 장세를 주도함.
- 2020-08-18, SPY가 저점 이후 103 거래일 만에 다시 2월 고점을 상회하며 마감.
2020년 3월 9일: 서킷브레이커가 발동된 장세
시장 전체 서킷브레이커(market-wide circuit breakers)는 S&P 500 지수를 기준으로 작동하므로, 본 패널은 다른 대용 지표가 아닌 S&P 500 ETF인 SPY를 통해 거래 중단 상황을 분석한다. 직전 주말 동안 팬데믹에 따른 가격 재산정(repricing)과 원유 공급 충격(아래에서 상세 설명)이 맞물리면서, 시장은 사실상 정상적인 개장을 하지 못했다.
| 이전 종가 | 정규장 시가 | 갭 변동률(%) | 최초 거래정지 누락 시간(ET) | 거래정지 누락 시간(분) | 정규장 저가 | 저가 시간(ET) | 정규장 종가 | 일간 변동률(%) | 일간 거래량(백만) | 정규장 분봉 |
|---|---|---|---|---|---|---|---|---|---|---|
| 297.42 | 275.3 | -7.4 | 09:35 | 14 | 273.45 | 14:44 | 274.4 | -7.7 | 304.6 | 376 |
모든 수치 뒤에 숨겨진 정확한 SQL
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')두 가지 수치를 먼저 제시한다. 첫째, 갭(gap)이다. SPY는 275.3달러에 시가를 형성했는데, 이는 금요일 종가인 297.42달러보다 -7.4%달러 낮은 수준이었으며, 개장 후 몇 분 지나지 않아 S&P 500의 하락 폭은 1단계(Level-1) 임계치인 7%에 도달했다. 둘째, 더 중요한 수치로, 평소 390개인 정규장 분봉이 376개에 불과했다. 오전 9시 34분 이후 테이프(거래 기록)가 멈췄다. 09:35시(ET 기준)부터 14분 동안 연속으로 어떠한 바(bar)도 생성되지 않았다. 그 어떤 곳에서도 거래가 이루어지지 않은 것이다. 데이터상의 이 공백 자체가 곧 서킷브레이커를 의미한다. 해당 장은 304.6백만 주가 거래된 가운데 -7.7%달러 하락한 274.4달러로 마감했다.
거래 중단 세션의 형태
| 동부표준시(ET) | 구간 종가 | 구간 저가 | 거래량(백만) |
|---|---|---|---|
| 09:30 | 279.93 | 273.5 | 17.4 |
| 10:00 | 280.72 | 275.6 | 23.4 |
| 10:30 | 278.61 | 275.5 | 19.1 |
| 11:00 | 281.03 | 275.5 | 17.2 |
| 11:30 | 282.69 | 280.06 | 19.1 |
| 12:00 | 281.01 | 280.95 | 17.2 |
| 12:30 | 279.71 | 275.95 | 13.4 |
| 13:00 | 278.59 | 278.24 | 11.5 |
| 13:30 | 275.84 | 275.34 | 19.4 |
| 14:00 | 274.95 | 274.06 | 21.2 |
| 14:30 | 276.59 | 273.45 | 25.9 |
| 15:00 | 277.9 | 275.55 | 24.5 |
| 15:30 | 274.4 | 274.37 | 50.2 |
모든 수치 뒤에 숨겨진 정확한 SQL
SELECT
b.et_time AS et_time,
b.bucket_close AS bucket_close,
b.bucket_low AS bucket_low,
round((b.bar_shares + if(b.et_time = '15:30', p.print_shares, 0)) / 1e6, 1) AS shares_m
FROM
(
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,
toFloat64(sum(volume)) AS bar_shares
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
) AS b
CROSS JOIN
(
SELECT toFloat64(maxIf(size, has(conditions, 8))) AS print_shares
FROM global_markets.stocks_trades
WHERE ticker = 'SPY'
AND sip_timestamp >= toDateTime('2020-03-09 20:00:00', 'UTC')
AND sip_timestamp < toDateTime('2020-03-09 20:15:00', 'UTC')
) AS p
ORDER BY et_time오프닝 버킷(opening bucket)에는 폭락, 거래 중단, 그리고 재개가 한꺼번에 포함되어 있습니다. 해당 구간의 저점인 $273.5은 당일 전체 저점인 $273.45과 불과 몇 센트 차이였으며, 오후 14:44 ET에 기록된 거래는 오전의 저점 수준을 재확인했을 뿐입니다. 거래 재개 이후 테이프(tape, 실시간 호가 및 체결 정보)는 거의 움직이지 않았습니다. 30분 단위 종가는 모두 재개 시점 가격에서 몇 달러 범위 내에 머물렀으며, 당일의 손실은 장 초반 몇 분 만에 결정되었습니다. 거래량은 이와 반대되는 양상을 보였는데, 마감 흐름이 교차한 마지막 30분 동안 50.2백만 주가 거래되며 당일 가장 많은 거래량을 기록했습니다. 서킷브레이커(circuit breakers)는 정확히 이러한 형태를 만들어내도록 설계되었습니다. 즉, 급락을 멈추고 재개 경매(reopening auction)를 강제한 뒤, 재조정된 가격 수준에서 연속 매매가 재개되도록 하는 것입니다. 시장의 시계에는 이제 이러한 메커니즘이 영구적으로 내재되어 있습니다.
8거래일 동안 네 번의 거래 중단
3월 9일은 시작에 불과했습니다.
| 세션 | 종가($) | 변동률(%) | 거래량(백만) |
|---|---|---|---|
| 2020-03-09 | 274.4 | -7.7 | 304.6 |
| 2020-03-12 | 248.1 | -9.6 | 389.3 |
| 2020-03-16 | 239.41 | -11.6 | 291.5 |
| 2020-03-18 | 241.01 | -5.2 | 324.7 |
모든 수치 뒤에 숨겨진 정확한 SQL
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_dateLevel-1 서킷브레이커(시장 일시 중단 제도)는 3월 12일(-9.6% 마감), 3월 16일(1987년 이후 S&P 지수 최대 일간 하락폭을 기록하며 -11.6%에 $239.41로 마감), 3월 18일(장중 중단, -5.2% 마감)에도 발동되었습니다. 23년 동안 단 한 번도 없었던 시장 전체 거래 중단이 8거래일 만에 네 번이나 발생한 것입니다. 주목할 점은 한 번도 발생하지 않은 상황입니다. 모든 중단은 7% 하락 기준인 Level-1 단계에서 멈췄습니다. 13% 및 20% 하락 단계에는 도달하지 않았으며, 3월 16일에도 거래 중단 이후 하락세가 둔화되어 해당 세션은 Level-2 기준선 안쪽에서 마감되었습니다.
가장 큰 하락폭을 기록한 종목
지수 숫자는 그 이면에 숨겨진 분산도를 가린다. 대표적인 대형주 몇 개를 대상으로 동일한 일일 종가 산술 방식을 적용해 보면, 3월 9일 당일과 2월 19일부터 3월 23일까지 이어진 전체 하락장에서 폭락의 충격이 실제로 어디에 집중되었는지 알 수 있다.
| ticker | 3월 9일 대비 변동률(%) | 폭락률(%) |
|---|---|---|
| CCL | -19.9 | -72.3 |
| UAL | -10.4 | -66.9 |
| XOM | -12.2 | -47.9 |
| JPM | -13.7 | -42.6 |
| SPY | -7.7 | -34.2 |
| AAPL | -7.9 | -31 |
| WMT | -0.1 | -2.9 |
모든 수치 뒤에 숨겨진 정확한 SQL
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 ASC해당 패널에서 가장 큰 타격을 입은 종목은 크루즈 운영사인 CCL(Carnival)로, 3월 9일 하루에만 -19.9%가 하락했으며 고점 대비 저점까지는 -72.3%가 빠졌다. 유나이티드 항공은 폭락 기간 동안 -66.9%를 내주었고, 엑손모빌(ExxonMobil)은 -47.9%, JP모건(JPMorgan)은 -42.6% 하락했다. 이들과 비교하면 SPY의 -34.2% 하락은 거의 완만해 보이며, 애플(Apple)은 -31%로 시장과 비슷한 수준으로 하락했다. 반면 봉쇄 기간에도 영업을 지속한 식료품 및 필수재 기업인 월마트(Walmart)는 같은 기간 -2.9% 하락하는 데 그쳤다. 여행 및 에너지 부문은 멈춰버린 세계 경제에 맞춰 가격이 재조정되었으나, 필수 소비재는 거의 움직이지 않았다.
간략히 살펴보는 유가 전쟁
위의 에너지 관련 논쟁은 한 문단으로 설명할 가치가 있습니다. '유가 전쟁'이라는 용어는 3월 9일 기사의 나머지 절반을 담고 있기 때문입니다. 사우디아라비아와 러시아 간의 OPEC+ 생산량 협상은 2020년 3월 6일 금요일 합의 없이 종료되었습니다. 주말 동안 사우디아라비아는 공식 판매 가격을 인하하고, 여행 수요가 이미 급감하던 세계 시장에 생산량을 늘리겠다는 계획을 발표했습니다. 이는 수요 충격에 공급 충격이 겹친 상황이었습니다. 월요일 주식 시장 개장과 동시에 두 충격이 모두 반영되었으며, 그 결과는 위 패널에 나타나 있습니다. 당시 ExxonMobil은 월요일에 -12.2% 하락했고, SPY는 -7.7% 하락했습니다.
안전 자산 선호 현상과 그 흐름이 깨진 한 주
주식 시장은 전체 이야기의 절반에 불과했다. 나머지 절반은 미국 국채 시장이었는데, 이곳에서는 전형적인 안전 자산 선호 현상이 기록적인 수준까지 이어지다가 놀랍게도 한 주 동안 역행하는 모습을 보였다.
| 날짜 | 10년물 수익률(%) | 3개월물 수익률(%) |
|---|---|---|
| 2020-02-18 | 1.55 | 1.58 |
| 2020-02-19 | 1.56 | 1.58 |
| 2020-02-20 | 1.52 | 1.58 |
| 2020-02-21 | 1.46 | 1.56 |
| 2020-02-24 | 1.38 | 1.53 |
| 2020-02-25 | 1.33 | 1.53 |
| 2020-02-26 | 1.33 | 1.53 |
| 2020-02-27 | 1.3 | 1.45 |
| 2020-02-28 | 1.13 | 1.27 |
| 2020-03-02 | 1.1 | 1.13 |
| 2020-03-03 | 1.02 | 0.95 |
| 2020-03-04 | 1.02 | 0.72 |
| 2020-03-05 | 0.92 | 0.62 |
| 2020-03-06 | 0.74 | 0.45 |
| 2020-03-09 | 0.54 | 0.33 |
| 2020-03-10 | 0.76 | 0.44 |
| 2020-03-11 | 0.82 | 0.42 |
| 2020-03-12 | 0.88 | 0.33 |
| 2020-03-13 | 0.94 | 0.28 |
| 2020-03-16 | 0.73 | 0.24 |
모든 수치 뒤에 숨겨진 정확한 SQL
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 date10년 만기 국채 금리는 주식 시장이 정점에 달했던 2월 19일에 1.56%를 기록했다. 거래가 중단되었던 3월 9일, 금리는 사상 최저치인 0.54%로 마감했다. 이는 투자자들이 안전을 대가로 10년 동안 연 0.5%의 수익률을 감수한 결과였다. 이후 패턴이 반전되었다. 3월 18일까지 10년 만기 국채 금리는 1.18%로 상승한 반면, 주식은 계속 하락했다. 이는 '현금 확보를 위한 질주(dash for cash)' 현상으로, 펀드와 기업, 외국인 투자자들이 달러를 마련하기 위해 국채를 포함한 유동성 있는 모든 자산을 매도했던 한 주였다. 한편, 3개월 만기 국채는 같은 날 0.02%로 마감하며 현금성 자산이 제로 수준에 고정되었다. 가장 안전한 자산과 가장 위험한 자산이 동시에 하락할 때, 투자자들이 매수하는 대상은 바로 유동성 그 자체이다. 수익률 곡선(yield curve)은 이 사건을 역사 속에 영구히 기록하고 있다.
옵션 테이프가 보여주는 것
시장 헤지(hedging)의 대표적 장소인 SPY 상장 옵션은 공포에 대한 자체적인 기록을 남겼으며, 그 시점이 흥미로운 부분입니다.
| 세션 | 풋 옵션 계약 수(백만) | 콜 옵션 계약 수(백만) | 풋-콜 비율(PCR) |
|---|---|---|---|
| 2020-03-02 | 3.74 | 2.54 | 1.47 |
| 2020-03-03 | 3.14 | 2.24 | 1.4 |
| 2020-03-04 | 3.06 | 2.27 | 1.35 |
| 2020-03-05 | 3.14 | 1.82 | 1.73 |
| 2020-03-06 | 4.64 | 2.38 | 1.95 |
| 2020-03-09 | 4.35 | 2.38 | 1.83 |
| 2020-03-10 | 3.61 | 2.4 | 1.5 |
| 2020-03-11 | 3.75 | 2.44 | 1.54 |
| 2020-03-12 | 4.53 | 3.43 | 1.32 |
| 2020-03-13 | 4.63 | 3.27 | 1.41 |
모든 수치 뒤에 숨겨진 정확한 SQL
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 session풋/콜 거래량 비율(put/call volume ratio)은 거래 중단 세션 이전인 3월 6일 금요일에 1.95으로 정점을 찍었으며, 콜옵션 한 계약당 거의 두 계약의 풋옵션이 거래되었습니다. 3월 9일 당일에는 4.35백만 계약의 풋옵션이 2.38백만 계약의 콜옵션과 대비되어 거래되었으며, 비율은 1.83였습니다. -9.6% 세션이었던 3월 12일에는 풋옵션과 함께 콜옵션 거래량이 늘어나면서 해당 비율은 1.32로 완화되었습니다. 가장 강력한 풋 편향(put skew)은 하락의 바닥이 아닌 초기 단계에서 나타났습니다. 즉, 방어 수단은 초기에 매수되었고, 이후 더 큰 폭의 하락이 발생한 날에는 옵션 테이프가 보다 양방향적인 거래 양상을 보였습니다.
시장 전체 거래 중단(market-wide halt)의 실제 작동 방식
시장 전체 서킷브레이커(market-wide breakers)는 사용 빈도가 낮아 잊히기 쉽지만, 그 작동 원리는 다음과 같습니다. S&P 500 지수가 전일 종가 대비 7%(Level 1) 및 13%(Level 2) 하락할 경우, 오후 3시 25분(ET 기준) 이전에 발생하면 각각 15분간 거래가 중단됩니다. 20%(Level 3) 하락 시에는 해당 세션이 즉시 종료됩니다. 거래 중단 기간에는 모든 거래소에서 거래가 이루어지지 않으며, 주문은 재개 경매(reopening auction)를 위해 대기합니다. 이 재개 경매는 매일 아침 시가 경매(opening auction)와 동일한 방식으로 누적된 매수·매도 의사를 하나의 가격으로 집중시킵니다. 이러한 설계는 2010년 플래시 크래시(flash crash) 이후 도입되었습니다. 당시 기존의 임계치는 실제 시장 붕괴 상황에서도 작동하기에는 너무 느슨하다는 점이 드러났기 때문입니다.
2020년 3월은 해당 설계가 도입된 이후 현재까지 유일하게 실제 시장에서 테스트된 사례입니다. 위 패널에서 확인할 수 있듯이, 총 네 차례의 Level 1 중단이 발생했고 매번 질서 있게 거래가 재개되었습니다. Level 2나 Level 3까지 도달한 적은 없었으며, S&P 500 역사상 가장 빠른 대규모 하락장이었던 23번의 세션 동안 시장은 정상적으로 기능했습니다. 이후에도 규정은 그대로 유지되었습니다. S&P 500 지수를 기준으로 하는 7/13/20%의 임계치는 오늘날에도 동일하게 적용됩니다. 시스템은 유연하게 대응했고, 시장의 인프라는 견고했습니다.
COVID-19 폭락 관련 FAQ
2020년 3월 9일 서킷브레이커(circuit breaker)가 발동된 원인은 무엇인가?
S&P 500 지수가 개장 직후 전일 종가 대비 7% 하락하며 1단계 시장 전체 서킷브레이커 발동 기준에 도달했기 때문이다. 시장 전체 거래가 15분간 중단되었으며, 이후 경매(auction) 방식을 통해 거래가 재개되었다. 이 거래 중단은 본 페이지의 분 단위 테이프(minute tape)에서 14개의 연속된 누락 막대로 확인되며, 09:35 ET부터 시작되었다.
COVID-19 폭락 당시 주식 시장은 얼마나 하락했는가?
SPY의 일간 종가 기준으로 측정했을 때, -34.2%, 2020년 2월 19일 $338.31에서 2020년 3월 23일 $222.51까지 총 23 거래일 동안 하락했다.
2020년 3월에 서킷브레이커는 몇 번 발동되었는가?
3월 9일, 12일, 16일, 18일 총 네 차례의 1단계 시장 전체 거래 중단이 있었다. 이는 1997년 10월 이후 처음 있는 일이었다.
2020년에 2단계나 3단계 서킷브레이커가 발동된 적이 있는가?
없다. 2020년의 네 차례 중단은 모두 1단계(7%)였다. 현행 제도 하에서 2단계(13%)나 3단계(20%) 시장 전체 거래 중단이 발동된 적은 없으며, 폭락장에서 가장 하락 폭이 컸던 3월 16일에도 -11.6% 수준에 그쳐 발동되지 않았다.
주식 시장은 COVID-19 폭락에서 완전히 회복되었는가?
그렇다. SPY는 3월 23일 저점 이후 103 거래일이 지난 2020-08-18에 2020년 2월 19일 고점을 상회하며 마감했다. 이는 이 정도 규모의 약세장(bear market)에서 기록한 가장 빠른 완전 회복 사례 중 하나다.
위의 모든 패널은 과거 거래 데이터를 대상으로 하는 버전 관리된 쿼리 결과이며, SQL을 확장하면 각 측정값을 확인할 수 있다. 읽는 것 대신 당시 상황을 체감하고 싶은가? 이는 Strasmore Labs 트레이딩 시뮬레이터에서 플레이 가능한 시나리오 중 하나다.