#!/usr/bin/env python3
"""
**Timing Industry — 31 SPDR ETFs** (Zarattini & Antonacci Section 6).

Tradable replication of the industry trend-following model on State Street sector/industry
ETFs (Jan 2005 → Mar 2024 in the paper). Benchmark: SPY. Cash sleeve: Ken French daily RF.

Paper headline (2005–2024, with $0.0035/share costs): CAGR ~7.7%, vol ~13.7%,
Sharpe ~0.61, max DD ~24%, alpha ~2.7% vs SPY.

Example::

    cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 \\
      .venv/bin/python RenTech/strategy_stack/run_industry_trend_timing_spdr31.py \\
      --start 2005-01-03 --end 2024-03-28 --capital 100000 \\
      --out-prefix RenTech/data/logs/industry_trend_timing_spdr31
"""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

_REPO = Path(__file__).resolve().parents[2]
if str(_REPO) not in sys.path:
    sys.path.insert(0, str(_REPO))

from RenTech.strategy_stack.spdr_industry_trend_timing import (
    SPDR_TIMING_TICKERS,
    run_spdr_industry_trend_timing,
)

LOGS = _REPO / "RenTech" / "data" / "logs"
DEFAULT_OUT = LOGS / "industry_trend_timing_spdr31"


def main() -> None:
    ap = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])
    ap.add_argument("--start", default="2005-01-03")
    ap.add_argument("--end", default="2024-03-28")
    ap.add_argument("--capital", type=float, default=100_000.0)
    ap.add_argument("--bench", default="SPY", help="Benchmark ticker (default SPY)")
    ap.add_argument("--out-prefix", type=Path, default=DEFAULT_OUT)
    args = ap.parse_args()

    res = run_spdr_industry_trend_timing(
        start=args.start,
        end=args.end,
        capital=float(args.capital),
        bench_ticker=args.bench,
    )

    prefix = args.out_prefix.expanduser().resolve()
    prefix.parent.mkdir(parents=True, exist_ok=True)
    daily_path = Path(f"{prefix}_daily.csv")
    yearly_path = Path(f"{prefix}_yearly.csv")
    weights_path = Path(f"{prefix}_weights.csv")
    meta_path = Path(f"{prefix}_meta.json")
    metrics_path = Path(f"{prefix}_metrics.txt")

    res.daily.to_csv(daily_path, index=False)
    res.yearly.to_csv(yearly_path, index=False)
    res.weights.to_csv(weights_path, index_label="date")
    meta = res.meta.copy()
    meta["daily_csv"] = str(daily_path)
    meta["yearly_csv"] = str(yearly_path)
    meta["weights_csv"] = str(weights_path)
    meta["command"] = (
        "PYTHONUNBUFFERED=1 .venv/bin/python "
        "RenTech/strategy_stack/run_industry_trend_timing_spdr31.py "
        f"--start {args.start} --end {args.end} --capital {args.capital} "
        f"--bench {args.bench} --out-prefix {prefix}"
    )
    meta_path.write_text(json.dumps(meta, indent=2), encoding="utf-8")

    bm = meta["benchmark"]
    pref = meta.get("paper_reference_2005_2024", {})
    lines = [
        "=== Industry Trend Timing (31 SPDR ETFs) ===",
        meta["command"],
        f"Universe ({len(SPDR_TIMING_TICKERS)}): {', '.join(SPDR_TIMING_TICKERS)}",
        f"Window: {meta['start']} → {meta['end']}  ({meta['n_sessions']} sessions)",
        "",
        "Timing ETFs:",
        f"  Return {meta['total_return_pct']:.1f}%  CAGR {meta['cagr_pct']:.1f}%  "
        f"Vol {meta['vol_ann_pct']:.1f}%  Sharpe {meta['sharpe_excess_rf']:.2f}  "
        f"MaxDD {meta['max_drawdown_pct']:.1f}%",
        f"  Alpha(ann) {meta.get('alpha_ann_pct')}%  Beta {meta.get('beta_mkt')}  "
        f"Avg gross {meta['avg_gross_exposure']:.0%}  Avg active {meta['avg_n_active']:.1f}",
        "",
        f"Benchmark ({bm['label']}):",
        f"  CAGR {bm['cagr_pct']:.1f}%  Vol {bm['vol_ann_pct']:.1f}%  "
        f"Sharpe {bm['sharpe_excess_rf']:.2f}  MaxDD {bm['max_drawdown_pct']:.1f}%",
        "",
        "Paper reference (2005–2024, with $0.0035/share): "
        f"ETF CAGR ~{pref.get('timing_etfs_cagr_pct')}%  "
        f"Sharpe ~{pref.get('timing_etfs_sharpe')}  "
        f"MDD ~{pref.get('timing_etfs_max_dd_pct')}%  "
        f"Alpha ~{pref.get('timing_etfs_alpha_ann_pct')}%",
        "",
        "Note: this run excludes commissions/slippage (paper Section 6.2).",
    ]
    metrics_path.write_text("\n".join(lines) + "\n", encoding="utf-8")

    print("\n".join(lines), flush=True)
    print(f"\nWrote {daily_path}", flush=True)
    print(f"Wrote {yearly_path}", flush=True)
    print(f"Wrote {weights_path}", flush=True)
    print(f"Wrote {meta_path}", flush=True)


if __name__ == "__main__":
    main()
