# -*- coding: utf-8 -*-
# 정밀 확인: ① 진짜 0인가 ② 3배가 1배를 이기는 임계 변동성 ③ 회복 소요기간
import csv, datetime, math, os
HERE = os.path.dirname(os.path.abspath(__file__))

def load(slug):
    out = {}
    with open(os.path.join(HERE, f"lev_{slug}_daily.csv"), encoding="utf-8") as f:
        for r in csv.DictReader(f):
            out[datetime.date.fromisoformat(r["date"])] = float(r["close"])
    return out

QQQ, SPY, IRX = load("qqq"), load("spy"), load("irx")
_rf = {}
def rf_on(d):
    if not _rf:
        prev = 0.05
        for x in sorted(IRX):
            v = IRX[x] / 100.0
            if v == v and v >= 0: prev = v
            _rf[x] = prev
        _rf["_k"] = sorted(IRX)
    if d in _rf: return _rf[d]
    ks = [x for x in _rf["_k"] if x <= d]
    return _rf[ks[-1]] if ks else 0.05

def rets(px, d0=None, d1=None):
    ds = sorted(d for d in px if (d0 is None or d >= d0) and (d1 is None or d <= d1))
    return [(ds[i], px[ds[i]] / px[ds[i-1]] - 1) for i in range(1, len(ds))]

def sim(px, lev, er, spread=0.005, d0=None, d1=None):
    path, eq = [], 1.0
    for d, r in rets(px, d0, d1):
        eq *= (1 + lev*r - (lev-1)*(rf_on(d)+spread)/252.0 - er/252.0)
        eq = max(eq, 1e-12)
        path.append((d, eq))
    return path

def base(px, d0=None, d1=None):
    path, eq = [], 1.0
    for d, r in rets(px, d0, d1):
        eq *= (1+r); path.append((d, eq))
    return path

L = []
q0 = min(QQQ)
p3 = sim(QQQ, 3.0, 0.0095, 0.005, q0)
p1 = base(QQQ, q0)
peak = 0.0; trough = (None, 9e9, None)
for d, v in p3:
    peak = max(peak, v)
    if v/peak - 1 < trough[1]: trough = (d, v/peak - 1, v)
L.append("① QQQ 3배 시뮬 — 진짜 0이 됐나?")
L.append(f"   최저점 {trough[0]}  고점대비 {trough[1]*100:.3f}%  (시작 1.0 기준 잔액 {trough[2]:.6f})")
L.append(f"   = 1억을 넣었으면 {trough[2]*1e8:,.0f}원")
mn = min(v for _, v in p3)
L.append(f"   전구간 최저 누적배수 {mn:.8f}  (0으로 클램프 안 됨: {mn>1e-12})")
# 1배 기준 같은 날
d1x = dict(p1)
L.append(f"   같은 날 QQQ 1배 누적 {d1x[trough[0]]:.4f}배 (고점 대비 -{(1-d1x[trough[0]]/max(v for dd,v in p1 if dd<=trough[0]))*100:.1f}%)")

L.append("")
L.append("② 3배가 1배를 이기는 임계 변동성  (L·μ - L²σ²/2 = μ - σ²/2  →  σ* = √(2μ/(L+1)))")
for name, px, d0 in (("QQQ 1999~2026", QQQ, q0), ("SPY 1993~2026", SPY, min(SPY))):
    rs = [r for _, r in rets(px, d0)]
    m = sum(rs)/len(rs); mu = m*252
    var = sum((r-m)**2 for r in rs)/(len(rs)-1)*252
    sd = math.sqrt(var)
    star = math.sqrt(2*mu/4)      # L=3
    L.append(f"   {name}: μ={mu*100:.2f}%  σ={sd*100:.2f}%  →  임계 σ*={star*100:.2f}%  "
             f"{'3배 불리 (σ > σ*)' if sd > star else '3배 유리 (σ < σ*)'}  차이 {(sd-star)*100:+.2f}%p")

L.append("")
L.append("③ 닷컴 고점(2000-03-24) 매수 후 원금 회복까지")
for tag, px, lev, er in (("QQQ 1배", QQQ, 1.0, 0.0), ("QQQ 3배", QQQ, 3.0, 0.0095)):
    st = datetime.date(2000, 3, 24)
    p = base(px, st) if lev == 1 else sim(px, lev, er, 0.005, st)
    rec = next((d for d, v in p if v >= 1.0), None)
    if rec:
        L.append(f"   {tag}: {rec} 회복 — {(rec-st).days/365.25:.1f}년")
    else:
        L.append(f"   {tag}: 2026-07-22까지 미회복 — 현재 {p[-1][1]:.4f}배 "
                 f"(원금의 {p[-1][1]*100:.2f}%)")

L.append("")
L.append("④ 비용 뜯어보기 — 3배 ETF가 1년에 떼가는 것 (2026-07 기준 rf)")
r = rf_on(datetime.date(2026, 7, 22))
L.append(f"   무위험수익률 rf={r*100:.2f}%  ·  차입 2배분 이자 = 2×(rf+0.5%) = {2*(r+0.005)*100:.2f}%")
L.append(f"   운용보수 0.95%  →  합계 연 {2*(r+0.005)*100+0.95:.2f}% (기초자산이 제자리여도 나가는 돈)")

L.append("")
L.append("⑤ 하루 -33.3%면 원금 전액. 실제로 얼마나 가까웠나 (QQQ 일간 최악 5일)")
for d, x in sorted(rets(QQQ, q0), key=lambda t: t[1])[:5]:
    L.append(f"   {d}  QQQ {x*100:+.2f}%  →  3배 {x*3*100:+.2f}%")

open(os.path.join(HERE, "out", "lev_detail.txt"), "w", encoding="utf-8").write("\n".join(L))
print("\n".join(L))
