"""
코스피에 요일 효과가 있을까 (짧은 실험 스크립트)

사용법:
    pip install pandas numpy matplotlib finance-datareader
    python weekday_effect.py
    python weekday_effect.py --synthetic     # 난수 데이터로 동작 확인

데이터: FinanceDataReader 의 코스피(KS11) 일별 종가 (1995-05 ~ 2026-09-17, 글과 같은 기간)
결과:  output/weekday_results.txt 와 차트 PNG
1998년까지는 토요일에도 장이 열렸으므로 요일 비교는 1999년 이후로 한다.
월요일 수익률은 금요일 종가에서 월요일 종가까지(주말 포함)다.
"""
import argparse
import os

import numpy as np
import pandas as pd

HERE = os.path.dirname(os.path.abspath(__file__))
OUT = os.path.join(HERE, "output")
os.makedirs(OUT, exist_ok=True)
NAMES = ["월", "화", "수", "목", "금"]
END = "2026-09-17"                                # 글의 표와 같은 기간(2026년 9월 17일까지)


def load(synthetic=False):
    if synthetic:
        rng = np.random.default_rng(7)
        idx = pd.bdate_range("1999-01-04", "2026-09-17")
        return pd.Series(1000 * np.exp(np.cumsum(rng.normal(0.0003, 0.015, len(idx)))), index=idx)
    import FinanceDataReader as fdr
    return fdr.DataReader("KS11", "1995-01-01", END)["Close"].dropna()


def by_weekday(r):
    g = r.groupby(r.index.dayofweek)
    t = pd.DataFrame({
        "일수": g.size(),
        "평균(%)": g.mean() * 100,
        "t값": g.mean() / (g.std() / np.sqrt(g.size())),
        "상승 비율(%)": g.apply(lambda s: (s > 0).mean() * 100),
    })
    t.index = [NAMES[i] for i in t.index]
    return t


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--synthetic", action="store_true")
    a = ap.parse_args()
    r = load(a.synthetic).pct_change().dropna().loc["1999":]
    lines = [f"기간 {r.index[0].date()} ~ {r.index[-1].date()}, {len(r)}거래일"]
    for lab, sub in [("전체", r), ("1999~2012", r.loc[:"2012"]), ("2013~", r.loc["2013":])]:
        lines.append(f"\n[{lab}]\n" + by_weekday(sub).round(3).to_string())
    lines.append("")
    for d in [0, 1]:                                 # 월요일, 화요일을 각각 나머지 요일과 비교
        day, rest = r[r.index.dayofweek == d], r[r.index.dayofweek != d]
        t = (day.mean() - rest.mean()) / np.sqrt(day.var() / len(day) + rest.var() / len(rest))
        lines.append(f"{NAMES[d]}요일 vs 나머지 평균 차이 t값: {t:.2f}")
    # 월요일만 피하는 규칙: 금요일 종가에 팔고 월요일 종가에 다시 산다 (주 1회 왕복)
    years = (r.index[-1] - r.index[0]).days / 365.25
    bh = (1 + r).prod() ** (1 / years) - 1
    skip = r.where(r.index.dayofweek != 0, 0.0)
    n_mon = (r.index.dayofweek == 0).sum()
    for cost in [0.0, 0.001]:
        net = skip.copy()
        net[r.index.dayofweek == 0] -= cost          # 매주 한 번 팔고 사는 왕복 비용
        lines.append(f"월요일 회피 CAGR (왕복 비용 {cost:.1%}): {(1 + net).prod() ** (1 / years) - 1:.2%}  / 보유 {bh:.2%}")
    lines.append(f"월요일 수 {n_mon}, 연평균 {n_mon / years:.1f}번 왕복")
    text = "\n".join(lines)
    print(text)
    with open(os.path.join(OUT, "weekday_results.txt"), "w", encoding="utf-8") as fh:
        fh.write(text + "\n")
    try:
        import matplotlib
        matplotlib.use("Agg")
        import matplotlib.pyplot as plt
        fig, axes = plt.subplots(1, 2, figsize=(11, 4), sharey=True)
        for ax, (lab, sub) in zip(axes, [("1999-2012", r.loc[:"2012"]), ("2013-2026", r.loc["2013":])]):
            g = sub.groupby(sub.index.dayofweek)
            m, se = g.mean() * 100, g.std() / np.sqrt(g.size()) * 100
            ax.bar(["Mon", "Tue", "Wed", "Thu", "Fri"], m.values, yerr=2 * se.values,
                   color=["#b22222" if v < 0 else "#1f5fbf" for v in m.values], capsize=4)
            ax.axhline(0, color="black", linewidth=0.8)
            ax.set_title(f"KOSPI mean daily return by weekday, {lab}")
            ax.set_ylabel("% (bars: ±2 standard errors)")
            ax.grid(alpha=0.3, axis="y")
        fig.tight_layout(); fig.savefig(os.path.join(OUT, "48_weekday_effect.png"), dpi=120); plt.close(fig)
    except ImportError:
        pass


if __name__ == "__main__":
    main()
