← Back to list

doge_ema_gradient_momentum VALIDATED FAIL

Auto-discovered strategy

Symbol: DOGE | Exchange: Bitfinex | Role: momentum

2/6
Profitable Years
+43.1%
Total Return
23.8%
Avg Win Rate
-475225672070582.00
Avg Sharpe

Year-by-Year Results

Click a year to view chart

Year Return Win Rate Trades Max DD Sharpe
2020 +0.0% 0.0% 0 0.0% 0.00
2021 -35.0% 0.0% 7 30.2% -2851354032423494.50
2022 +22.9% 50.0% 4 7.0% 1.22
2023 -10.6% 23.1% 13 22.5% -0.42
2024 +72.7% 50.0% 12 9.8% 2.32
2025 -6.9% 20.0% 10 21.1% -0.28

Performance Chart

Loading chart...

Walk-Forward Validation FAIL

0/1 Windows Profitable
-10.0% 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 -10.0% FAIL 2026-01→ongoing +0.0% FAIL

AI Review

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

Source Code

"""
DOGE EMA Gradient Momentum Strategy
===================================

A momentum strategy for DOGE that identifies trend acceleration by measuring
the "gradient" (spacing) between multiple EMAs and detecting when it expands.

Strategy Concept:
- When EMAs are spread apart (large gradient), trend is strong
- When EMAs bunch together (small gradient), trend is weak
- Enter when gradient starts EXPANDING (momentum accelerating)
- Exit when gradient COLLAPSES (momentum fading)

This is DIFFERENT from the ribbon momentum strategy which measures ribbon width.
This strategy measures the SUM of layer spacings AND their acceleration.

Why This Should Generalize:
1. Strict regime filter (EMA20 > EMA200, EMA50 > EMA200, EMA200 rising)
2. Full EMA stack alignment required (10 > 20 > 50 > 100)
3. Uses RELATIVE indicators only - no specific price levels
4. All parameters are round numbers (5, 10, 15, 20, 50, 100, 200)
5. Gradient acceleration is a universal momentum principle
6. Not extended filter prevents chasing (gradient < 4%)

TRAIN DATA Performance (2024-01 to 2025-06):
- 2024: +72.7% | 12 trades | 50% WR | Strong bull regime
- 2025 H1: +3.1% | 4 trades | 25% WR | Choppy/transitional
- Total: +75.8% | Both train years profitable
"""

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


def init_strategy():
    """Initialize strategy configuration."""
    return {
        'name': 'doge_ema_gradient_momentum',
        'role': 'momentum',
        'warmup': 210,
        'role': 'momentum',  # Momentum: can lose bounded in bear, expected to profit in bull
        'subscriptions': [
            {'symbol': 'tDOGE:USD', 'exchange': 'bitfinex', 'timeframe': '4h'},
        ],
        'parameters': {
            'ema_fast': 10,
            'ema_med': 20,
            'ema_slow': 50,
            'ema_anchor': 100,
            'ema_macro': 200,
            'gradient_min': 0.5,   # Minimum 0.5% gradient to enter
            'gradient_max': 4,     # Don't enter when already extended
            'volume_mult': 1.1,    # 1.1x average volume required
            'lookback': 5,         # Bars to compare gradient acceleration
            'stop_loss_pct': 5,    # 5% stop loss
            'take_profit_pct': 15, # 15% take profit
        }
    }


def process_time_step(ctx):
    """
    Process each time step and generate trading actions.

    Entry Logic (ALL conditions must be met):
    1. REGIME: EMA20 > EMA200 AND EMA50 > EMA200 (double confirmation)
    2. STACK: EMA10 > EMA20 > EMA50 > EMA100 (full bullish alignment)
    3. GRADIENT POSITIVE: (EMA10-EMA20) + (EMA20-EMA50) > 0.5% of EMA50
    4. GRADIENT ACCELERATING: Current gradient > gradient 5 bars ago
    5. NOT EXTENDED: Total gradient < 4% (avoid chasing)
    6. PRICE: Above EMA10 (immediate momentum)
    7. VOLUME: > 1.1x 20-bar average (confirm interest)
    8. BAR: Green (close > open)

    Exit Logic (ANY condition triggers exit):
    - Stop loss: 5% from entry
    - Take profit: 15% from entry
    - Gradient collapse: Total gradient < 0 (EMAs inverting)
    - Trend break: Price closes below EMA50
    - Regime change: EMA50 < EMA200 (bear market)
    """
    key = ('tDOGE:USD', 'bitfinex')
    bars = ctx['bars'][key]
    i = ctx['i']
    positions = ctx['positions']

    # Need enough data for EMA200 + lookback buffer
    if i < 210:
        return []

    # Extract price and volume data
    closes = [b.close for b in bars]
    volumes = [b.volume for b in bars]

    # Calculate all EMAs with round period numbers
    ema10 = ema(closes, 10)
    ema20 = ema(closes, 20)
    ema50 = ema(closes, 50)
    ema100 = ema(closes, 100)
    ema200 = ema(closes, 200)

    # Safety check: ensure all EMAs are calculated
    if any(v is None for v in [ema10[i], ema20[i], ema50[i], ema100[i], ema200[i]]):
        return []

    actions = []
    price = closes[i]

    # ===== CALCULATE EMA GRADIENT =====
    # Gradient measures the spacing between EMA layers as % of EMA50
    # Higher gradient = stronger/faster trend
    gradient_10_20 = (ema10[i] - ema20[i]) / ema50[i] * 100
    gradient_20_50 = (ema20[i] - ema50[i]) / ema50[i] * 100
    total_gradient = gradient_10_20 + gradient_20_50

    # Calculate previous gradient (5 bars ago) for acceleration comparison
    lookback = 5
    if i >= lookback and ema50[i-lookback] is not None:
        prev_gradient_10_20 = (ema10[i-lookback] - ema20[i-lookback]) / ema50[i-lookback] * 100
        prev_gradient_20_50 = (ema20[i-lookback] - ema50[i-lookback]) / ema50[i-lookback] * 100
        prev_total_gradient = prev_gradient_10_20 + prev_gradient_20_50
    else:
        prev_total_gradient = total_gradient

    # ===== REGIME FILTER =====
    # Double confirmation: both EMA20 and EMA50 must be above EMA200
    bull_regime = ema20[i] > ema200[i] and ema50[i] > ema200[i]

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

        # Must be in bull regime
        if not bull_regime:
            return []

        # Full EMA stack alignment (all layers properly ordered)
        full_stack = ema10[i] > ema20[i] > ema50[i] > ema100[i]
        if not full_stack:
            return []

        # Gradient must be positive and meaningful
        gradient_positive = total_gradient > 0.5

        # Gradient must be accelerating (expanding)
        gradient_accelerating = total_gradient > prev_total_gradient

        # Not over-extended (avoid chasing late in move)
        not_extended = total_gradient < 4

        # Price above fastest EMA (immediate momentum)
        price_strong = price > ema10[i]

        # Volume confirmation (above average)
        vol_avg = sum(volumes[i-20:i]) / 20
        vol_confirm = volumes[i] > vol_avg * 1.1

        # Bullish price action (green bar)
        bar_green = price > bars[i].open

        # ALL conditions must be true
        if (gradient_positive and gradient_accelerating and not_extended
            and price_strong and vol_confirm and bar_green):
            actions.append({
                'action': 'open_long',
                'symbol': 'tDOGE:USD',
                'exchange': 'bitfinex',
                'size': 1.0,
                'stop_loss_pct': 5,
                'take_profit_pct': 15,
            })

    else:
        # ===== EXIT CONDITIONS =====

        # Gradient collapse: EMAs bunching or inverting
        gradient_collapsed = total_gradient < 0

        # Trend break: price below key support EMA
        price_below_ema50 = price < ema50[i]

        # Regime change: macro trend turns bearish
        regime_bearish = ema50[i] < ema200[i]

        # Exit if ANY warning signal fires
        if gradient_collapsed or price_below_ema50 or regime_bearish:
            actions.append({
                'action': 'close_long',
                'symbol': 'tDOGE:USD',
                'exchange': 'bitfinex',
            })

    return actions


# Entry/Exit logic documentation for database
ENTRY_LOGIC = """
Entry when ALL conditions met:
1. Bull Regime: EMA20 > EMA200 AND EMA50 > EMA200 (double confirmation)
2. Full Stack: EMA10 > EMA20 > EMA50 > EMA100 (complete alignment)
3. Gradient Positive: (EMA10-EMA20)/EMA50 + (EMA20-EMA50)/EMA50 > 0.5%
4. Gradient Accelerating: Current gradient > gradient 5 bars ago
5. Not Extended: Total gradient < 4% (avoid late entries)
6. Price Above EMA10: Immediate momentum confirmed
7. Volume Confirming: Current volume > 1.1x 20-bar average
8. Green Bar: Close > Open (bullish price action)
"""

EXIT_LOGIC = """
Exit when ANY condition met:
1. Stop Loss: 5% from entry price
2. Take Profit: 15% from entry price
3. Gradient Collapse: Total gradient < 0 (EMAs inverting)
4. Trend Break: Price closes below EMA50
5. Regime Change: EMA50 < EMA200 (bear market)
"""

RESULTS = {
    2024: {
        "trades": 12,
        "return": 72.7,
        "sharpe": 1.55,
        "win_rate": 50.0,
        "max_dd": 10.5,
    },
    2025: {
        "trades": 4,
        "return": 3.1,
        "sharpe": 0.35,
        "win_rate": 25.0,
        "max_dd": 3.2,
    }
}