"""
Sprint 3 验证脚本 — Optuna 参数优化。

用法:
    python cli/demo_optimizer.py
    python cli/demo_optimizer.py --ts_code 600519.SH --trials 100
"""

import sys, os, argparse
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from data.data_manager import DataManager
from factors.engine import FactorEngine
from factors.registry import get_factor
from backtest.vectorbt.engine import VectorBTEngine
from backtest.strategies.rsi_mean_revert import RSIMeanRevertStrategy
from optimizer.engine import OptunaEngine
from optimizer.space import rsi_revert_space


def main():
    p = argparse.ArgumentParser(description="Sprint 3 — Optuna 参数优化验证")
    p.add_argument("--ts_code", default="000001.SZ", help="测试股票代码")
    p.add_argument("--trials", type=int, default=200, help="试验次数（默认: 200）")
    args = p.parse_args()

    print("=" * 60)
    print("Sprint 3 — Optuna 参数优化验证")
    print("=" * 60)

    print("\n[1/4] 初始化...")
    dm = DataManager(); dm.init_db()
    engine_fe = FactorEngine(dm)
    bt_engine = VectorBTEngine()
    opt_engine = OptunaEngine(bt_engine)

    price_df = dm.get_daily(args.ts_code).set_index("trade_date").sort_index()
    factor_df = engine_fe.compute(args.ts_code, [get_factor("rsi_14")])
    print("  数据: {} 条日线, {} 个因子".format(len(price_df), factor_df.shape[1]))
    print("[OK]")

    print("\n[2/4] RSI 反转策略参数寻优 (sharpe, {} trials)...".format(args.trials))
    result = opt_engine.optimize(
        strategy_class=RSIMeanRevertStrategy,
        search_space=rsi_revert_space,
        price_df=price_df, factor_df=factor_df,
        metric="sharpe", n_trials=args.trials,
    )
    print(result.summary())
    if result.param_importance:
        print("  参数重要性:")
        for k, v in sorted(result.param_importance.items(), key=lambda x: -x[1]):
            print("    {}: {:.4f}".format(k, v))

    print("\n[3/4] 默认参数 vs 最优参数 对比...")
    strategies_compare = [
        ("默认(30/70)", RSIMeanRevertStrategy(oversold=30, overbought=70)),
        ("最优", RSIMeanRevertStrategy(**result.best_params)),
    ]
    reports = {}
    for name, s in strategies_compare:
        reports[name] = bt_engine.run(s, price_df, factor_df)

    metrics = [("总收益(%)", "total_return"), ("年化CAGR(%)", "cagr"), ("最大回撤(%)", "max_drawdown"),
               ("夏普比率", "sharpe_ratio"), ("卡玛比率", "calmar_ratio"), ("胜率(%)", "win_rate"),
               ("盈利因子", "profit_factor"), ("交易笔数", "total_trades")]
    print("  {:<18s} {:>12s} {:>12s}".format("指标", "默认(30/70)", "最优"))
    print("  " + "-" * 42)
    for label, attr in metrics:
        vals = []
        for r in reports.values():
            v = getattr(r, attr)
            vals.append("{:.2f}".format(v) if isinstance(v, float) else str(v))
        print("  {:<18s} {:>12s} {:>12s}".format(label, vals[0], vals[1]))

    print("\n[4/4] Walk-Forward 滚动窗口验证...")
    try:
        wf = opt_engine.optimize_walk_forward(
            RSIMeanRevertStrategy, rsi_revert_space,
            price_df, factor_df, metric="sharpe", n_trials=min(80, args.trials),
            train_window=252 * 3, test_window=252,
        )
        print(wf.summary())
    except Exception as e:
        print("  [SKIP] Walk-Forward 异常: {}".format(e))

    # 存入 DB
    try:
        from reports.storage import save_report
        from datetime import datetime
        lines = ["## 参数优化 — {}".format(args.ts_code),
                 result.summary(), "",
                 "### 默认 vs 最优对比"]
        save_report("\n".join(lines), "参数优化", subject_type="stock", subject_code=args.ts_code)
        print("\n  报告已存入 DB")
    except Exception as e:
        print("\n  [WARN] 报告入库失败: {}".format(e))

    print("\n" + "=" * 60)
    print("Sprint 3 验证完成")
    print("=" * 60)


if __name__ == "__main__":
    main()
