← Back to list

volume_thrust_momentum

Volume Thrust Multi-Timeframe Momentum A volume spike pattern strategy that enters on high-volume breakouts with strong trend alignment and exits dynamically based on momentum deterioration.

Symbol: BTC | Exchange: Bitfinex

6/6
Profitable Years
+58.6%
Total Return
42.6%
Avg Win Rate
0.62
Avg Sharpe

Year-by-Year Results

Year Return Win Rate Trades Max DD Sharpe
2020 +11.9% 31.6% 19 12.0% 0.49
2021 +1.7% 33.3% 9 8.0% 0.10
2022 +8.9% 60.0% 5 2.3% 1.24
2023 +7.0% 33.3% 18 9.6% 0.40
2024 +25.7% 47.4% 19 13.3% 1.00
2025 +3.3% 50.0% 4 3.1% 0.50

Entry Logic

See strategy file

Exit Logic

See strategy file

Source Code

"""
Strategy: volume_thrust_momentum
================================
Volume Thrust Multi-Timeframe Momentum

A volume spike pattern strategy that enters on high-volume breakouts with strong
trend alignment and exits dynamically based on momentum deterioration.

Entry Conditions:
- Volume surge: 3x the 25-bar average (strong institutional participation)
- Price breakout: Close above 12-bar high (breakout confirmation)
- Strong close: Bar closes in top 25% of its range (buying pressure)
- Trend alignment: Price > EMA20 > EMA50 (multi-timeframe momentum)
- Recent momentum: Price higher than 5 bars ago (sustained thrust)

Exit Conditions:
- Price closes below EMA15 (momentum fading), OR
- 7% trailing stop from recent 8-bar peak (profit protection)

Performance: 6/6 years profitable | Total: +58.6%
2020: +11.9% | 32% WR | 19 trades
2021: +1.7% | 33% WR | 9 trades
2022: +8.9% | 60% WR | 5 trades
2023: +7.0% | 33% WR | 18 trades
2024: +25.7% | 47% WR | 19 trades
2025: +3.3% | 50% WR | 4 trades
"""
import sys
sys.path.insert(0, "/root/trade_rules")
from lib import ema


def init_strategy():
    return {
        'name': 'volume_thrust_momentum',
        'subscriptions': [
            {'symbol': 'tBTCUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
        ],
        'parameters': {}
    }


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

    if not bars or i >= len(bars) or i < 100:
        return []

    closes = [b.close for b in bars]
    highs = [b.high for b in bars]
    lows = [b.low for b in bars]
    volumes = [b.volume for b in bars]

    # Calculate EMAs
    ema15 = ema(closes, 15)
    ema20 = ema(closes, 20)
    ema50 = ema(closes, 50)

    if ema15[i] is None or ema20[i] is None or ema50[i] is None:
        return []

    actions = []
    has_position = key in positions

    if not has_position:
        # Entry: volume surge with breakout and trend alignment
        # Volume surge: 3x 25-bar average
        vol_sma25 = sum(volumes[i-25:i]) / 25
        if volumes[i] < vol_sma25 * 3.0:
            return []

        # Price breakout: above 12-bar high
        high_12 = max(highs[i-12:i])
        if closes[i] <= high_12:
            return []

        # Strong close: top 25% of bar range
        bar_range = bars[i].high - bars[i].low
        if bar_range > 0:
            close_position = (closes[i] - bars[i].low) / bar_range
            if close_position < 0.75:
                return []

        # Trend alignment: price > EMA20 > EMA50
        if closes[i] < ema20[i]:
            return []
        if ema20[i] < ema50[i]:
            return []

        # Momentum: positive 5-bar rate of change
        if closes[i] <= closes[i-5]:
            return []

        actions.append({
            'action': 'open_long',
            'symbol': 'tBTCUSD',
            'exchange': 'bitfinex',
            'size': 1.0,
        })
    else:
        # Exit on momentum fade or trailing stop
        # Dynamic exit: price closes below EMA15
        if closes[i] < ema15[i]:
            actions.append({
                'action': 'close_long',
                'symbol': 'tBTCUSD',
                'exchange': 'bitfinex',
            })
        # Or 7% trailing stop
        elif i >= 8:
            recent_peak = max(highs[i-8:i+1])
            if closes[i] < recent_peak * 0.93:
                actions.append({
                    'action': 'close_long',
                    'symbol': 'tBTCUSD',
                    'exchange': 'bitfinex',
                })

    return actions