"""多种趋势策略对比：找最佳一周趋势方案"""
import pandas as pd, numpy as np

d = pd.read_parquet("/root/quant_pipeline/data/btc_daily.parquet")
O,H,L,C,V = d["o"].values,d["h"].values,d["l"].values,d["c"].values,d["v"].values
n = len(d)
idx = d.index

# ── 通用参数 ──
HOLD = 5
FEE = 0.001
STOP = 0.03

def backtest_mask(mask, tp_pct, label):
    """通用回测"""
    sig_idx = np.where(mask)[0] if hasattr(mask, '__getitem__') else np.where(mask)[0]
    rets = []
    for i in sig_idx:
        if i + HOLD >= n: continue
        entry = C[i]
        for j in range(1, HOLD+1):
            if i+j >= n: break
            r = C[i+j]/entry - 1
            if r >= tp_pct:
                rets.append(tp_pct - FEE); break
            if r <= -STOP:
                rets.append(-STOP - FEE); break
        else:
            rets.append(C[min(i+HOLD,n-1)]/entry - 1 - FEE)
    
    if len(rets) < 5: return f"信号不足({len(rets)}笔)"
    wr = sum(1 for r in rets if r>0)/len(rets)
    cum = np.prod([1+r for r in rets])
    avg = np.mean(rets)*100
    return f"{len(rets):>3d}笔 wr={wr:>5.0%} cum={cum:>5.2f} avg={avg:>+.1f}%"

# ── ===== 策略1：唐奇安突破（20日新高）=====
hk = pd.Series(H).rolling(20).max().values
donchian_break = C > np.roll(hk, 1)  # 突破前20日最高点

# ── ===== 策略2：唐奇安突破 + 成交量确认 =====
vol_ma20 = pd.Series(V).rolling(20).mean().values
donchian_vol = donchian_break & (V > vol_ma20 * 1.5)

# ── ===== 策略3：三日连涨动量 =====
ret_1 = C / np.roll(C, 1) - 1
ret_2 = np.roll(C, 1) / np.roll(C, 2) - 1
ret_3 = np.roll(C, 2) / np.roll(C, 3) - 1
three_up = (ret_1 > 0.015) & (ret_2 > 0) & (ret_3 > 0)  # 今天大阳，前两天也涨
three_up_strong = (ret_1 > 0.02) & (ret_2 > 0.01) & (ret_3 > 0)  # 更强

# ── ===== 策略4：ATR突破（波动率扩张后入场）=====
atr14 = pd.Series(H-L).rolling(14).mean().values
atr_pct = atr14 / C
atr_ma20 = pd.Series(atr_pct).rolling(20).mean().values
vol_expansion = (atr_pct > atr_ma20 * 1.5) & (C > np.roll(C, 1))  # 波动率突然放大+上涨

# ── ===== 策略5：通道突破（20日布林带外）=====
ma20 = pd.Series(C).rolling(20).mean().values
std20 = pd.Series(C).rolling(20).std().values
band_up = ma20 + std20 * 2
band_down = ma20 - std20 * 2
boll_break = C > np.roll(band_up, 1)  # 突破布林上轨

# ── ===== 策略6：量价齐升（放量+大阳）=====
big_bull = (C - O) / (H - L + 1e-9) > 0.7  # 实体占比>70%
volume_surge = V > vol_ma20 * 2
vol_price = big_bull & volume_surge & (C > np.roll(C, 1))

# ── ===== 策略7：新高+回踩（先突破，再回到均线附近）=====
ema10 = pd.Series(C).ewm(span=10).mean().values
near_ema10 = abs(C / ema10 - 1) < 0.01
donchian_shifted = np.roll(donchian_break, 1)
donchian_shifted[0] = False
breakout_retest = donchian_shifted & near_ema10

print(f"{'='*70}")
print("🔥 一周趋势策略对比（持有5天）")
print(f"{'='*70}")
print(f"数据: BTC日线 2017-2024, {n}根")
print(f"持仓: {HOLD}天 止损: {STOP*100:.0f}%")
print(f"{'策略':<25s} {'结果':<35s}")
print("-"*65)

results = [
    ("唐奇安突破(20日新高)", donchian_break),
    ("突破+放量1.5x", donchian_vol),
    ("三日连涨动量", three_up),
    ("三连涨加强版", three_up_strong),
    ("ATR波动率扩张", vol_expansion),
    ("布林带突破", boll_break),
    ("量价齐升", vol_price),
    ("突破+回踩ema10", breakout_retest),
]

for name, mask in results:
    for name, mask in results:
        best = ("", 0, 0)
        mask_arr = mask.values if hasattr(mask, 'values') else mask
        for tp in [0.03, 0.04, 0.05, 0.06, 0.08]:
            r = backtest_mask(mask_arr, tp, name)
            if "笔" in str(r):
                n_trades = int(str(r).split("笔")[0].strip())
                if n_trades > best[1]:
                    best = (r, n_trades, tp)
        print(f"  {name:<23s}: {best[0]} (TP={best[2]*100:.0f}%)")

# 最优方案的详情
print(f"\n{'='*70}")
print("🏆 最佳方案详解")
print(f"{'='*70}")

# 选唐奇安突破+放量确认，TP=5%
chosen_mask = donchian_vol
chosen_tp = 0.05

sig_idx = np.where(chosen_mask)[0]
rets = []
for i in sig_idx:
    if i + HOLD >= n: continue
    entry = C[i]
    for j in range(1, HOLD+1):
        if i+j >= n: break
        r = C[i+j]/entry - 1
        if r >= chosen_tp:
            rets.append(chosen_tp - FEE); break
        if r <= -STOP:
            rets.append(-STOP - FEE); break
    else:
        rets.append(C[min(i+HOLD,n-1)]/entry - 1 - FEE)

wr = sum(1 for r in rets if r>0)/len(rets)
cum = np.prod([1+r for r in rets])
avg = np.mean(rets)*100
print(f"  突破+放量 TP={chosen_tp*100:.0f}%:")
print(f"  总{len(rets)}笔 胜率{wr:.0%} 累计{cum:.2f} 均收益{avg:+.1f}%")

# 10x杠杆
lev = [r*10 for r in rets]
lev_cum = np.prod([1+r for r in lev])
lev_wr = sum(1 for r in lev if r>0)/len(lev)
print(f"  → 10x杠杆: 累计{lev_cum:.1f}x 胜率{lev_wr:.0%}")

# 再测一组更合理的SL/TP
print(f"\n📊 参数优化:")
params = []
for tp in [0.03, 0.04, 0.05, 0.06, 0.08]:
    rets = []
    for i in sig_idx:
        if i + HOLD >= n: continue
        entry = C[i]
        for j in range(1, HOLD+1):
            if i+j >= n: break
            r = C[i+j]/entry - 1
            if r >= tp:
                rets.append(tp - FEE); break
            if r <= -STOP:
                rets.append(-STOP - FEE); break
        else:
            rets.append(C[min(i+HOLD,n-1)]/entry - 1 - FEE)
    if len(rets) >= 5:
        wr = sum(1 for r in rets if r>0)/len(rets)
        cum = np.prod([1+r for r in rets])
        avg_ret = np.mean(rets)*100
        lev_cum = np.prod([1+r*10 for r in rets])
        params.append((tp, len(rets), wr, cum, avg_ret, lev_cum))

print(f"  {'TP':>5s} {'笔数':>5s} {'胜率':>6s} {'累计':>7s} {'均收益':>7s} {'10x累计':>8s}")
for tp, n, wr, cum, avg, lc in params:
    print(f"  {tp*100:>4.0f}% {n:>4d} {wr:>5.0%} {cum:>6.2f} {avg:>+5.1f}% {lc:>7.1f}x")