"""
缠论买卖点 + 回测
基于中枢的第三类买卖点 + 第一类(背驰)
"""
import pandas as pd, numpy as np
from chanlun_engine import merge_candles, identify_fenxing, identify_bi, identify_xduan, identify_zhongshu

df_raw = pd.read_parquet("data/btc_multidim.parquet")
d = df_raw.resample("1h").agg({"open":"first","high":"max","low":"min","close":"last","volume":"sum"}).dropna()

print("="*60)
print("缠论 买卖点回测")
print("="*60)

# 分月滚动处理（避免全局中枢）
FEE, SL, TP, MAX_BARS = 0.001, 0.01, 0.03, 72
all_trades = []

for month_start in pd.date_range(d.index[0], d.index[-1], freq="MS"):
    month_end = month_start + pd.DateOffset(months=3)  # 用3个月窗口
    if month_end > d.index[-1]:
        month_end = d.index[-1]
    
    chunk = d[month_start:month_end]
    if len(chunk) < 200:
        continue
    
    try:
        result = run_chanlun(chunk)
    except:
        continue
    
    if not result["zhongshu"] or not result["bi"]:
        continue
    
    zs = result["zhongshu"]
    bi = result["bi"]
    df_m = result["merged_df"]
    
    # 取最后一个中枢
    last_zs = zs[-1]
    ZG, ZD, ZZ = last_zs["ZG"], last_zs["ZD"], last_zs["ZZ"]
    
    # 在中枢形成后的价格中找买卖点
    last_bi_end = bi[-1]["end_idx"]
    
    for idx in range(last_bi_end + 1, min(last_bi_end + 200, len(df_m))):
        price = df_m["close"].iloc[idx]
        
        # 第三类买点: 价格突破ZG后回踩不破
        if idx >= 2:
            prev_close = df_m["close"].iloc[idx-1]
            prev2_close = df_m["close"].iloc[idx-2]
            # 之前突破过ZG，现在回踩到ZG附近(<1%)
            broke_above = prev2_close > ZG or prev_close > ZG
            near_zg = abs(price - ZG) / ZG < 0.008
            if broke_above and near_zg and price > ZD:  # 在ZG附近但不跌破ZD
                # 模拟交易
                entry = price
                direction = 1  # 做多
                win, loss = False, False
                for j in range(1, min(MAX_BARS, len(df_m) - idx - 1)):
                    exit_px = df_m["close"].iloc[idx + j]
                    ret = (exit_px / entry - 1) * direction
                    if ret <= -SL:
                        loss = True
                        all_trades.append({
                            "ts": df_m.index[idx], "dir": "多", "type": "三买",
                            "ret": -SL - FEE, "win": 0, "bars": j
                        })
                        break
                    elif ret >= TP:
                        win = True
                        all_trades.append({
                            "ts": df_m.index[idx], "dir": "多", "type": "三买",
                            "ret": TP - FEE, "win": 1, "bars": j
                        })
                        break
                if not win and not loss:
                    exit_px = df_m["close"].iloc[min(idx+MAX_BARS, len(df_m)-1)]
                    ret = (exit_px / entry - 1) * direction
                    all_trades.append({
                        "ts": df_m.index[idx], "dir": "多", "type": "三买",
                        "ret": ret - FEE, "win": 1 if ret > 0 else 0, "bars": MAX_BARS
                    })
        
        # 第三类卖点: 价格跌破ZD后反弹不破
        broke_below = (df_m["close"].iloc[idx-1] < ZD) if idx >= 1 else False
        near_zd = abs(price - ZD) / ZD < 0.008
        if broke_below and near_zd and price < ZG:
            entry = price
            direction = -1
            win, loss = False, False
            for j in range(1, min(MAX_BARS, len(df_m) - idx - 1)):
                exit_px = df_m["close"].iloc[idx + j]
                ret = (exit_px / entry - 1) * direction
                if ret <= -SL:
                    loss = True
                    all_trades.append({
                        "ts": df_m.index[idx], "dir": "空", "type": "三卖",
                        "ret": -SL - FEE, "win": 0, "bars": j
                    })
                    break
                elif ret >= TP:
                    win = True
                    all_trades.append({
                        "ts": df_m.index[idx], "dir": "空", "type": "三卖",
                        "ret": TP - FEE, "win": 1, "bars": j
                    })
                    break
            if not win and not loss:
                exit_px = df_m["close"].iloc[min(idx+MAX_BARS, len(df_m)-1)]
                ret = (exit_px / entry - 1) * direction
                all_trades.append({
                    "ts": df_m.index[idx], "dir": "空", "type": "三卖",
                    "ret": ret - FEE, "win": 1 if ret > 0 else 0, "bars": MAX_BARS
                })

# ── 结果 ──
if not all_trades:
    print("无交易信号")
else:
    tdf = pd.DataFrame(all_trades)
    n = len(tdf)
    wr = tdf["win"].mean()
    cum = (1 + tdf["ret"]).prod()
    avg = tdf["ret"].mean() * 10000
    
    print(f"\n交易: {n} 笔")
    print(f"胜率: {wr:.1%}")
    print(f"均益: {avg:+.0f} bps")
    print(f"累计: {cum:.4f} ({(cum-1)*100:+.1f}%)")
    
    # 分类统计
    for t in ["三买","三卖"]:
        sub = tdf[tdf["type"] == t]
        if len(sub) > 0:
            print(f"\n{t}: {len(sub)}笔 胜率{sub['win'].mean():.1%} 均益{sub['ret'].mean()*10000:+.0f}bps")
    
    # 月度
    tdf["month"] = pd.to_datetime(tdf["ts"]).dt.to_period("M")
    monthly = tdf.groupby("month").agg(n=("ret","count"), wr=("win","mean"))
    print(f"\n月度:\n{monthly}")
