"""
Sniper 额外分析：
问题出在 SL=3% 跟周线级别的日间波动不匹配
"""

import pandas as pd
import numpy as np

d = pd.read_parquet("/root/quant_pipeline/data/btc_daily.parquet")
print(f"日线数据: {len(d)}根  {d.index[0].date()} ~ {d.index[-1].date()}")

# 日线波动率分析
daily_vol = ((d["h"] - d["l"]) / d["c"] * 100)
print(f"\n📊 BTC 日线波动率统计:")
print(f"  平均日内振幅: {daily_vol.mean():.1f}%")
print(f"  中位数: {daily_vol.median():.1f}%")
print(f"  75分位: {daily_vol.quantile(0.75):.1f}%")
print(f"  >3%的交易日: {(daily_vol > 3).sum()}/{len(daily_vol)} ({(daily_vol > 3).mean()*100:.0f}%)")
print(f"  >5%的交易日: {(daily_vol > 5).sum()}/{len(daily_vol)} ({(daily_vol > 5).mean()*100:.0f}%)")
print(f"  最大单日振幅: {daily_vol.max():.1f}%")

# 入场后第1天的波动
d["ret_1d"] = d["c"].pct_change()
print(f"\n📊 日线涨跌幅:")
print(f"  平均: {d['ret_1d'].mean()*100:+.2f}%")
print(f"  标准差: {d['ret_1d'].std()*100:.1f}%")
print(f"  95%区间: [{d['ret_1d'].quantile(0.025)*100:.1f}%, {d['ret_1d'].quantile(0.975)*100:.1f}%]")

# ── 2. 使用原始 buy-and-hold 方式（匹配最初的研究）──
print(f"\n{'='*65}")
print(f"📈 原始研究方式：入场后持有X周（不含SL/TP）")
print(f"{'='*65}")

weekly = d.resample("W").agg({"o":"first","h":"max","l":"min","c":"last","v":"sum"}).dropna()
C_weekly = weekly["c"].values
O_weekly = weekly["o"].values

# 重建周线信号
delta = pd.Series(C_weekly).diff()
gain = delta.clip(lower=0).rolling(14).mean()
loss = (-delta.clip(upper=0)).rolling(14).mean()
rsi = (100 - 100 / (1 + gain / (loss + 1e-9))).values
sma20 = pd.Series(C_weekly).rolling(20).mean().values
ret_8w = C_weekly / np.roll(C_weekly, 8) - 1

bottom = (rsi > 20) & (rsi < 35) & (ret_8w < -0.1) & (C_weekly < sma20)
sig_idx = np.where(bottom)[0]
n = len(weekly)

print(f"周线: {n}根, 信号: {len(sig_idx)}次")

# 入场日线级模拟（持仓N周）
print(f"\n{'='*65}")
print(f"📈 逐周持有（10x杠杆，不含SL/TP，含手续费）")
print(f"{'='*65}")

LEVERAGE = 10
FEE_RATE = 0.0005

# 找入场后的日线
for hold_weeks in [4, 8, 12]:
    trades = []
    for i in sig_idx:
        entry_week_end = weekly.index[i]
        entry_price = C_weekly[i]
        
        # 找到对应的日线位置
        pos = np.searchsorted(d.index.values, entry_week_end)
        if pos >= len(d):
            continue
        
        # 找到退出日
        exit_days = hold_weeks * 7
        exit_pos = pos + exit_days
        if exit_pos >= len(d):
            continue
        
        exit_price = d.iloc[exit_pos]["c"]
        
        ret_pct = (exit_price / entry_price - 1) * LEVERAGE
        fee = (entry_price + exit_price) / entry_price * FEE_RATE * LEVERAGE
        net_ret = (ret_pct - fee) * 100
        
        trades.append({
            "entry": entry_week_end.date(),
            "exit": d.index[exit_pos].date(),
            "entry_price": entry_price,
            "exit_price": exit_price,
            "ret_pct": round(net_ret, 2),
            "rsi": rsi[i],
        })
    
    if trades:
        df = pd.DataFrame(trades)
        wins = (df["ret_pct"] > 0).sum()
        total_ret = df["ret_pct"].sum()
        cum = (1 + df["ret_pct"] / 100).prod()
        print(f"\n  📌 持有{hold_weeks}周: {len(df)}笔 | 胜率{wins/len(df)*100:.0f}% | 平均{df['ret_pct'].mean():+.2f}% | 复利{cum:.2f}x ({((cum-1)*100):+.0f}%)")
        
        # 看看赢家输家
        print(f"    赢家{wins}笔 平均{df[df['ret_pct']>0]['ret_pct'].mean():+.2f}%  输家{len(df)-wins}笔 平均{df[df['ret_pct']<=0]['ret_pct'].mean():+.2f}%")
        print(f"    最好: {df['ret_pct'].max():+.2f}%  最差: {df['ret_pct'].min():+.2f}%")

# ═══ 3. 关键发现：什么时候应该用宽止损 ═══
print(f"\n{'='*65}")
print(f"💡 关键是：Sniper是周线级别策略，SL太紧就是送")
print(f"{'='*65}")
print(f"""
周线策略的止损应该用 ATR 来算，而不是固定百分比。
当前 BTC ~$63k, 周线 ATR ≈ $3k-$5k ≈ 5-8%
SL=3% 等于不到半个 ATR，几乎必被扫。

建议止损方案：
  1. 如果坚持 SL=3% → 这是1H级别的玩法，不适合周线
  2. 周线级别合理止损 = 1.5x ATR ≈ 8-12%
  3. 或者更聪明：用日线结构止损（前低/重要支撑位）

但 SL 放宽意味着杠杆必须降低，否则单次亏损太大。
""")

# 计算周线 ATR
weekly["tr"] = np.maximum(
    weekly["h"] - weekly["l"],
    np.maximum(
        abs(weekly["h"] - weekly["c"].shift(1)),
        abs(weekly["l"] - weekly["c"].shift(1))
    )
)
weekly["atr14"] = weekly["tr"].rolling(14).mean()
print(f"📊 周线 ATR(14) 统计:")
print(f"  均值: {weekly['atr14'].mean()/weekly['c'].mean()*100:.1f}% 相对于价格")
print(f"  中位数: {weekly['atr14'].median():.0f} USDT")
print(f"  最近值: {weekly['atr14'].iloc[-1]:.0f} USDT (≈{weekly['atr14'].iloc[-1]/weekly['c'].iloc[-1]*100:.1f}%)")
