"""
v4.0 真实微观数据策略 - 使用真实 Taker 买卖量
核心：大跌 + 真实主力抄底信号 + 趋势过滤
"""
import pandas as pd
import numpy as np

print("🚀 加载数据...")
df = pd.read_parquet('/root/quant_pipeline/data/btc_15m_binance_full.parquet')
print(f"数据量: {len(df):,} 根 K 线")

# 计算必要指标
df['ret'] = df['c'].pct_change() * 100
df['ema21'] = df['c'].ewm(span=21).mean()
df['ema50'] = df['c'].ewm(span=50).mean()
df['vol_ma20'] = df['v'].rolling(20).mean()

# 1小时趋势 (用4根15分钟K线模拟)
df['ema21_1h'] = df['c'].ewm(span=21*4).mean()

print("\n📊 策略回测：大跌 + 真实Taker流入 + 趋势过滤")
print("="*80)

# 策略参数
DROP_THRESHOLD = -2.0  # 大跌阈值
TAKER_RATIO_THRESH = 0.55  # Taker买入占比阈值
VOL_RATIO_THRESH = 1.2  # 成交量放大倍数
CONFIRM_WINDOW = 6  # 最多等6根K线确认

signals = []
for i in range(100, len(df) - 10):
    # 1. 检测大跌
    drop_pct = df['ret'].iloc[i-12:i+1].min()
    if drop_pct > DROP_THRESHOLD:
        continue
    
    # 找到大跌的那根K线索引
    drop_idx = (i-12 + np.argmin(df['ret'].iloc[i-12:i+1].values))
    
    # 2. 在大跌后的窗口内寻找 Taker 流入信号
    found_signal = False
    for offset in range(1, min(CONFIRM_WINDOW, len(df)-i)):
        ci = drop_idx + offset
        if ci >= len(df) - 5:
            break
        
        # 真实 Taker 买入占比
        taker_ratio = df['taker_buy_ratio'].iloc[ci]
        
        # 成交量放大
        vol_ratio = df['v'].iloc[ci] / (df['vol_ma20'].iloc[ci] + 1e-9)
        
        # 1H 趋势向上
        trend_up = df['ema21_1h'].iloc[ci] > df['ema50'].iloc[ci]
        
        # 阳线确认
        is_bull = df['c'].iloc[ci] > df['o'].iloc[ci]
        
        # 入场条件：Taker流入 + 成交量放大 + 趋势向上 + 阳线
        if (taker_ratio >= TAKER_RATIO_THRESH and 
            vol_ratio >= VOL_RATIO_THRESH and 
            trend_up and is_bull):
            
            # 入场
            entry_price = df['c'].iloc[ci]
            
            # 出场：固定止盈止损
            sl_mult = 1.0
            tp_mult = 2.0
            atr = df['v'].iloc[ci-20:ci+1].std() * 0.01  # 简化ATR
            
            sl_price = entry_price * (1 - atr/entry_price * sl_mult)
            tp_price = entry_price * (1 + atr/entry_price * tp_mult)
            
            # 模拟持仓最多24根K线 (6小时)
            exit_price = None
            exit_idx = None
            hit_sl = hit_tp = False
            
            for j in range(ci+1, min(ci+24, len(df))):
                high_j = df['h'].iloc[j]
                low_j = df['l'].iloc[j]
                
                if high_j >= tp_price:
                    exit_price = tp_price
                    hit_tp = True
                    exit_idx = j
                    break
                elif low_j <= sl_price:
                    exit_price = sl_price
                    hit_sl = True
                    exit_idx = j
                    break
            
            if exit_price is None:
                exit_price = df['c'].iloc[min(ci+24, len(df)-1)]
                exit_idx = min(ci+24, len(df)-1)
            
            ret_pct = (exit_price / entry_price - 1) * 100 - 0.06  # 减去手续费
            
            signals.append({
                'entry_time': df.index[ci],
                'exit_time': df.index[exit_idx],
                'entry_price': entry_price,
                'exit_price': exit_price,
                'taker_ratio': taker_ratio,
                'vol_ratio': vol_ratio,
                'return_pct': ret_pct,
                'hit_tp': hit_tp,
                'hit_sl': hit_sl,
            })
            found_signal = True
            break  # 找到信号就跳出，避免重复
    
    if found_signal:
        continue  # 已处理，跳过

# 分析结果
if len(signals) == 0:
    print("❌ 没有产生任何信号！需要放宽条件。")
else:
    df_sig = pd.DataFrame(signals)
    
    total_trades = len(df_sig)
    wins = (df_sig['return_pct'] > 0).sum()
    win_rate = wins / total_trades * 100
    avg_ret = df_sig['return_pct'].mean()
    total_ret = df_sig['return_pct'].sum()
    
    # 复利计算
    cum = (1 + df_sig['return_pct']/100).prod()
    
    # 最大回撤
    equity_curve = (1 + df_sig['return_pct']/100).cumprod()
    peak = equity_curve.expanding().max()
    max_dd = ((equity_curve - peak) / peak).min() * 100
    
    # Sharpe (年化)
    sharpe = df_sig['return_pct'].mean() / df_sig['return_pct'].std() * np.sqrt(365*4) if df_sig['return_pct'].std() > 0 else 0
    
    print(f"\n{'='*80}")
    print(f"📊 v4.0 真实微观数据策略回测结果")
    print(f"{'='*80}")
    print(f"总交易次数: {total_trades}")
    print(f"盈利次数: {wins} | 亏损次数: {total_trades - wins}")
    print(f"✅ 胜率: {win_rate:.1f}%")
    print(f"平均单笔收益: {avg_ret:+.2f}%")
    print(f"总收益: {total_ret:+.1f}%")
    print(f"复利倍数: {cum:.2f}x")
    print(f"最大回撤: {max_dd:.1f}%")
    print(f"Sharpe比率: {sharpe:.2f}")
    print(f"{'='*80}")
    
    # 按 Taker 占比分组分析
    print(f"\n📈 按 Taker 买入占比分组:")
    df_sig['taker_bucket'] = pd.cut(df_sig['taker_ratio'], bins=[0, 0.5, 0.55, 0.6, 0.65, 1.0], 
                                     labels=['<50%', '50-55%', '55-60%', '60-65%', '>65%'])
    grouped = df_sig.groupby('taker_bucket', observed=True).agg({
        'return_pct': ['count', 'mean', 'sum']
    }).round(2)
    print(grouped)
    
    # 展示前10笔交易
    print(f"\n📋 前10笔交易详情:")
    print(df_sig[['entry_time', 'exit_time', 'entry_price', 'exit_price', 'taker_ratio', 'return_pct']].head(10).to_string())
