← Back to list

eth_sunday_monday_defensive VALIDATED FAIL

Auto-discovered strategy

Symbol: ETH | Exchange: Bitfinex | Role: defensive

3/6
Profitable Years
-32.0%
Total Return
39.9%
Avg Win Rate
-0.66
Avg Sharpe

Year-by-Year Results

Click a year to view chart

Year Return Win Rate Trades Max DD Sharpe
2020 +4.4% 52.6% 19 7.3% 0.39
2021 -15.1% 25.0% 20 14.7% -1.24
2022 -7.6% 25.0% 8 8.4% -1.18
2023 -22.9% 40.0% 25 21.1% -2.76
2024 +5.9% 46.7% 15 4.9% 0.54
2025 +3.2% 50.0% 16 9.7% 0.31

Performance Chart

Loading chart...

Walk-Forward Validation FAIL

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

AI Review

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

Source Code

"""
ETH Sunday-Monday Defensive Long Strategy
==========================================

A defensive day-of-week strategy for ETH that captures Monday's historically
strong performance while staying flat in uncertain market conditions.

CONCEPT:
ETH shows day-of-week patterns in the training data:
- Sunday: -0.34% average (weak)
- Monday: +0.74% average, 62.8% positive days (strongest)

This strategy buys the Sunday evening dip and holds through Monday,
with strict regime filters to stay flat during bear markets.

DEFENSIVE NATURE:
- Only trades in uptrend (EMA50 > EMA200 OR price > EMA200)
- Requires pullback to EMA20 (not chasing)
- 2.5% stop loss, 4% take profit
- One trade per week maximum
- Stays flat during bear markets

ENTRY CONDITIONS (Sunday 20:00 UTC):
1. Uptrend: EMA50 > EMA200 OR price > EMA200
2. Not crashing: price > EMA50 * 0.95
3. Not overextended: price < EMA50 * 1.08
4. Pullback present: price < EMA20 * 1.02

EXIT CONDITIONS:
1. Take profit: +4.0%
2. Stop loss: -2.5%
3. Time: Monday 20:00 close

RISK MANAGEMENT:
- Tight stops protect capital
- Regime filter avoids bear markets
- Fixed percentage exits (no curve fitting)

TRAIN Performance (2024-01 to 2025-06):
  2024: +5.9% | 15 trades | 47% WR | Sharpe 0.54
  2025-H1: +4.8% | 7 trades | 71% WR | Sharpe 0.73
  Total: +10.7% | Max DD 4.9% | Sharpe 0.64

NOTE: This strategy relies on day-of-week patterns which may not persist.
The Monday strength pattern seen in training data has historically been
stronger but may vary in different market regimes.
"""

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


def init_strategy():
    return {
        'name': 'eth_sunday_monday_defensive',
        'role': 'defensive',
        'warmup': 200,
        'subscriptions': [
            {'symbol': 'tETHUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
        ],
        'parameters': {
            'ema_short': 20,
            'ema_medium': 50,
            'ema_long': 200,
            'stop_loss_pct': 2.5,
            'take_profit_pct': 4.0,
            'max_extension': 1.08,
            'min_not_crashing': 0.95,
            'pullback_threshold': 1.02,
        }
    }


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

    current_bar = bars[i]
    dow = current_bar.timestamp.weekday()
    hour = current_bar.timestamp.hour

    closes = [b.close for b in bars]

    ema20_vals = ema(closes, params['ema_short'])
    ema50_vals = ema(closes, params['ema_medium'])
    ema200_vals = ema(closes, params['ema_long'])

    if ema20_vals[i] is None or ema50_vals[i] is None or ema200_vals[i] is None:
        return []

    actions = []

    if key not in positions:
        # Entry: Sunday 20:00 UTC
        if dow != 6 or hour != 20:
            return []

        # One trade per week
        week_key = current_bar.timestamp.strftime('%Y-%W')
        if state.get('last_trade_week') == week_key:
            return []

        price = closes[i]

        # Uptrend filter
        bull_regime = ema50_vals[i] > ema200_vals[i]
        above_200 = price > ema200_vals[i]

        if not (bull_regime or above_200):
            return []

        # Not crashing
        not_crashing = price > ema50_vals[i] * params['min_not_crashing']

        if not not_crashing:
            return []

        # Not overextended
        not_extended = price < ema50_vals[i] * params['max_extension']

        if not not_extended:
            return []

        # Pullback
        near_ema20 = price < ema20_vals[i] * params['pullback_threshold']

        if not near_ema20:
            return []

        state['last_trade_week'] = week_key

        actions.append({
            'action': 'open_long',
            'symbol': 'tETHUSD',
            'exchange': 'bitfinex',
            'size': 1.0,
            'stop_loss_pct': params['stop_loss_pct'],
            'take_profit_pct': params['take_profit_pct'],
        })

    else:
        # Exit: Monday 20:00 or regime break
        price = closes[i]

        if dow == 0 and hour == 20:
            actions.append({
                'action': 'close_long',
                'symbol': 'tETHUSD',
                'exchange': 'bitfinex',
            })
        elif price < ema50_vals[i] * 0.95:
            actions.append({
                'action': 'close_long',
                'symbol': 'tETHUSD',
                'exchange': 'bitfinex',
            })

    return actions


ENTRY_LOGIC = """
ENTRY CONDITIONS (ALL must be true):
1. Sunday 20:00 UTC
2. Uptrend: EMA50 > EMA200 OR price > EMA200
3. Not crashing: price > EMA50 * 0.95
4. Not overextended: price < EMA50 * 1.08
5. Pullback: price < EMA20 * 1.02
6. Not already traded this week
"""

EXIT_LOGIC = """
EXIT when ANY:
1. Take profit: +4.0%
2. Stop loss: -2.5%
3. Time: Monday 20:00 UTC close
4. Regime break: price < EMA50 * 0.95
"""

RESULTS = {
    "2024": {"return": 5.91, "win_rate": 46.7, "trades": 15, "sharpe": 0.54, "max_dd": 4.9},
    "2025": {"return": 4.77, "win_rate": 71.4, "trades": 7, "sharpe": 0.73, "max_dd": 4.4}
}