ALGOLAB · 정직 검증 — 커버드콜 편

같은 나스닥100인데,
배당 11.6%가 배당 0.4%에게 3배로 졌습니다

월배당 커버드콜 ETF QYLD와 그냥 지수 ETF QQQ1000만원씩 넣고 2013년 12월부터 2026년 8월까지 12년을 실측했습니다. 시뮬레이션이 아니라 실물 ETF의 가격과 분배금 실지급 기록입니다. 분배금을 한 푼도 안 쓰고 전부 재투자해도 2831만원 vs 9411만원. 매달 현금으로 받아 썼다면 계좌에 남은 돈은 730만원이었습니다.

2831만 vs 9411만
분배금 전액 재투자 · 12년
730만원
분배금을 현금으로 받은 경우 남은 원금
1번 / 14년
연 총수익으로 QYLD가 이긴 해
재현 코드 받기 (무료) 한계 먼저 읽기

세 가지 시나리오, 전부 실측

1000만원 · 2013-12-12 ~ 2026-08-27 (기준일 고정) · 만원 단위

시나리오QYLDQQQ
A. 분배금 전액 재투자 (총수익)2831만9411만
B. 분배금 현금 수령 — 남은 원금730만8488만
B. 받은 분배금 누적1126만274만
B. 합계 (원금 + 분배금)1856만8762만
C. 분배금 15% 원천징수 후 재투자2311만9267만
최대낙폭 (재투자 기준)-25%-35%
QYLD는 12년 동안 분배금을 147번, 사실상 매달 지급했습니다. 1000만원 기준 한 달 평균 7.4만원. 그 약속은 지켰습니다. 대신 지수가 오를 때의 상승분을 콜옵션으로 팔아 분배금을 만들기 때문에, 오르는 해의 상승을 따라가지 못합니다. 2020년 QQQ가 +48.4%일 때 QYLD는 +8.7%였습니다.

연도별 총수익 — 이긴 해까지 전부 공개

배당 재투자 기준 · 커버드콜이 이긴 해는 2022년 하락장 한 번

연도QYLDQQQ승자
2014+3.4%+19.2%QQQ
2015+6.5%+9.4%QQQ
2016+3.0%+7.1%QQQ
2017+18.1%+32.7%QQQ
2018-3.1%-0.1%QQQ
2019+22.7%+39.0%QQQ
2020+8.7%+48.4%QQQ
2021+10.4%+27.4%QQQ
2022-19.1%-32.6%QYLD
2023+22.8%+54.9%QQQ
2024+19.4%+25.6%QQQ
2025+9.3%+20.8%QQQ
2026 (8월까지)+12.1%+17.7%QQQ
하락 완충은 사실입니다 — 2022년에 13.5%p 덜 떨어졌고 최대낙폭도 -25%로 QQQ(-35%)보다 얕습니다. 그런데 2018년처럼 살짝 빠진 해에는 오히려 더 잃었습니다. S&P500으로 같은 계산을 해도(XYLD 2904만 vs SPY 6122만), 시작일을 2018년·2021년 고점·2022년 바닥으로 바꿔도 순위는 한 번도 뒤집히지 않았습니다.

배당 투자가 문제가 아니었습니다 — 자라는 배당

주당 연 분배금 · 2014년 → 2025년 실측

ETF2014년 주당2025년 주당변화
SCHD (배당성장)$0.35$1.053.0배
QYLD (커버드콜)$2.38$2.04-14%
SCHD를 2013년 12월에 산 사람은 지금 처음 산 가격 기준으로 한 해 8.8%를 배당으로 받습니다. 배당을 현금으로 다 써도 계좌에는 2940만원이 남아 있고, 재투자 총수익은 4446만원 — 같은 기간 S&P500(5372만)의 83%를 따라가면서 배당이 3배로 자랐습니다. 배당 ETF를 고를 때는 지금 배당률이 아니라 배당이 자라고 있는지를 보세요.

이 계산의 한계 — 접지 않고 그대로 둡니다

① 세전 · 미국 상장 기준. 미국 원천징수 15%는 시나리오 C로 반영했지만 국내 종합과세·건보료는 사람마다 달라 뺐습니다. 환율도 반영하지 않았습니다(두 ETF 모두 달러라 비교의 방향은 안 바뀝니다).
② 국내 상장 커버드콜 ETF는 못 쟀습니다. 대부분 2023년 이후 상장이라 12년 검증 자체가 불가능합니다. 같은 구조(콜옵션 매도)라는 것까지만 말할 수 있습니다.
③ 과거 실측이지 예측이 아닙니다. 앞으로 12년이 지난 12년과 같다는 보장은 어디에도 없습니다.
④ 커버드콜이 항상 틀렸다는 뜻도 아닙니다. 매달 현금이 반드시 필요한 은퇴 생활자에게는 도구가 될 수 있습니다. 다만 그 현금의 재료가 내 계좌의 상승분이라는 것을 알고 선택해야 합니다.

재현 코드 — 전부 무료 공개

표준 라이브러리만 씁니다. 파이썬만 있으면 pip 설치 없이 그대로 돌아갑니다.

파이썬 설치python.org에서 3.8 이상.

아래 코드 저장covered_call_backtest.py 이름으로 저장하거나 여기서 내려받기.

실행python covered_call_backtest.py. 야후 파이낸스에서 데이터를 받아 위 표의 모든 숫자를 다시 만듭니다.

기준일을 영상 제작일(2026-08-27)로 고정해 뒀습니다. 그래서 언제 돌려도 이 페이지·영상과 같은 숫자가 나옵니다. 오늘까지 데이터로 보려면 코드 상단의 ASOFNone으로 바꾸세요 — 시세가 움직인 만큼 숫자가 달라지는 게 정상입니다.
covered_call_backtest.py 다운로드
# -*- coding: utf-8 -*-
# =============================================================================
# 커버드콜 ETF 12년 실측 — AlgoLab (algolab.co.kr/coveredcall)
#
# 영상 "커버드콜 ETF 12년, 원금이 730만원 남았습니다"의 재현 코드입니다.
# 표준 라이브러리만 씁니다(pip 설치 불필요). 파이썬 3.8+ 에서:
#
#   python covered_call_backtest.py
#
# 하는 일:
#   1) 야후 파이낸스에서 QYLD·QQQ·XYLD·SPY·SCHD 일봉과 분배금 내역을 받는다
#   2) 1000만원을 넣고 세 가지로 계산한다
#      A. 분배금 전액 재투자(총수익)  B. 분배금 현금 수령  C. 분배금에 15% 원천징수 후 재투자
#   3) 연도별 총수익, 주당 분배금 성장까지 영상의 모든 수치를 다시 만든다
#
# ⚠ ASOF 를 영상 기준일로 고정했습니다. 오늘까지 데이터로 보려면 None 으로 바꾸세요.
#   (고정하지 않으면 시세가 움직여 영상과 숫자가 달라집니다 — 오류가 아닙니다)
# =============================================================================
import datetime
import json
import urllib.request

ASOF = datetime.date(2026, 8, 27)   # 영상 기준일. 최신으로 보려면 None
INIT = 1000.0                       # 만원


def fetch(sym):
    u = (f"https://query1.finance.yahoo.com/v8/finance/chart/{sym}"
         f"?range=20y&interval=1d&events=div%2Csplit")
    req = urllib.request.Request(u, headers={"User-Agent": "Mozilla/5.0"})
    j = json.loads(urllib.request.urlopen(req, timeout=40).read())
    r = j["chart"]["result"][0]
    ts = r["timestamp"]
    close = r["indicators"]["quote"][0]["close"]
    adj = r["indicators"]["adjclose"][0]["adjclose"]
    rows = []
    for t, c, a in zip(ts, close, adj):
        if c is None or a is None:
            continue
        d = datetime.date.fromtimestamp(t)
        if ASOF and d > ASOF:
            continue
        rows.append((d, c, a))
    divs = []
    for v in (r.get("events", {}).get("dividends", {}) or {}).values():
        d = datetime.date.fromtimestamp(v["date"])
        if ASOF and d > ASOF:
            continue
        divs.append((d, v["amount"]))
    divs.sort()
    return rows, divs


def reinvest(rows, d0):
    """A. 분배금 전액 재투자 = adjclose 총수익"""
    seg = [r for r in rows if r[0] >= d0]
    return INIT * seg[-1][2] / seg[0][2]


def take_cash(rows, divs, d0, tax=0.0):
    """B. 분배금 현금 수령 — 수량 고정. (남은 평가액, 받은 분배금 합계)"""
    seg = [r for r in rows if r[0] >= d0]
    units = INIT / seg[0][1]
    cash = sum(units * amt * (1 - tax) for d, amt in divs if seg[0][0] <= d <= seg[-1][0])
    return units * seg[-1][1], cash


def reinvest_after_tax(rows, divs, d0, tax=0.15):
    """C. 분배금에 세금 떼고 그날 종가로 재투자"""
    seg = [r for r in rows if r[0] >= d0]
    di = dict(divs)
    units = INIT / seg[0][1]
    for d, c, a in seg:
        if d in di:
            units += units * di[d] * (1 - tax) / c
    return units * seg[-1][1]


def yearly(rows, d0):
    seg = [r for r in rows if r[0] >= d0]
    out = {}
    for y in range(seg[0][0].year, seg[-1][0].year + 1):
        m = [i for i, r in enumerate(seg) if r[0].year == y]
        if len(m) < 10:
            continue
        prev = seg[m[0] - 1][2] if m[0] > 0 else seg[m[0]][2]
        out[y] = seg[m[-1]][2] / prev - 1
    return out


def year_div(divs, y):
    return sum(a for d, a in divs if d.year == y)


def main():
    data = {s: fetch(s) for s in ("QYLD", "QQQ", "XYLD", "SPY", "SCHD")}
    d0 = data["QYLD"][0][0][0]          # QYLD 상장일 = 2013-12-12
    print(f"구간: {d0} ~ {data['QYLD'][0][-1][0]}  (1000만원 기준, 만원 단위)\n")

    print("[나스닥100] 같은 지수, 두 ETF")
    for sym in ("QYLD", "QQQ"):
        rows, divs = data[sym]
        a = reinvest(rows, d0)
        b_val, b_cash = take_cash(rows, divs, d0)
        c = reinvest_after_tax(rows, divs, d0)
        print(f"  {sym:5s} 재투자 {a:7.0f}만 | 현금수령: 남은 돈 {b_val:6.0f}만"
              f" + 받은 배당 {b_cash:6.0f}만 = {b_val + b_cash:7.0f}만 | 세후재투자 {c:7.0f}만")

    print("\n[S&P500] 같은 비교 — 부호가 유지되는가")
    d0x = data["XYLD"][0][0][0]
    for sym in ("XYLD", "SPY"):
        print(f"  {sym:5s} 재투자 {reinvest(data[sym][0], d0x):7.0f}만  (시작 {d0x})")

    print("\n[연도별 총수익] QYLD vs QQQ — 커버드콜이 이긴 해")
    yq = yearly(data["QYLD"][0], d0)
    yb = yearly(data["QQQ"][0], d0)
    wins = [y for y in yq if y in yb and yq[y] > yb[y]]
    for y in sorted(yq):
        if y in yb:
            mark = " ← QYLD 승" if y in wins else ""
            print(f"  {y}  QYLD {yq[y]*100:+6.1f}%   QQQ {yb[y]*100:+6.1f}%{mark}")
    print(f"  → QYLD가 이긴 해 {len(wins)}번")

    print("\n[주당 연 분배금] 배당이 자라는가 (2014 → 2025)")
    for sym in ("SCHD", "QYLD"):
        v14 = year_div(data[sym][1], 2014)
        v25 = year_div(data[sym][1], 2025)
        print(f"  {sym:5s} ${v14:.2f} → ${v25:.2f}  ({v25 / v14:.2f}배)")

    rows, divs = data["SCHD"]
    seg0 = [r for r in rows if r[0] >= d0][0]
    print(f"\n[SCHD] 2013-12 매수가 기준 지금 시가배당률(YoC): "
          f"{year_div(divs, 2025) / seg0[1] * 100:.1f}%")
    print(f"  SCHD 재투자 {reinvest(rows, d0):.0f}만 · "
          f"같은 기간 SPY {reinvest(data['SPY'][0], d0):.0f}만")

    print("\n[민감도] 시작일을 바꿔도 순위가 유지되는가 (재투자)")
    for dd in (datetime.date(2018, 1, 2), datetime.date(2021, 11, 19),
               datetime.date(2022, 12, 28)):
        a = reinvest(data["QYLD"][0], dd)
        b = reinvest(data["QQQ"][0], dd)
        print(f"  {dd} 시작  QYLD {a:6.0f}만  QQQ {b:6.0f}만")

    print("\n한계: 미국 상장 ETF 세전 기준, 환율·국내 세금 미반영. 과거 실측이지 예측이 아닙니다.")


if __name__ == "__main__":
    main()
Strategy Lab · 이 검증 더 보기
내 전략도 같은 잣대로 검증해드립니다 — 제작 전 백테스트 상담 → 이 검증을 영상으로 보기4분 14초 매매 비용 실측 — 3393만원 vs 12만원비용 실측 24종목을 샀는데 실질 베팅 수는 1.06분산 실측 전략 검증 전체 보기 →
본 페이지는 정보 제공 목적이며 특정 상품의 매수·매도 추천이 아닙니다. 과거 성과는 미래 수익을 보장하지 않습니다. 데이터: 야후 파이낸스 조정 종가(배당 재투자 반영)·분배금 실지급 내역. 기준일 2026-08-27 고정. 투자 판단과 책임은 본인에게 있습니다. — AlgoLab