#!/usr/bin/env python3
"""
ALPHA HUNTER v3 - Push for Sharpe > 2
Advanced parameter optimization and regime detection
"""

import pandas as pd
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

RESULTS_DIR = "/home/node/.openclaw/workspace/crypto-wallet/backtest"
INITIAL_CAPITAL = 10_000
COMMISSION = 0.001

print("=" * 70)
print("🧙‍♂️ ALPHA HUNTER v3 - PUSHING FOR SHARPE > 2")
print("=" * 70)

# ─── LOAD & FEATURES ─────────────────────────────────────────────────────────
df = pd.read_csv(f"{RESULTS_DIR}/btc_ohlcv_2024_2025.csv", parse_dates=["timestamp"], index_col="timestamp")
print(f"📊 Loaded {len(df)} candles")

def compute_features(df):
    df = df.copy()
    df["body"] = df["close"] - df["open"]
    df["upper_wick"] = df["high"] - df[["open", "close"]].max(axis=1)
    df["lower_wick"] = df[["open", "close"]].min(axis=1) - df["low"]
    
    # Volume analysis
    df["vol_avg_20"] = df["volume"].rolling(20).mean()
    df["vol_avg_50"] = df["volume"].rolling(50).mean()
    df["vol_zscore"] = (df["volume"] - df["vol_avg_20"]) / df["volume"].rolling(50).std()
    
    # Delta (buy/sell pressure)
    df["buy_vol"] = np.where(df["body"] > 0, df["volume"] * 0.7, df["volume"] * 0.3)
    df["sell_vol"] = df["volume"] - df["buy_vol"]
    df["delta"] = df["buy_vol"] - df["sell_vol"]
    df["delta_ma"] = df["delta"].rolling(20).mean()
    df["delta_div"] = df["delta"] - df["delta_ma"]
    df["delta_std"] = df["delta_div"].rolling(50).std()
    
    # Momentum
    df["mom_1h"] = df["close"].pct_change(1)
    df["mom_4h"] = df["close"].pct_change(4)
    df["mom_24h"] = df["close"].pct_change(24)
    df["mom_72h"] = df["close"].pct_change(72)
    
    # Funding proxy
    df["funding"] = df["mom_24h"] * 10
    df["funding_abs"] = np.abs(df["funding"])
    
    # Volatility squeeze
    df["atr"] = (df["high"] - df["low"]).rolling(14).mean()
    df["atr_ratio"] = df["atr"] / df["close"]
    df["atr_low"] = df["atr_ratio"].rolling(100).quantile(0.15)
    df["squeeze"] = (df["atr_ratio"] < df["atr_low"]).astype(int)
    
    # Volume spike
    df["vol_spike"] = (df["volume"] > df["vol_avg_20"] * 2).astype(int)
    df["liq_squeeze"] = (df["squeeze"] & df["vol_spike"]).astype(int)
    
    # VPIN
    df["vpin"] = np.abs(df["delta"]) / df["vol_avg_50"]
    df["vpin_ma"] = df["vpin"].rolling(20).mean()
    
    # Multi-TF alignment
    df["bull_all"] = ((df["mom_1h"] > 0) & (df["mom_4h"] > 0) & (df["mom_24h"] > 0)).astype(int)
    df["bear_all"] = ((df["mom_1h"] < 0) & (df["mom_4h"] < 0) & (df["mom_24h"] < 0)).astype(int)
    
    # Regime detection
    df["volatility_regime"] = df["atr_ratio"].rolling(24).mean()
    df["high_vol"] = (df["volatility_regime"] > df["volatility_regime"].quantile(0.75)).astype(int)
    df["low_vol"] = (df["volatility_regime"] < df["volatility_regime"].quantile(0.25)).astype(int)
    
    # Trend strength
    df["trend_4h"] = np.where(df["mom_4h"] > 0.005, 1, np.where(df["mom_4h"] < -0.005, -1, 0))
    df["trend_24h"] = np.where(df["mom_24h"] > 0.01, 1, np.where(df["mom_24h"] < -0.01, -1, 0))
    
    # Exchange flow proxy
    df["up_bar"] = (df["close"] > df["open"]).astype(int)
    df["acc_score"] = df["up_bar"] * df["volume"] / df["vol_avg_20"]
    
    return df

df = compute_features(df)
print("✅ Features computed")

# ─── BACKTESTER ──────────────────────────────────────────────────────────────

def backtest(df, strategy_name, entry_fn, max_hours=36, stop_loss=0.02, take_profit=0.04):
    df = df.dropna().copy().reset_index()
    
    capital = INITIAL_CAPITAL
    position = 0
    entry_price = 0
    entry_idx = 0
    trades = []
    equity = [INITIAL_CAPITAL]
    
    for i in range(1, len(df)):
        signal = entry_fn(df, i)
        price = df.iloc[i]["close"]
        
        if position == 0 and signal == 1:
            position = 1
            entry_price = price
            entry_idx = i
        elif position == 0 and signal == -1:
            position = -1
            entry_price = price
            entry_idx = i
        
        if position != 0:
            pnl = (price - entry_price) / entry_price if position == 1 else (entry_price - price) / entry_price
            held = i - entry_idx
            
            if held >= max_hours or pnl <= -stop_loss or pnl >= take_profit:
                capital *= (1 + pnl - COMMISSION)
                trades.append({
                    "type": "LONG" if position == 1 else "SHORT",
                    "entry": entry_price,
                    "exit": price,
                    "pnl": round(pnl * 100, 2),
                    "held": held,
                    "exit_type": "sl" if pnl < -stop_loss else "tp" if pnl > take_profit else "time"
                })
                position = 0
                entry_price = 0
        
        equity.append(capital)
    
    if position != 0:
        price = df.iloc[-1]["close"]
        pnl = (price - entry_price) / entry_price if position == 1 else (entry_price - price) / entry_price
        capital *= (1 + pnl - COMMISSION)
        trades[-1].update({"exit": price, "pnl": round(pnl * 100, 2)})
    
    equity[-1] = capital
    
    eq = pd.Series(equity)
    returns = eq.pct_change().dropna()
    winning = [t for t in trades if t["pnl"] > 0]
    losing = [t for t in trades if t["pnl"] <= 0]
    
    sharpe = returns.mean() / returns.std() * np.sqrt(365 * 24) if returns.std() > 0 else 0
    max_dd = ((eq - eq.cummax()) / eq.cummax()).min() * 100
    
    return {
        "strategy": strategy_name,
        "return": round((capital - INITIAL_CAPITAL) / INITIAL_CAPITAL * 100, 1),
        "sharpe": round(sharpe, 2),
        "trades": len(trades),
        "win_rate": round(len(winning) / len(trades) * 100, 0) if trades else 0,
        "max_dd": round(max_dd, 1),
        "winners": len(winning),
        "losers": len(losing),
        "equity": equity,
        "avg_held": np.mean([t["held"] for t in trades]) if trades else 0
    }

# ─── STRATEGIES ──────────────────────────────────────────────────────────────

results = []

# 1. FUNDING TIMING VARIANTS
print("\n📈 FUNDING RATE TIMING VARIANTS...")

def funding_v1(df, i):
    row = df.iloc[i]
    if row["funding_abs"] < 0.002 and row["mom_1h"] > 0:
        return 1
    if row["funding_abs"] < 0.002 and row["mom_1h"] < 0:
        return -1
    return 0

for h in [24, 36, 48]:
    for sl in [0.015, 0.02, 0.025]:
        for tp in [0.03, 0.04, 0.05]:
            r = backtest(df, f"Funding_T_{h}_SL{sl}_TP{tp}", funding_v1, h, sl, tp)
            results.append(r)

# 2. SQUEEZE EXPLOSION VARIANTS
print("📈 SQUEEZE EXPLOSION VARIANTS...")

def squeeze_v1(df, i):
    row = df.iloc[i]
    if row["liq_squeeze"] == 1:
        if row["bull_all"] == 1: return 1
        if row["bear_all"] == 1: return -1
    return 0

for h in [24, 36, 48]:
    for sl in [0.02, 0.03]:
        for tp in [0.04, 0.06]:
            r = backtest(df, f"Squeeze_T{h}_SL{sl}_TP{tp}", squeeze_v1, h, sl, tp)
            results.append(r)

# 3. VPIN + MOMENTUM
print("📈 VPIN + MOMENTUM VARIANTS...")

def vpin_mom(df, i):
    row = df.iloc[i]
    if row["vpin"] > row["vpin_ma"] * 1.5:
        if row["mom_4h"] > 0.002: return 1
        if row["mom_4h"] < -0.002: return -1
    return 0

for h in [24, 36]:
    for sl in [0.02, 0.025]:
        for tp in [0.04, 0.05]:
            r = backtest(df, f"VPIN_Mom_T{h}_SL{sl}_TP{tp}", vpin_mom, h, sl, tp)
            results.append(r)

# 4. REGIME-AWARE STRATEGIES
print("📈 REGIME-AWARE STRATEGIES...")

def regime_long(df, i):
    """Only trade in low vol regimes"""
    row = df.iloc[i]
    if row["low_vol"] == 1:
        if row["mom_1h"] > 0 and row["delta_div"] > 0:
            return 1
    return 0

def regime_short(df, i):
    """Only trade in high vol regimes"""
    row = df.iloc[i]
    if row["high_vol"] == 1:
        if row["mom_1h"] < 0 and row["delta_div"] < 0:
            return -1
    return 0

def regime_entry(df, i):
    row = df.iloc[i]
    if row["low_vol"] == 1:
        if row["mom_1h"] > 0 and row["delta_div"] > row["delta_std"]:
            return 1
    if row["high_vol"] == 1:
        if row["mom_1h"] < 0 and row["delta_div"] < -row["delta_std"]:
            return -1
    return 0

for h in [24, 36, 48]:
    for sl in [0.02, 0.025]:
        for tp in [0.04, 0.05, 0.06]:
            r = backtest(df, f"Regime_T{h}_SL{sl}_TP{tp}", regime_entry, h, sl, tp)
            results.append(r)

# 5. TREND CONFIRMED DELTA
print("📈 TREND CONFIRMED DELTA...")

def trend_delta(df, i):
    row = df.iloc[i]
    lookback = 500
    start = max(0, i - lookback)
    q90 = df["delta_div"].iloc[start:i].quantile(0.9) if i > lookback else df["delta_div"].quantile(0.9)
    q10 = df["delta_div"].iloc[start:i].quantile(0.1) if i > lookback else df["delta_div"].quantile(0.1)
    
    if row["trend_24h"] == 1 and row["delta_div"] > q90:
        return 1
    if row["trend_24h"] == -1 and row["delta_div"] < q10:
        return -1
    return 0

for h in [36, 48]:
    for sl in [0.02, 0.025, 0.03]:
        for tp in [0.04, 0.05]:
            r = backtest(df, f"TrendDelta_T{h}_SL{sl}_TP{tp}", trend_delta, h, sl, tp)
            results.append(r)

# 6. ACCUMULATION SCORE
print("📈 ACCUMULATION SCORE...")

def accum_score(df, i):
    row = df.iloc[i]
    score = 0
    if row["acc_score"] > 1.5: score += 1
    if row["delta_div"] > 0: score += 1
    if row["funding_abs"] < 0.003: score += 1
    if row["mom_4h"] > 0: score += 1
    if score >= 3:
        return 1
    return 0

for h in [36, 48, 72]:
    for sl in [0.02, 0.025]:
        for tp in [0.04, 0.05]:
            r = backtest(df, f"Accum_T{h}_SL{sl}_TP{tp}", accum_score, h, sl, tp)
            results.append(r)

# 7. COMBO: Funding + Delta + Squeeze
print("📈 COMBO: FUNDING + DELTA + SQUEEZE...")

def combo_v1(df, i):
    row = df.iloc[i]
    score = 0
    if row["funding_abs"] < 0.003: score += 1
    if abs(row["delta_div"]) > row["delta_std"] * 1.5: score += 1
    if row["liq_squeeze"] == 1: score += 1
    if row["mom_4h"] > 0: score += 1
    
    if score >= 3:
        if row["mom_4h"] > 0: return 1
        if row["mom_4h"] < 0: return -1
    return 0

for h in [24, 36, 48]:
    for sl in [0.02, 0.025]:
        for tp in [0.04, 0.05, 0.06]:
            r = backtest(df, f"Combo_T{h}_SL{sl}_TP{tp}", combo_v1, h, sl, tp)
            results.append(r)

# 8. VOLUME BREAKOUT + MOMENTUM
print("📈 VOLUME BREAKOUT + MOMENTUM...")

def vol_mom(df, i):
    row = df.iloc[i]
    if row["vol_zscore"] > 2 and row["mom_4h"] > 0.003:
        return 1
    if row["vol_zscore"] > 2 and row["mom_4h"] < -0.003:
        return -1
    return 0

for h in [24, 36]:
    for sl in [0.02, 0.025]:
        for tp in [0.04, 0.05]:
            r = backtest(df, f"VolMom_T{h}_SL{sl}_TP{tp}", vol_mom, h, sl, tp)
            results.append(r)

# ─── TOP RESULTS ──────────────────────────────────────────────────────────────

print("\n" + "=" * 70)
print("🏆 TOP 20 STRATEGIES (by Sharpe)")
print("=" * 70)

sorted_results = sorted(results, key=lambda x: x["sharpe"], reverse=True)

for i, r in enumerate(sorted_results[:20], 1):
    emoji = "🎯" if r["sharpe"] > 2 else "📊" if r["sharpe"] > 0 else "❌"
    print(f"  {emoji} {i:2d}. {r['strategy']:35s} | Sharpe: {r['sharpe']:+.2f} | Return: {r['return']:+.1f}% | Trades: {r['trades']:3d} | Win: {r['win_rate']:.0f}% | DD: {r['max_dd']:.1f}%")

best = sorted_results[0]
print(f"\n🥇 BEST: {best['strategy']}")
print(f"   Sharpe: {best['sharpe']} | Return: {best['return']}% | Trades: {best['trades']} | Win: {best['win_rate']}% | DD: {best['max_dd']}%")
print(f"   Avg Held: {best['avg_held']:.1f}h")

# ─── SAVE RESULTS ─────────────────────────────────────────────────────────────

results_df = pd.DataFrame([{k: v for k, v in r.items() if k != 'equity'} for r in sorted_results])
results_df.to_csv(f"{RESULTS_DIR}/alpha_hunter_v3_results.csv", index=False)

print(f"\n✅ Results saved to {RESULTS_DIR}/alpha_hunter_v3_results.csv")

# ─── PLOT TOP 4 ──────────────────────────────────────────────────────────────

top4 = sorted_results[:4]
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
fig.suptitle("ALPHA HUNTER v3 - Top 4 Optimized | BTC/USDT 2024-2025", fontsize=14, fontweight='bold')
colors = ["#2ecc71", "#3498db", "#e74c3c", "#9b59b6"]

for idx, r in enumerate(top4):
    ax = axes[idx // 2, idx % 2]
    ax.plot(r["equity"], color=colors[idx], linewidth=1.5)
    ax.set_title(f"{r['strategy']}\nSharpe: {r['sharpe']} | Return: {r['return']}%", fontweight='bold')
    ax.set_ylabel("Capital ($)")
    ax.grid(True, alpha=0.3)
    ax.axhline(INITIAL_CAPITAL, color='gray', linestyle='--', alpha=0.5)

plt.tight_layout()
plt.savefig(f"{RESULTS_DIR}/alpha_hunter_v3_results.png", dpi=150, bbox_inches='tight')
print(f"💾 Chart saved: {RESULTS_DIR}/alpha_hunter_v3_results.png")
plt.close()
