#!/usr/bin/env python3
"""
**Timing Industry** — Zarattini & Antonacci long-only industry trend-following.

Replicates the 48-industry Ken French backtest from *A Century of Profitable Industry
Trends* (Donchian/Keltner breakout, 14-day vol sizing, 200% gross cap, T-bill cash).

Paper headline (Jul 1926 → Mar 2024): ~18.2% CAGR, 12.6% vol, Sharpe 1.39, max DD 33%.

Example::

    cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 \\
      .venv/bin/python RenTech/strategy_stack/run_industry_trend_timing.py \\
      --start 1926-07-01 --end 2024-03-29 --capital 100000 \\
      --out-prefix RenTech/data/logs/industry_trend_timing_french48
"""

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.french_industry_loader import ensure_french_factors_daily, ensure_french_industry_daily
from RenTech.strategy_stack.industry_trend_timing_engine import run_industry_trend_timing

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


def main() -> None:
    ap = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])
    ap.add_argument("--start", default="1926-07-01")
    ap.add_argument("--end", default="2024-03-29")
    ap.add_argument("--capital", type=float, default=100_000.0)
    ap.add_argument("--out-prefix", type=Path, default=DEFAULT_OUT)
    ap.add_argument("--refresh-french", action="store_true", help="Re-download Ken French CSV zips")
    ap.add_argument(
        "--industry-weighting",
        choices=("value", "equal"),
        default="value",
        help="French industry return weighting (default value)",
    )
    args = ap.parse_args()

    if args.refresh_french:
        ensure_french_industry_daily(refresh=True)
        ensure_french_factors_daily(refresh=True)
    else:
        ensure_french_industry_daily()
        ensure_french_factors_daily()

    res = run_industry_trend_timing(
        start=args.start,
        end=args.end,
        capital=float(args.capital),
        industry_weighting=args.industry_weighting,
    )

    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")
    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)
    meta = res.meta.copy()
    meta["daily_csv"] = str(daily_path)
    meta["yearly_csv"] = str(yearly_path)
    meta["command"] = (
        "PYTHONUNBUFFERED=1 .venv/bin/python RenTech/strategy_stack/run_industry_trend_timing.py "
        f"--start {args.start} --end {args.end} --capital {args.capital} "
        f"--industry-weighting {args.industry_weighting} --out-prefix {prefix}"
    )
    meta_path.write_text(json.dumps(meta, indent=2), encoding="utf-8")

    bm = meta["benchmark"]
    lines = [
        "=== Industry Trend Timing (French 48) ===",
        meta["command"],
        f"Window: {meta['start']} → {meta['end']}  ({meta['n_sessions']} sessions)",
        "",
        "Timing Industry:",
        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}",
        "",
        "Market benchmark:",
        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 (1926–2024): Timing CAGR ~18.2%, vol ~12.6%, Sharpe ~1.39, MDD ~33%",
    ]
    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 {meta_path}", flush=True)


if __name__ == "__main__":
    main()
