Auto-discovered strategy
Symbol: DOGE | Exchange: Binance | Role: momentum
Click a year to view chart
| Year | Return | Win Rate | Trades | Max DD | Sharpe |
|---|---|---|---|---|---|
| 2020 | +39.1% | 26.1% | 23 | 23.2% | 0.94 |
| 2021 | +332.1% | 31.2% | 16 | 21.9% | 0.96 |
| 2022 | -22.1% | 20.0% | 10 | 20.5% | -2.03 |
| 2023 | -1.4% | 30.4% | 23 | 15.4% | -0.05 |
| 2024 | +237.4% | 26.1% | 23 | 24.9% | 1.40 |
| 2025 | +19.7% | 21.4% | 14 | 18.4% | 0.56 |
| Window | Train Period | Val Period | Val Return | Val | Test Period | Test Return | Status |
|---|---|---|---|---|---|---|---|
| WF-1 | 2024-01→2025-06 | 2025-07→2025-12 | -16.9% | FAIL | 2026-01→ongoing | +0.0% | FAIL |
Not yet reviewed. Run: ./review_strategy.sh doge_ema50_pullback_v2
"""
DOGE EMA50 Pullback Strategy
=============================
Buy pullbacks to EMA50 in confirmed uptrends on DOGE/USDT.
Entry Conditions:
1. Macro uptrend: EMA50 > EMA200
2. Mid-term momentum: EMA100 rising (5-bar slope positive)
3. Pullback zone: Low within 3% of EMA50
4. Bounce confirmed: Close above EMA50
5. Not overextended: Close < EMA50 * 1.10
6. Volume confirmation: Above 80% of 20-bar average
Exit Conditions:
1. Close below EMA50 by 1%
2. EMA100 starts falling (early trend weakness warning)
3. Trend reversal: EMA50 < EMA200
Risk Management:
- 5% stop loss per trade
- Only trades during confirmed uptrends
Train Performance (2024-01 to 2025-06):
- 2024: +237.4% | 23 trades | 26% WR | Sharpe 1.40 | MaxDD 24.9%
- 2025H1: +13.2% | 6 trades | 33% WR | Sharpe 0.61 | MaxDD 5.6%
- Total: +250.6% | Profit Factor: 4.59
"""
import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema, sma, atr
def init_strategy():
return {
'name': 'doge_ema50_pullback_v2',
'role': 'momentum',
'warmup': 200,
'subscriptions': [
{'symbol': 'DOGEUSDT', 'exchange': 'binance', 'timeframe': '4h'},
],
'parameters': {}
}
def process_time_step(ctx):
key = ('DOGEUSDT', 'binance')
bars = ctx['bars'][key]
i = ctx['i']
positions = ctx['positions']
# Initialize indicators once
if 'indicators' not in ctx['state']:
closes = [b.close for b in bars]
lows = [b.low for b in bars]
highs = [b.high for b in bars]
volumes = [b.volume for b in bars]
ctx['state']['indicators'] = {
'ema50': ema(closes, 50),
'ema100': ema(closes, 100),
'ema200': ema(closes, 200),
'atr': atr(highs, lows, closes, 20),
'vol_sma': sma(volumes, 20),
}
ind = ctx['state']['indicators']
# Safety checks
if ind['ema50'][i] is None or ind['ema100'][i] is None or ind['ema200'][i] is None:
return []
if ind['atr'][i] is None or ind['vol_sma'][i] is None:
return []
actions = []
if key not in positions:
# === ENTRY CONDITIONS ===
# 1. MACRO REGIME: EMA50 > EMA200 (uptrend)
macro_uptrend = ind['ema50'][i] > ind['ema200'][i]
if not macro_uptrend:
return []
# 2. MID REGIME: EMA100 rising (5-bar slope positive)
if i >= 5 and ind['ema100'][i-5] is not None:
ema100_rising = ind['ema100'][i] > ind['ema100'][i-5]
else:
ema100_rising = False
if not ema100_rising:
return []
# 3. PULLBACK: Low within 3% of EMA50
ema50 = ind['ema50'][i]
low = bars[i].low
pullback_zone = low <= ema50 * 1.03 and low >= ema50 * 0.97
# 4. BOUNCE: Close above EMA50
close_above = bars[i].close > ema50
# 5. NOT OVER-EXTENDED: Close within 10% of EMA50
not_extended = bars[i].close < ema50 * 1.10
# 6. VOLUME: Above 80% average
volume_ok = bars[i].volume > ind['vol_sma'][i] * 0.8
if pullback_zone and close_above and not_extended and volume_ok:
actions.append({
'action': 'open_long',
'symbol': 'DOGEUSDT',
'exchange': 'binance',
'size': 1.0,
'stop_loss_pct': 5.0,
})
else:
# === EXIT CONDITIONS ===
# Exit if close below EMA50 by 1%
if bars[i].close < ind['ema50'][i] * 0.99:
actions.append({
'action': 'close_long',
'symbol': 'DOGEUSDT',
'exchange': 'binance',
})
# Exit if EMA100 starts falling (early warning)
elif i >= 5 and ind['ema100'][i-5] is not None and ind['ema100'][i] <= ind['ema100'][i-5]:
actions.append({
'action': 'close_long',
'symbol': 'DOGEUSDT',
'exchange': 'binance',
})
# Exit if trend reverses
elif ind['ema50'][i] < ind['ema200'][i]:
actions.append({
'action': 'close_long',
'symbol': 'DOGEUSDT',
'exchange': 'binance',
})
return actions
# For direct testing
if __name__ == '__main__':
from strategy import backtest_strategy
print("Testing DOGE EMA50 Pullback V2")
print("="*50)
results, profitable, _ = backtest_strategy(init_strategy, process_time_step)