#!/usr/bin/env python3
"""꼬리 청산 A/B — baseline vs 래칫 vs 시간컷 (fast 5위 base, 2026-05)."""
from __future__ import annotations

import json
from datetime import datetime

from database import TradeDB
from kis_trader.backtest import tail_backtest_common as tbc
from kis_trader.engine import tail_engine as te

START = "2026-05-01"
END = "2026-05-31"
TF = 3

SCENARIOS = [
    ("baseline_DB(래칫ON·어깨0.5%·트레일OFF)", {}),
    ("어깨2%+trail1.5/1.5_래칫ON", {
        "shoulder_min_high": 0.02,
        "trail_pct": 0.015,
        "trail_arm_pct": 0.015,
    }),
    ("어깨2%+trail1.5/1.5_래칫OFF", {
        "ratchet_tiers": "",
        "shoulder_min_high": 0.02,
        "trail_pct": 0.015,
        "trail_arm_pct": 0.015,
    }),
    ("어깨2%만_트레일OFF_래칫ON", {
        "shoulder_min_high": 0.02,
        "trail_pct": 0.0,
        "trail_arm_pct": 0.0,
    }),
    ("어깨2%만_트레일OFF_래칫OFF", {
        "ratchet_tiers": "",
        "shoulder_min_high": 0.02,
        "trail_pct": 0.0,
        "trail_arm_pct": 0.0,
    }),
]


def _load_base_params() -> dict:
    """DB 최신값 그대로 — fast 파라서치·실매와 동일."""
    d = te.get_tail_defaults_from_db()
    d["portfolio_mode"] = True
    d["force_eod_exit"] = False
    d.setdefault("max_hold_bars", 0)
    return d


def main() -> None:
    db = TradeDB()
    try:
        start_key, end_key, start_ymd, end_ymd = tbc.date_keys(START, END)
        candles_by_code, _, _ = tbc.load_tail_candles_by_code(
            db, start_key, end_key, TF, rsi_period=14,
        )
        universe_by_slot, _, _, _ = tbc.resolve_tail_universe(
            start_ymd, end_ymd, use_saved_history=True,
        )
        snap = db.get_merged_env_snapshot()
        fee_rate, sell_tax, _ = tbc.fee_and_slot_from_env_row(snap)
        base = _load_base_params()
        period_days = max(1, (datetime.strptime(END, "%Y-%m-%d") - datetime.strptime(START, "%Y-%m-%d")).days + 1)
        slot = float(base.get("slot_money") or 200000)
        mxs = int(base.get("max_stocks") or 20)
        tb = float(base.get("total_budget_krw") or mxs * slot)

        rows = []
        for label, patch in SCENARIOS:
            params = dict(base)
            params.update(patch)
            meta: dict = {}
            trades = tbc.run_tail_backtest_web_aligned(
                candles_by_code, params, universe_by_slot,
                slot_money=slot, fee_rate=fee_rate, sell_tax=sell_tax,
                max_stocks=mxs, total_budget_krw=tb, meta_out=meta,
            )
            stats = tbc.summarize_tail_trades(
                trades, total_budget_krw=tb, period_days=period_days,
            )
            reasons: dict = {}
            for t in trades:
                k = str(t.get("sell_reason") or t.get("reason") or "?")
                reasons[k] = reasons.get(k, 0) + 1
            rows.append({
                "scenario": label,
                "total_trades": stats["total_trades"],
                "win_rate": stats["win_rate"],
                "total_pnl": stats["total_pnl"],
                "pf": stats["pf"],
                "avg_hold_min": stats["avg_hold_min"],
                "sell_reasons": reasons,
                "patch": patch,
            })
            print(
                f"{label:32} | 거래 {stats['total_trades']:4} | "
                f"승률 {stats['win_rate']:5.1f}% | PnL {stats['total_pnl']:>9,} | "
                f"PF {stats['pf']:.2f} | 보유 {stats['avg_hold_min']:.0f}분 | {reasons}"
            )

        out = {
            "start": START, "end": END, "timeframe": TF,
            "base": {k: base.get(k) for k in (
                "min_drop_rate", "shoulder_min_high", "shoulder_cut_pct",
                "ratchet_tiers", "trail_pct", "trail_arm_pct",
                "stop_atr_mult", "target_atr_mult", "max_daily_change",
                "entry_mode", "slot_money", "max_stocks", "total_budget_krw",
            )},
            "scenarios": rows,
        }
        path = f"/home/hoon/kis_bot/kis_trader/backtest/results/tail_exit_ab_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(path, "w", encoding="utf-8") as f:
            json.dump(out, f, ensure_ascii=False, indent=2)
        print(f"\n💾 저장: {path}")
    finally:
        db.close()


if __name__ == "__main__":
    main()
