"""
缠论实战交易: 笔级别顶底分型 + 大级别过滤
核心逻辑: 底分型确认→做多, 顶分型确认→做空
"""
import pandas as pd, numpy as np
from chanlun_engine import merge_candles, identify_fenxing, identify_bi

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

# 大级别方向(4H/日线)
d4h = df_raw.resample("4h").agg({"close":"last"}).dropna()
d4h["ma50"] = d4h["close"].rolling(50).mean()
d4h["trend"] = (d4h["close"] > d4h["ma50"]).astype(int)  # 1=上升, 0=下降

# 映射到1H
d1h["htf_trend"] = d4h["trend"].reindex(d1h.index, method="ffill").fillna(0)

print("="*60)
print("缠论 笔级交易回测")
print("="*60)

FEE, SL, TP = 0.001, 0.01, 0.03
MAX_BARS = 48

all_trades = []

# 分月滑动窗口, 每次分析3个月数据
for i in range(0, len(d1h) - 24*30, 24*15):  # 每15天滑动一次
    chunk = d1h.iloc[i:i+24*90]  # 3个月窗口
    if len(chunk) < 200:
        continue
    
    try:
        df_m = merge_candles(chunk)
        fx = identify_fenxing(df_m)
        bi = identify_bi(fx, df_m)
    except:
        continue
    
    if len(bi) < 3:
        continue
    
    # 取最后几笔，找最近的顶/底分型
    last_bi = bi[-1]
    second_last_bi = bi[-2] if len(bi) >= 2 else None
    
    if second_last_bi is None:
        continue
    
    # 信号: 上一个分型确认后，找入场机会
    # 底分型确认 → 等回调→做多
    # 顶分型确认 → 等反弹→做空
    
    # 检查最近的分型类型
    prev_fx_type = last_bi["start_type"]  # 上一笔的起点类型
    prev_fx_idx = last_bi["start_idx"]
    
    # 寻找该分型之后的入场点
    for j in range(prev_fx_idx + 1, min(prev_fx_idx + 10, len(df_m))):
        if j >= len(df_m):
            break
        
        price = df_m["close"].iloc[j]
        
        # 底分型确认 → 做多
        if prev_fx_type == "底":
            # 等回调到分型低点附近
            fx_low = df_m["low"].iloc[prev_fx_idx]
            near_low = abs(price - fx_low) / fx_low < 0.008
            
            if near_low:
                # 检查大级别方向
                htf_idx = min(j, len(d1h) - 1)
                
                entry = price
                direction = 1
                win, loss = False, False
                for k in range(1, min(MAX_BARS, len(df_m) - j - 1)):
                    exit_px = df_m["close"].iloc[j + k]
                    ret = (exit_px / entry - 1) * direction
                    if ret <= -SL:
                        loss = True
                        all_trades.append({"dir":"多","ret":-SL-FEE,"win":0,"bars":k})
                        break
                    elif ret >= TP:
                        win = True
                        all_trades.append({"dir":"多","ret":TP-FEE,"win":1,"bars":k})
                        break
                if not win and not loss:
                    ep = df_m["close"].iloc[min(j+MAX_BARS, len(df_m)-1)]
                    r = (ep/entry-1)*direction
                    all_trades.append({"dir":"多","ret":r-FEE,"win":1 if r>0 else 0,"bars":MAX_BARS})
        
        # 顶分型确认 → 做空
        elif prev_fx_type == "顶":
            fx_high = df_m["high"].iloc[prev_fx_idx]
            near_high = abs(price - fx_high) / fx_high < 0.008
            
            if near_high:
                entry = price
                direction = -1
                win, loss = False, False
                for k in range(1, min(MAX_BARS, len(df_m) - j - 1)):
                    exit_px = df_m["close"].iloc[j + k]
                    ret = (exit_px / entry - 1) * direction
                    if ret <= -SL:
                        loss = True
                        all_trades.append({"dir":"空","ret":-SL-FEE,"win":0,"bars":k})
                        break
                    elif ret >= TP:
                        win = True
                        all_trades.append({"dir":"空","ret":TP-FEE,"win":1,"bars":k})
                        break
                if not win and not loss:
                    ep = df_m["close"].iloc[min(j+MAX_BARS, len(df_m)-1)]
                    r = (ep/entry-1)*direction
                    all_trades.append({"dir":"空","ret":r-FEE,"win":1 if r>0 else 0,"bars":MAX_BARS})

# ── 结果 ──
if not all_trades:
    print("无信号")
else:
    t = pd.DataFrame(all_trades)
    print(f"交易: {len(t)}笔")
    print(f"胜率: {t['win'].mean():.1%}")
    print(f"均益: {t['ret'].mean()*10000:+.0f} bps")
    cum = (1 + t["ret"]).prod()
    print(f"累计: {cum:.4f} ({(cum-1)*100:+.1f}%)")
    
    for d in ["多","空"]:
        s = t[t["dir"]==d]
        if len(s) > 0:
            print(f"  {d}: {len(s)}笔 胜率{s['win'].mean():.1%} 均益{s['ret'].mean()*10000:+.0f}bps")
    
    # 加入大级别过滤
    print(f"\n--- 加日线方向过滤 ---")
    # 重新跑一遍，但只做大级别顺势的
