#!/usr/bin/env python3
"""손익비 후보 소수 조합 — 단일 프로세스·학습+OOS 동시 표 (멀티프로세싱 없음)."""
from __future__ import annotations

import os
import sys
from itertools import product

HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(os.path.dirname(HERE))
if ROOT not in sys.path:
    sys.path.insert(0, ROOT)

from database import TradeDB
from kis_trader.backtest.param_search_momentum import (
    _evaluate_momentum_chunk,
    _load_candles_for_search,
    _mom_fixed_defaults,
)
from kis_trader.backtest.momentum_rr_crossval import _base_entry_ui, _load_universe


def main() -> None:
    train = ("2026-05-11", "2026-05-30")
    oos = ("2026-06-01", "2026-06-01")
    fixed = _mom_fixed_defaults()
    base = _base_entry_ui(fixed)

    # 핵심 손익비 후보만 (실행 시간 — 전체 Cartesian 은 param_search --mode rr 사용)
    candidates = [
        (2.0, 2.0, 1.8, 0.5, 0.02),   # baseline_live
        (2.0, 2.5, 2.5, 50.0, 0.25),  # shoulder_off
        (1.5, 2.5, 2.5, 1.0, 0.25),   # wide_shoulder
        (1.2, 3.0, 3.0, 1.2, 0.30),   # delayed_shoulder
        (1.5, 2.0, 2.0, 50.0, 0.20),  # tp_only
        (1.8, 2.2, 2.2, 0.8, 0.20),   # loose_shoulder
        (1.5, 2.5, 2.5, 0.5, 0.15),
        (1.5, 2.5, 2.5, 1.0, 0.15),
        (1.8, 2.0, 2.0, 1.0, 0.20),
        (2.0, 2.5, 2.5, 1.0, 0.15),
        (1.2, 2.5, 2.5, 1.0, 0.25),
        (1.5, 3.0, 3.0, 50.0, 0.25),
    ]
    combos = []
    for sl, tp, tpm, sa, sc in candidates:
        ui = dict(base)
        ui.update({
            "sl_pct": sl, "tp_pct": tp, "tp_max_pct": tpm,
            "shoulder_min_high": sa, "shoulder_cut_pct": sc,
        })
        combos.append(ui)

    print(f"평가 조합: {len(combos)}개 (단일 프로세스)")

    periods = [("train", train), ("oos", oos)]
    data_cache = {}
    uni_cache = {}
    for label, (s, e) in periods:
        data_cache[label] = _load_candles_for_search(s, e, 3)
        uni_cache[label], src = _load_universe(s, e)
        print(f"  {label} {s}~{e}: candles={len(data_cache[label])} uni={src}")

    db = TradeDB()
    row = db.conn.execute("SELECT * FROM env_config ORDER BY id DESC LIMIT 1").fetchone()
    env_row = dict(row) if row else {}
    db.close()
    from kis_trader.backtest import scalping_backtest_common as sbc
    fee, tax, _ = sbc.fee_and_slot_from_env(env_row, strategy="MOMENTUM")

    rows = []
    keys = list(combos[0].keys()) if combos else []
    for i, ui in enumerate(combos, 1):
        row_train = row_oos = None
        for label, _ in periods:
            heap = _evaluate_momentum_chunk(
                [ui], fixed, keys,
                data_cache[label], 1, 0.0, 0.0, 1, uni_cache[label],
                200_000, 20, 2_000_000, fee, tax, 20 if label == "train" else 1,
            )
            if heap:
                _, _, _, pkg = heap[0]
                if label == "train":
                    row_train = pkg
                else:
                    row_oos = pkg
        if not row_train or not row_oos:
            continue
        rows.append({
            "sl": ui["sl_pct"], "tp": ui["tp_pct"], "tpmax": ui["tp_max_pct"],
            "sh": f"{ui['shoulder_min_high']}/{ui['shoulder_cut_pct']}",
            "train_pnl": row_train["total_pnl"],
            "oos_pnl": row_oos["total_pnl"],
            "train_pf": row_train["pf"],
            "oos_pf": row_oos["pf"],
            "oos_trades": row_oos["total_trades"],
        })
        if i % 10 == 0:
            print(f"  ... {i}/{len(combos)}")

    rows.sort(key=lambda r: (r["oos_pnl"], r["train_pnl"]), reverse=True)
    print("\n=== OOS 손익 우선 TOP 10 (train 5/11~30 + oos 6/1) ===")
    print(f"{'sl':>4} {'tp':>4} {'max':>4} {'shoulder':>12} {'train':>10} {'oos':>10} {'oos_pf':>6}")
    for r in rows[:10]:
        print(
            f"{r['sl']:4.1f} {r['tp']:4.1f} {r['tpmax']:4.1f} {r['sh']:>12} "
            f"{r['train_pnl']:>10,} {r['oos_pnl']:>10,} {r['oos_pf']:>6.2f}"
        )
    pos_both = [r for r in rows if r["train_pnl"] > 0 and r["oos_pnl"] > 0]
    print(f"\n학습·OOS 둘 다 플러스: {len(pos_both)}건")
    if pos_both:
        b = pos_both[0]
        print(f"  추천: sl={b['sl']} tp={b['tp']} tpmax={b['tpmax']} shoulder={b['sh']}")


if __name__ == "__main__":
    main()
