"""
v4.1 真实微观数据策略 - 修复版
仔细分析 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()
df['ema21_1h'] = df['c'].ewm(span=84).mean()  # 21*4

# ──────────────────────────────────────────────────────
# 第一步：找出所有大跌事件 (>2% 跌幅)
# ──────────────────────────────────────────────────────
print("\n📊 第一步：分析大跌事件后的 Taker 行为模式")
print("="*80)

drop_events = []
for i in range(50, len(df) - 24):
    # 检查过去12根K线内是否有单次跌幅>2%
    for j in range(i-12, i+1):
        if df['ret'].iloc[j] < -2.0:
            drop_events.append({
                'drop_idx': j,
                'drop_pct': df['ret'].iloc[j],
                'scan_start': i,
            })
            break

print(f"找到 {len(drop_events)} 个大跌事件")

# ──────────────────────────────────────────────────────
# 第二步：分析大跌后不同 Taker 占比区间的后续表现
# ──────────────────────────────────────────────────────
print("\n📊 第二步：Taker 占比 vs 后续收益热力图")
print("="*80)

results = []
for evt in drop_events:
    i = evt['scan_start']
    
    # 在大跌后 1-6 根 K 线内寻找信号
    for offset in range(1, 7):
        ci = evt['drop_idx'] + offset
        if ci >= len(df) - 24 or ci < 0:
            continue
        
        taker_ratio = df['taker_buy_ratio'].iloc[ci]
        
        # 趋势过滤
        trend_up = df['ema21_1h'].iloc[ci] > df['ema50'].iloc[ci]
        
        # 成交量放大
        vol_ratio = df['v'].iloc[ci] / (df['vol_ma20'].iloc[ci] + 1e-9)
        
        # 阳线
        is_bull = df['c'].iloc[ci] > df['o'].iloc[ci]
        
        # 模拟入场
        entry_price = df['c'].iloc[ci]
        
        # 简单持有24根K线 (6小时) 看最终收益
        exit_idx = min(ci + 24, len(df) - 1)
        exit_price = df['c'].iloc[exit_idx]
        ret_24 = (exit_price / entry_price - 1) * 100 - 0.06
        
        results.append({
            'taker_ratio': taker_ratio,
            'trend_up': trend_up,
            'vol_ratio': vol_ratio,
            'is_bull': is_bull,
            'ret_24': ret_24,
            'entry_time': df.index[ci],
        })

df_res = pd.DataFrame(results)
print(f"总样本数: {len(df_res):,}")

# 按 Taker 占比分组统计
print("\n📈 Taker 买入占比分组的平均收益:")
bins = [0, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 1.0]
labels = ['<45%', '45-50%', '50-55%', '55-60%', '60-65%', '65-70%', '>70%']
df_res['bucket'] = pd.cut(df_res['taker_ratio'], bins=bins, labels=labels, right=False)

grouped = df_res.groupby('bucket', observed=True).agg({
    'ret_24': ['count', 'mean', 'std', 'sum'],
    'trend_up': 'mean',
}).round(3)
print(grouped)

# ──────────────────────────────────────────────────────
# 第三步：测试不同条件组合的胜率
# ──────────────────────────────────────────────────────
print("\n\n📊 第三步：测试不同条件组合的胜率")
print("="*80)

test_configs = [
    ("仅 Taker>0.55", lambda r: r['taker_ratio'] >= 0.55),
    ("Taker>0.55 + 趋势向上", lambda r: r['taker_ratio'] >= 0.55 and r['trend_up']),
    ("Taker>0.55 + 放量", lambda r: r['taker_ratio'] >= 0.55 and r['vol_ratio'] >= 1.2),
    ("Taker>0.55 + 阳线", lambda r: r['taker_ratio'] >= 0.55 and r['is_bull']),
    ("Taker>0.60 + 趋势向上 + 阳线", lambda r: r['taker_ratio'] >= 0.60 and r['trend_up'] and r['is_bull']),
    ("Taker>0.65 + 趋势向上 + 放量 + 阳线", lambda r: r['taker_ratio'] >= 0.65 and r['trend_up'] and r['vol_ratio'] >= 1.3 and r['is_bull']),
]

for name, condition in test_configs:
    subset = df_res[df_res.apply(condition, axis=1)]
    if len(subset) == 0:
        print(f"{name}: 无信号")
        continue
    
    wins = (subset['ret_24'] > 0).sum()
    total = len(subset)
    win_rate = wins / total * 100
    avg_ret = subset['ret_24'].mean()
    total_ret = subset['ret_24'].sum()
    
    flag = "✅" if win_rate > 55 else "⚠️" if win_rate > 50 else "❌"
    print(f"{flag} {name}:")
    print(f"   信号数: {total}, 胜率: {win_rate:.1f}%, 平均收益: {avg_ret:+.2f}%, 总收益: {total_ret:+.1f}%")

# ──────────────────────────────────────────────────────
# 第四步：找出最优 Taker 阈值
# ──────────────────────────────────────────────────────
print("\n\n📊 第四步：寻找最优 Taker 阈值")
print("="*80)

thresholds = np.arange(0.45, 0.80, 0.02)
best_threshold = None
best_score = -999

for thresh in thresholds:
    subset = df_res[df_res['taker_ratio'] >= thresh]
    if len(subset) < 20:  # 至少需要20个样本
        continue
    
    wins = (subset['ret_24'] > 0).sum()
    win_rate = wins / len(subset)
    avg_ret = subset['ret_24'].mean()
    
    # 综合评分：胜率 * 平均收益
    score = win_rate * avg_ret
    
    if score > best_score:
        best_score = score
        best_threshold = thresh
        best_stats = {
            'thresh': thresh,
            'count': len(subset),
            'win_rate': win_rate * 100,
            'avg_ret': avg_ret,
            'total_ret': subset['ret_24'].sum(),
        }

if best_threshold:
    print(f"\n🏆 最优 Taker 阈值: {best_threshold:.2f}")
    print(f"   信号数: {best_stats['count']}")
    print(f"   胜率: {best_stats['win_rate']:.1f}%")
    print(f"   平均收益: {best_stats['avg_ret']:+.2f}%")
    print(f"   总收益: {best_stats['total_ret']:+.1f}%")

print("\n" + "="*80)
print("💡 结论:")
print("  - 单纯提高 Taker 阈值不一定能提高胜率")
print("  - 需要结合其他条件 (趋势、成交量、形态)")
print("  - 下一步：用最优阈值 + 多条件过滤做完整回测")
