Skip to main content

나스닥 100 요일별 수익률 분포 분석

Data
Macro
나스닥 100(NDX) 단타에서 롱은 월요일 본장 전, 숏은 목요일 본장 전에 진입하는게 기대손익비가 높을 수 있음
Author

gitSAM

Published

November 10, 2026

1 연구 배경 및 문제 정의

금융 시장의 전통적인 이상 현상(Market Anomaly) 중 하나인 요일 효과(Day-of-the-Week Effect)는 주로 주말 간 악재 반영에 따른 월요일의 음(-) 수익률과 주 후반 매수세 집중에 기반해 논의되어 왔다. 금융공학 초기 문헌이 지목한 주말 효과(Weekend Effect)는 최근 알고리즘 매매와 상장지수펀드(ETF) 패시브 자금 팽창, 파생상품 만기 구조 변화를 겪으며 다른 형태로 재편되고 있다.

Cboe(Chicago Board Options Exchange)가 2022년 하반기 나스닥 100(NDX) 및 S&P 500(SPX) 지수를 대상으로 화요일과 목요일 옵션 만기를 추가하면서 주 5일 전일 만기(Zero Days to Expiration, 0DTE) 체제가 안착되었다. 당일 만기 옵션 거래 비중이 지수 옵션 거래량의 40~50% 수준에 도달함에 따라, 시장 조성자(Market Maker)의 장중 델타 및 감마 헷징(Dynamic Hedging)이 요일별 변동성 형성에 직접적인 외생 변수로 작용한다.

나스닥 100 지수를 대상으로 최근 2년간의 일간 수익률 분포 특성과 지난 10년간의 요일별 중위값 시계열을 결합하여 시장 미세구조(Microstructure)의 레짐 전환(Regime Shift) 여부를 규명한다.

flowchart TD
    A["거시 경제 일정 (CPI, FOMC, 고용보고서)"] --> D["현물 지수(NDX) 요일별 수익률 왜곡"]
    B["주 5일 0DTE 옵션 만기 체제"] --> D
    C["주말 리스크 오프 및 월요일 숏커버링"] --> D
    D --> E["정규장(Open-to-Close) 미세구조 변화"]
    D --> F["야간(Close-to-Open) 갭 형성 양상"]

2 데이터 파이프라인 및 환경 설정

데이터셋은 Yahoo Finance API를 통해 나스닥 100 지수(^NDX, 2014-01-01 ~ 2026-11-10) 일간 데이터를 수집하고 ZSTD 압축 Parquet 형식으로 보관하여 재연산 비용을 최소화한다.

수익률은 세션별로 세 가지 축으로 분해하여 측정한다.

  1. 일간 총 수익률(Total Return): 전일 종가 대비 당일 종가 변동률 (\(Close_t / Close_{t-1} - 1\))
  2. 야간 오버나이트 수익률(Overnight Return): 전일 종가 대비 당일 시가 변동률 (\(Open_t / Close_{t-1} - 1\))
  3. 정규장 장중 수익률(Intraday Return): 당일 시가 대비 당일 종가 변동률 (\(Close_t / Open_t - 1\))
Code
import os
from pathlib import Path
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.available else 'default')
plt.rcParams['font.family'] = 'DejaVu Sans'
plt.rcParams['axes.unicode_minus'] = False

parquet_candidates = [Path("us_nasdaq_day.parquet"), Path("posts/us_nasdaq_day.parquet")]
parquet_path = next((p for p in parquet_candidates if p.exists()), Path("us_nasdaq_day.parquet"))

# 로컬 캐시 우선 로드, 부재 시 다운로드 수행
if parquet_path.exists():
    df = pd.read_parquet(parquet_path)
    if "Date" in df.columns:
        df["Date"] = pd.to_datetime(df["Date"])
        df = df.set_index("Date").sort_index()
else:
    df_raw = yf.download("^NDX", start="2014-01-01", progress=False)
    if isinstance(df_raw.columns, pd.MultiIndex):
        df_raw.columns = df_raw.columns.get_level_values(0)
    df = df_raw.copy()
    save_path = Path("posts/us_nasdaq_day.parquet") if Path("posts").exists() else Path("us_nasdaq_day.parquet")
    df.reset_index().to_parquet(save_path, engine="pyarrow", compression="zstd")

# 수익률(%) 및 날짜 변수 정의
df["Return_Total"] = df["Close"].pct_change() * 100
df["Return_Overnight"] = ((df["Open"] - df["Close"].shift(1)) / df["Close"].shift(1)) * 100
df["Return_Intraday"] = ((df["Close"] - df["Open"]) / df["Open"]) * 100
df["Year"] = df.index.year
df["Day_Name"] = df.index.day_name()

weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

3 최근 2개년 요일별 일간 수익률 분포

0DTE 만기가 일상화된 최근 2개년(2024~2026년) 구간을 추출하여 요일별 일간 수익률의 중심 경향치(중위값, 평균) 및 산포도(IQR, 표준편차), 비대칭성(왜도)을 집계한다.

Code
cutoff_2y = df.index.max() - pd.DateOffset(years=2)
recent_2y = df[df.index >= cutoff_2y].copy()

dist_2y = recent_2y.groupby("Day_Name")["Return_Total"].agg(
    count="count",
    median="median",
    mean="mean",
    std="std",
    q25=lambda x: np.percentile(x.dropna(), 25),
    q75=lambda x: np.percentile(x.dropna(), 75),
    iqr=lambda x: np.percentile(x.dropna(), 75) - np.percentile(x.dropna(), 25),
    skew=lambda x: x.skew()
).reindex(weekdays)

dist_2y.round(3)
count median mean std q25 q75 iqr skew
Day_Name
Monday 97 0.361 0.336 1.275 -0.338 1.091 1.429 -0.101
Tuesday 104 -0.068 0.031 1.161 -0.731 0.687 1.419 0.243
Wednesday 102 0.215 0.271 1.606 -0.289 0.780 1.069 3.654
Thursday 98 -0.129 -0.246 1.521 -0.689 0.689 1.378 -1.019
Friday 99 0.328 -0.066 1.450 -0.663 0.857 1.520 -1.339
Code
fig, ax = plt.subplots()
sns.boxplot(
    data=recent_2y, 
    x="Day_Name", 
    y="Return_Total", 
    order=weekdays, 
    hue="Day_Name",
    legend=False,
    palette="Blues", 
    width=0.45,
    ax=ax
)
sns.stripplot(
    data=recent_2y, 
    x="Day_Name", 
    y="Return_Total", 
    order=weekdays, 
    color="black", 
    alpha=0.25, 
    jitter=0.2, 
    size=4,
    ax=ax
)
ax.axhline(0, color="crimson", linestyle="--", linewidth=1.2, alpha=0.8)
ax.set_title("Recent 2-Year NDX Daily Return Distribution by Weekday (%)", fontsize=12, pad=12)
ax.set_xlabel("Weekday", labelpad=8)
ax.set_ylabel("Daily Return (%)", labelpad=8)
plt.tight_layout()
plt.show()

최근 2개년 나스닥 100 요일별 일간 수익률 분포 및 바이올린 플롯

3.1 분포 관측치 해석

집계된 표와 분포 차트에서 세 가지 비대칭적 양상이 도출된다.

첫째, 월요일의 강한 상방 편향이다. 월요일 수익률 중위값은 +0.361%로 평일 5일 중 가장 높으며, 평균치 또한 +0.336%로 견고하다. 사분위 범위(IQR) 역시 1.429%p 수준으로 통제되어 있으며 왜도는 -0.101에 불과하여 대칭에 가까운 견조한 우상향 분포를 형성한다.

둘째, 목요일의 기조적 약세다. 목요일은 중위값 -0.129%, 평균 -0.246%로 5개 요일 중 유일하게 중심 경향치가 뚜렷한 음(-)의 영역에 위치한다. 표준편차는 1.521%로 높고 왜도가 -1.019에 달해 하방 꼬리(Fat Tail)의 두께가 두드러진다. 이는 주간 실업수당 청구건수 발표와 주 후반 리스크 관리성 헤지 매도가 목요일 정규장에 집중되는 현실을 투영한다.

셋째, 금요일의 괴리 현상이다. 금요일의 중위값은 +0.328%로 높게 형성되지만 평균치는 -0.066%로 마이너스 전환된다. 왜도가 -1.339로 관측 요일 중 가장 극단적인 좌측 꼬리를 기록한다. 평상시에는 옵션 핀 효과에 힘입어 완만한 상승세로 마감하는 거래일이 다수이나, 비농업 고용지표나 CPI 충격이 터질 때의 하락 낙폭이 대단히 깊어 산술평균을 심각하게 잠식함을 뜻한다.

4 10개년 연도별 시계열 및 국면 전환

2017년부터 2026년까지 10개년에 걸친 연도별 × 요일별 일간 수익률 중위값(%) 피벗 매트릭스를 구성하여 거시 환경 변화에 따른 요일 효과의 영속성을 추적한다.

Code
recent_10y = df[df["Year"] >= 2017].copy()
pivot_median_10y = recent_10y.pivot_table(
    index="Year",
    columns="Day_Name",
    values="Return_Total",
    aggfunc="median"
)[weekdays]

pivot_median_10y.round(3)
Day_Name Monday Tuesday Wednesday Thursday Friday
Year
2017 0.118 0.151 0.189 -0.074 0.216
2018 0.234 0.318 0.084 0.016 -0.125
2019 0.084 0.141 0.289 0.181 0.125
2020 0.819 0.263 0.399 0.322 -0.034
2021 0.094 -0.058 0.110 0.579 0.292
2022 -0.305 -0.172 -0.067 -0.442 -0.396
2023 0.341 0.093 0.003 0.180 0.085
2024 0.209 0.142 0.078 0.000 0.171
2025 0.400 0.009 0.242 -0.034 0.303
2026 0.293 -0.125 0.141 -0.204 0.269
Code
plt.figure()
sns.heatmap(
    pivot_median_10y, 
    annot=True, 
    fmt=".2f", 
    cmap="vlag", 
    center=0, 
    cbar_kws={'label': 'Median Return (%)'},
    linewidths=0.5
)
plt.title("Yearly Median Daily Return by Weekday (2017–2026)", fontsize=12, pad=12)
plt.xlabel("Weekday", labelpad=8)
plt.ylabel("Year", labelpad=8)
plt.tight_layout()
plt.show()

연도별 x 요일별 나스닥 100 일간 수익률 중위값 (%) 히트맵

4.1 시계열 히트맵 해석

히트맵은 요일 효과가 단일 연도의 노이즈가 아닌 매크로 사이클 및 시장 구조와 밀접하게 연동됨을 보여준다.

첫째, 현대적 월요일 효과의 지속성이다. 2022년 금리 급인상 하락장(-0.305%)을 제외하면, 2017년부터 2026년까지 9개 연도에서 월요일 중위값은 예외 없이 양(+)의 영역을 유지했다. 2020년(+0.819%), 2023년(+0.341%), 2024년(+0.209%), 2025년(+0.400%), 2026년(+0.293%)에 걸쳐 월요일 강세는 구조적 패턴으로 확립되었다. 전통적인 주말 효과 가설(월요일 약세)은 현대 미국 기술주 시장에서 완전히 기각된다.

둘째, 약세장 레짐의 요일별 균열이다. 시장 전체가 30% 이상 폭락했던 2022년에는 평일 5개 요일의 중위값이 일제히 음수로 반전되었다. 그중에서도 목요일(-0.442%)과 금요일(-0.396%), 월요일(-0.305%) 순으로 주 후반과 주초의 투매가 두드러졌다.

셋째, 고금리 장기화 구간(2024~2026년)에서의 목요일 둔화 경향이다. 2024년 0.000%, 2025년 -0.034%, 2026년 -0.204%로 목요일 수익률 중위값은 3년 연속 하향 경로를 밟고 있다.

5 0DTE 체제 전환 전후 구조 비교 (Pre vs Post)

파생상품 미세구조 효과를 명확히 분리하기 위해 코로나19 충격 및 양적완화 왜곡기(2020~2022년)를 버퍼로 격리하고, 0DTE 도입 이전 안정적 상승기(Pre-0DTE, 2017~2019년)와 0DTE 전일 만기 정착기(Post-0DTE, 2023~2026년)를 직접 비교한다.

Code
pre_df = df[(df.index >= "2017-01-01") & (df.index <= "2019-12-31")].copy()
post_df = df[df.index >= "2023-01-01"].copy()

comp_table = pd.DataFrame({
    "Pre_Median": pre_df.groupby("Day_Name")["Return_Total"].median(),
    "Post_Median": post_df.groupby("Day_Name")["Return_Total"].median(),
    "Pre_Std": pre_df.groupby("Day_Name")["Return_Total"].std(),
    "Post_Std": post_df.groupby("Day_Name")["Return_Total"].std(),
    "Pre_Skew": pre_df.groupby("Day_Name")["Return_Total"].skew(),
    "Post_Skew": post_df.groupby("Day_Name")["Return_Total"].skew()
}).reindex(weekdays)

comp_table.round(3)
Pre_Median Post_Median Pre_Std Post_Std Pre_Skew Post_Skew
Day_Name
Monday 0.159 0.298 1.169 1.103 -0.880 -0.219
Tuesday 0.166 0.053 0.980 1.120 -0.430 0.039
Wednesday 0.180 0.136 1.138 1.434 0.007 2.650
Thursday 0.029 -0.047 1.011 1.452 -0.636 -0.593
Friday 0.123 0.160 1.124 1.313 -0.213 -0.981
Code
fig, axes = plt.subplots(2, 1, figsize=(6, 6))

med_df = comp_table[["Pre_Median", "Post_Median"]].rename(
    columns={"Pre_Median": "Pre-0DTE (2017-19)", "Post_Median": "Post-0DTE (2023-26)"}
)
med_df.plot(
    kind="bar", 
    ax=axes[0], 
    color=["#90caf9", "#1565c0"],
    edgecolor="black",
    linewidth=0.5
)
axes[0].set_title("Median Return: Pre vs Post 0DTE (%)", fontsize=11)
axes[0].set_ylabel("Median Return (%)")
axes[0].set_xlabel("Weekday")
axes[0].axhline(0, color="gray", linestyle="--", linewidth=0.8)
axes[0].set_xticklabels(weekdays, rotation=0)

std_df = comp_table[["Pre_Std", "Post_Std"]].rename(
    columns={"Pre_Std": "Pre-0DTE (2017-19)", "Post_Std": "Post-0DTE (2023-26)"}
)
std_df.plot(
    kind="bar", 
    ax=axes[1], 
    color=["#b0bec5", "#37474f"],
    edgecolor="black",
    linewidth=0.5
)
axes[1].set_title("Volatility (Std Dev): Pre vs Post 0DTE (%)", fontsize=11)
axes[1].set_ylabel("Standard Deviation (%)")
axes[1].set_xlabel("Weekday")
axes[1].set_xticklabels(weekdays, rotation=0)

plt.tight_layout()
plt.show()

0DTE 도입 전후 요일별 중위값 및 변동성(표준편차) 비교

5.1 체제 비교 해석

Pre 구간과 Post 구간의 지표 대조 결과는 파생상품 도입이 현물 시장 변동성에 미친 영향을 분명히 드러낸다.

첫째, 변동성(표준편차)의 전반적 레벨업이다. Pre-0DTE 기간에는 평일 5개 요일의 일간 표준편차가 0.98%~1.17% 범위 내에서 매우 균일했다. 반면 Post-0DTE 기간에는 수요일(1.434%), 목요일(1.452%), 금요일(1.313%) 등 주 중반 이후의 표준편차가 1.3~1.45% 수준으로 가파르게 확장되었다.

둘째, 금요일 왜도의 비대칭 심화다. 금요일 왜도는 Pre 기간 -0.213에서 Post 기간 -0.981로 음의 왜곡이 급증했다. 옵션 만기 당일 딜러 감마 포지션이 숏 감마 상태로 내몰릴 때 발생하는 델타 헷징 폭포(Delta Hedging Cascade)가 금요일 지수 급락의 빈도와 깊이를 심화시킨 결과로 해석된다.

셋째, 월요일 중위값 탄력성 강화다. 월요일 중위값은 0.159%에서 0.298%로 약 1.87배 증가했고 왜도는 -0.880에서 -0.219로 오히려 축소되었다. 0DTE 옵션이 활성화된 환경에서도 월요일은 주말 리스크 해소에 따른 상방 모멘텀이 안정적으로 작동함을 시사한다.

6 정규장(Intraday) vs 야간(Overnight) 세션 분해

요일 효과가 장 마감 후 발생한 정보(장외 실적 발표, 거시 뉴스)의 오버나이트 갭에서 유래하는지, 본장 개장 후 딜러 수급 및 알고리즘 집행 과정에서 생성되는지 분해한다.

Code
session_decomp = recent_2y.groupby("Day_Name")[
    ["Return_Overnight", "Return_Intraday", "Return_Total"]
].median().reindex(weekdays)

session_decomp.round(3)
Price Return_Overnight Return_Intraday Return_Total
Day_Name
Monday 0.256 0.204 0.361
Tuesday 0.070 0.084 -0.068
Wednesday 0.151 0.045 0.215
Thursday 0.054 -0.093 -0.129
Friday 0.127 0.099 0.328
Code
fig, ax = plt.subplots()
sess_df = session_decomp[["Return_Overnight", "Return_Intraday"]].rename(
    columns={
        "Return_Overnight": "Overnight (Close-to-Open)",
        "Return_Intraday": "Intraday (Open-to-Close)"
    }
)
sess_df.plot(
    kind="bar", 
    ax=ax, 
    color=["#42a5f5", "#ab47bc"],
    edgecolor="black",
    linewidth=0.5
)
ax.axhline(0, color="gray", linestyle="--", linewidth=0.8)
ax.set_title("Decomposition of Weekday Returns: Overnight vs Intraday Median (%)", fontsize=12, pad=10)
ax.set_ylabel("Median Return (%)", labelpad=8)
ax.set_xlabel("Weekday", labelpad=8)
ax.set_xticklabels(weekdays, rotation=0)
plt.tight_layout()
plt.show()

최근 2개년 요일별 야간(Overnight) vs 정규장(Intraday) 중위값 분해 (%)

6.1 세션 분해 해석

정규장과 야간 세션 분해 결과는 요일별 수급 압력의 원천을 명료하게 보여준다.

첫째, 월요일 수익률은 야간과 본장의 쌍방 기여다. 월요일의 총 수익률 중위값(+0.361%)은 야간 갭 상승(+0.256%)과 정규장 매수 흐름(+0.204%)이 균형 있게 결합된 결과다. 주말 간 누적된 매수 심리가 개장 전 지수선물 상승으로 1차 표출되고, 정규장 개장 후에도 추종 매수세가 이어졌다.

둘째, 목요일 하락은 정규장 매도 압력의 산물이다. 목요일의 야간 중위값은 +0.054%로 소폭 상승 출발했으나, 정규장 장중 중위값은 -0.093%로 급락 반전하여 총 수익률을 마이너스(-0.129%)로 떨어뜨렸다. 장외 정보의 악화라기보다, 개장 후 진행되는 매크로 지표 소화와 0DTE 만기 대응 매도 헤징이 본장 하방 압력의 주원인이다.

셋째, 수요일과 금요일의 성격 차이다. 수요일은 야간 갭(+0.151%)이 정규장(+0.045%) 대비 지수 상승을 주도한 반면, 금요일은 야간(+0.127%)과 정규장(+0.099%) 모두 완만한 플러스 중위값을 유지하며 정규장 방어력을 입증했다.

7 실증 분석 요약 및 시사점

실제 데이터를 통해 검증한 나스닥 100 요일별 미세구조의 결과는 다음과 같다.

  1. 월요일 이상 현상의 현대적 재정립: 과거 금융공학 이론의 주말 효과(월요일 약세)와 달리, 현대 나스닥 100 지수는 월요일에 일관되고 강력한 상방 중위값(+0.30%~+0.36%)을 기록한다.
  2. 목요일 정규장 약세 편향: 목요일은 5개 요일 중 유일하게 정규장 장중 중위값이 음수(-0.093%)를 나타내며 총 수익률의 하방 이탈을 이끌었다.
  3. 0DTE 도입에 따른 변동성 구조 왜곡: 2022년 하반기 Cboe의 전일 옵션 만기 도입 이후 주 후반(수·목·금) 일간 변동성이 1.3~1.45%대로 확대되었으며, 특히 금요일 왜도가 -0.98 수준으로 급락하여 하방 꼬리 위험이 심화되었다.