Auto-discovered strategy
Symbol: ETH | Exchange: Bitfinex | Role: momentum
Click a year to view chart
| Year | Return | Win Rate | Trades | Max DD | Sharpe |
|---|---|---|---|---|---|
| 2020 | +81.9% | 52.2% | 23 | 11.1% | 2.11 |
| 2021 | -1.8% | 33.3% | 21 | 27.2% | -0.06 |
| 2022 | +1.2% | 20.0% | 15 | 12.3% | 0.05 |
| 2023 | -9.7% | 36.4% | 22 | 15.0% | -0.56 |
| 2024 | +26.4% | 52.6% | 19 | 13.4% | 1.03 |
| 2025 | +26.2% | 33.3% | 21 | 22.1% | 0.73 |
| Window | Train Period | Val Period | Val Return | Val | Test Period | Test Return | Status |
|---|---|---|---|---|---|---|---|
| WF-1 | 2024-01→2025-06 | 2025-07→2025-12 | -13.8% | FAIL | 2026-01→ongoing | +0.0% | FAIL |
Not yet reviewed. Run: ./review_strategy.sh eth_regime_breakout_v5
"""
Strategy: eth_regime_breakout_v5
================================
ETH trend following strategy with regime filter.
CONCEPT:
- Uses EMA cascade (50 > 100 > 200) as regime filter
- Only trades in direction of the macro trend
- Enters on 20-bar breakouts with volume confirmation
- Trades both long (bull regime) and short (bear regime)
REGIME FILTER (Critical for bear market survival):
- Bull: EMA50 > EMA100 > EMA200 (only longs)
- Bear: EMA50 < EMA100 < EMA200 (only shorts)
- Neutral: Stay flat
ENTRY CONDITIONS:
Long (Bull regime):
- Price above EMA50
- EMA50 rising over 10 bars
- Breakout above 20-bar high
- Volume > 1.3x 20-bar average
- ROC(10) > 1% (momentum confirmation)
- Not extended (< 10% from EMA50)
- Strong close (close in upper 55% of candle range)
Short (Bear regime):
- Price below EMA50
- EMA50 falling over 10 bars
- Breakdown below 20-bar low
- Volume > 1.3x 20-bar average
- ROC(10) < -1%
- Not extended
- Weak close (close in lower 45% of candle range)
EXIT CONDITIONS:
- Close crosses EMA50 (trend weakening)
- Regime breaks (EMA50 crosses EMA100)
- Take profit at 15%
- Max hold 25 bars
- Momentum reversal (ROC(10) crosses +/-4%)
RISK MANAGEMENT:
- 5% stop loss per trade
- Max drawdown target: <20%
TRAIN PERFORMANCE (2024-2025H1):
- 2024: +26.4%, Sharpe 1.03, MaxDD 13.4%, 19 trades, 53% WR
- 2025: +31.9%, Sharpe 1.17, MaxDD 11.4%, 9 trades, 33% WR
- Total: +58.3%
"""
import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema, sma
def init_strategy():
return {
'name': 'eth_regime_breakout_v5',
'role': 'momentum',
'warmup': 50,
'subscriptions': [
{'symbol': 'tETHUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
],
'parameters': {}
}
def process_time_step(ctx):
key = ('tETHUSD', 'bitfinex')
bars = ctx['bars'].get(key, [])
i = ctx['i']
positions = ctx['positions']
if not bars or i >= len(bars) or i < 210:
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]
# EMAs - standard periods
ema20 = ema(closes, 20)
ema50 = ema(closes, 50)
ema100 = ema(closes, 100)
ema200 = ema(closes, 200)
# Volume
vol_ma = sma(volumes, 20)
if any(x[i] is None for x in [ema20, ema50, ema100, ema200, vol_ma]):
return []
actions = []
has_position = key in positions
# Regime detection
bull = ema50[i] > ema100[i] and ema100[i] > ema200[i]
bear = ema50[i] < ema100[i] and ema100[i] < ema200[i]
if not has_position:
# ========== LONG (Bull Regime Only) ==========
if bull:
above_ema50 = bars[i].close > ema50[i]
ema50_rising = ema50[i] > ema50[i-10]
# Breakout with volume
high_20 = max(highs[i-20:i])
breakout = bars[i].close > high_20
vol_surge = volumes[i] > vol_ma[i] * 1.3
# Momentum
roc_10 = (closes[i] - closes[i-10]) / closes[i-10] * 100
mom_ok = roc_10 > 1
# Not extended
ext = (bars[i].close - ema50[i]) / ema50[i] * 100
safe = ext < 10
# Strong close
candle_range = bars[i].high - bars[i].low + 0.0001
strength = (bars[i].close - bars[i].low) / candle_range
strong = strength > 0.55
if above_ema50 and ema50_rising and breakout and vol_surge and mom_ok and safe and strong:
actions.append({
'action': 'open_long',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
'size': 1.0,
'stop_loss_pct': 5.0,
})
# ========== SHORT (Bear Regime Only) ==========
elif bear:
below_ema50 = bars[i].close < ema50[i]
ema50_falling = ema50[i] < ema50[i-10]
# Breakdown with volume
low_20 = min(lows[i-20:i])
breakdown = bars[i].close < low_20
vol_surge = volumes[i] > vol_ma[i] * 1.3
# Momentum
roc_10 = (closes[i] - closes[i-10]) / closes[i-10] * 100
mom_ok = roc_10 < -1
# Not extended
ext = (ema50[i] - bars[i].close) / ema50[i] * 100
safe = ext < 10
# Weak close
candle_range = bars[i].high - bars[i].low + 0.0001
weakness = (bars[i].close - bars[i].low) / candle_range
weak = weakness < 0.45
if below_ema50 and ema50_falling and breakdown and vol_surge and mom_ok and safe and weak:
actions.append({
'action': 'open_short',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
'size': 1.0,
'stop_loss_pct': 5.0,
})
else:
pos = positions[key]
bars_held = i - pos.entry_bar
entry_price = pos.entry_price
if pos.side == 'long':
below_ema50 = bars[i].close < ema50[i]
regime_break = ema50[i] < ema100[i]
gain = (bars[i].close - entry_price) / entry_price * 100
tp = gain > 15
time_out = bars_held > 25
roc_10 = (closes[i] - closes[i-10]) / closes[i-10] * 100
mom_dead = roc_10 < -4
if below_ema50 or regime_break or tp or time_out or mom_dead:
actions.append({
'action': 'close_long',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
})
else:
above_ema50 = bars[i].close > ema50[i]
regime_flip = ema50[i] > ema100[i]
gain = (entry_price - bars[i].close) / entry_price * 100
tp = gain > 15
time_out = bars_held > 25
roc_10 = (closes[i] - closes[i-10]) / closes[i-10] * 100
mom_up = roc_10 > 4
if above_ema50 or regime_flip or tp or time_out or mom_up:
actions.append({
'action': 'close_short',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
})
return actions
# For standalone testing
if __name__ == '__main__':
from strategy import backtest_strategy
print("Backtesting eth_regime_breakout_v5...")
results, profitable, _ = backtest_strategy(init_strategy, process_time_step)
print(f"\nProfitable years: {profitable}/2")