← Back to list

volume_surge_momentum_breakout VALIDATED FAIL

Auto-discovered strategy

Symbol: BTC | Exchange: Bitfinex | Role: momentum

6/6
Profitable Years
+111.8%
Total Return
42.8%
Avg Win Rate
0.93
Avg Sharpe

Year-by-Year Results

Click a year to view chart

Year Return Win Rate Trades Max DD Sharpe
2020 +25.2% 36.7% 30 15.0% 0.74
2021 +34.3% 53.3% 15 5.0% 1.57
2022 +8.4% 66.7% 3 1.9% 0.94
2023 +5.5% 28.6% 21 13.9% 0.23
2024 +30.1% 41.7% 24 17.7% 1.19
2025 +8.3% 30.0% 10 3.4% 0.89

Performance Chart

Loading chart...

Walk-Forward Validation FAIL

0/1 Windows Profitable
-2.8% OOS Return
0.00 Median Sharpe
0.000 Score
Window Train Period Val Period Val Return Val Test Period Test Return Status
WF-1 2024-01→2025-06 2025-07→2025-12 -2.8% FAIL 2026-01→ongoing +0.0% FAIL

AI Review

Not yet reviewed. Run: ./review_strategy.sh volume_surge_momentum_breakout

Source Code

#!/usr/bin/env python3
"""
Volume Surge Momentum Breakout Strategy
========================================

CONCEPT: Captures momentum continuation moves when volume surges on a new high
within an established uptrend. Uses strict regime filtering to stay flat in
bear markets.

ENTRY CONDITIONS (all must be true):
1. Bull regime: EMA50 > EMA200 (macro uptrend)
2. EMA alignment: EMA20 > EMA50 (strong momentum)
3. Price above EMA20 (trend confirmation)
4. Volume surge: >= 2x 20-bar average
5. New 10-bar high (breakout)
6. Bullish candle (close > open)

EXIT CONDITIONS:
1. Close below EMA20 (momentum loss) OR
2. Regime turns bearish (EMA50 < EMA200)

RISK MANAGEMENT:
- 5% stop loss
- 15% take profit
- No trades in bear markets (regime filter)

ROLE: momentum - Expected to profit in bull, acceptable bounded loss in bear
"""

import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema, sma


def init_strategy():
    return {
        'name': 'volume_surge_momentum_breakout',
        'role': 'momentum',
        'warmup': 200,
        'role': 'momentum',  # Trend following, may lose bounded in bear
        'subscriptions': [
            {'symbol': 'tBTCUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
        ],
        'parameters': {
            'ema_fast': 20,
            'ema_mid': 50,
            'ema_slow': 200,
            'volume_mult': 2.0,
            'breakout_period': 10,
            'stop_loss_pct': 5,
            'take_profit_pct': 15,
        }
    }


def process_time_step(ctx):
    key = ('tBTCUSD', 'bitfinex')
    bars = ctx['bars'][key]
    i = ctx['i']
    positions = ctx['positions']
    state = ctx['state']

    # Warmup period for EMA200
    if i < 200:
        return []

    # Pre-compute indicators (cached in state)
    if 'ema20' not in state:
        closes = [b.close for b in bars]
        highs = [b.high for b in bars]
        volumes = [b.volume for b in bars]

        state['ema20'] = ema(closes, 20)
        state['ema50'] = ema(closes, 50)
        state['ema200'] = ema(closes, 200)
        state['vol_sma'] = sma(volumes, 20)
        state['highs'] = highs

    ema20 = state['ema20']
    ema50 = state['ema50']
    ema200 = state['ema200']
    vol_sma = state['vol_sma']
    highs = state['highs']

    actions = []

    # Safety: check for None values
    if ema50[i] is None or ema200[i] is None or vol_sma[i] is None or ema20[i] is None:
        return []

    # REGIME FILTER: Bull market only
    in_bull_regime = ema50[i] > ema200[i]

    if key not in positions:
        # === ENTRY LOGIC ===

        # Hard filter: No trades in bear market
        if not in_bull_regime:
            return []

        # 1. EMA alignment: strong momentum (EMA20 > EMA50)
        ema_aligned = ema20[i] > ema50[i]

        # 2. Price above EMA20: confirming trend
        above_ema20 = bars[i].close > ema20[i]

        # 3. Volume surge: >= 2x average
        vol_ratio = bars[i].volume / vol_sma[i] if vol_sma[i] > 0 else 0
        volume_surge = vol_ratio >= 2.0

        # 4. New 10-bar high: breakout confirmation
        high_10 = max(highs[i-10:i])
        new_high = bars[i].close > high_10

        # 5. Bullish candle: close > open
        bullish_candle = bars[i].close > bars[i].open

        # All conditions must be met
        if ema_aligned and above_ema20 and volume_surge and new_high and bullish_candle:
            actions.append({
                'action': 'open_long',
                'symbol': 'tBTCUSD',
                'exchange': 'bitfinex',
                'size': 1.0,
                'stop_loss_pct': 5,
                'take_profit_pct': 15,
            })
    else:
        # === EXIT LOGIC ===

        # 1. Momentum loss: close below EMA20
        below_ema20 = bars[i].close < ema20[i]

        # 2. Regime turns bearish
        regime_broken = not in_bull_regime

        if below_ema20 or regime_broken:
            actions.append({
                'action': 'close_long',
                'symbol': 'tBTCUSD',
                'exchange': 'bitfinex',
            })

    return actions


if __name__ == "__main__":
    from strategy import backtest_strategy

    print("\n" + "="*60)
    print("VOLUME SURGE MOMENTUM BREAKOUT - BACKTEST")
    print("="*60)

    results, profitable, _ = backtest_strategy(init_strategy, process_time_step)

    print("\n" + "="*60)
    if profitable >= 2:
        print(f"SUCCESS: {profitable}/2 train periods profitable")
        print("Strategy ready for validation on unseen 2025-H2 data")
    else:
        print(f"NEEDS WORK: Only {profitable}/2 profitable")