Auto-discovered strategy
Symbol: SOL | Exchange: Binance | Role: momentum
Click a year to view chart
| Year | Return | Win Rate | Trades | Max DD | Sharpe |
|---|---|---|---|---|---|
| 2020 | -40.0% | 9.1% | 11 | 34.1% | -2.80 |
| 2021 | +106.1% | 37.1% | 202 | 52.1% | 1.08 |
| 2022 | +15.2% | 34.8% | 23 | 20.1% | 0.46 |
| 2023 | +111.8% | 43.5% | 85 | 37.2% | 1.78 |
| 2024 | +83.4% | 36.9% | 65 | 30.0% | 1.60 |
| 2025 | +27.1% | 37.9% | 29 | 17.4% | 0.74 |
| Window | Train Period | Val Period | Val Return | Val | Test Period | Test Return | Status |
|---|---|---|---|---|---|---|---|
| WF-1 | 2024-01→2025-06 | 2025-07→2025-12 | +4.5% | OK | 2026-01→ongoing | +0.0% | PASS |
Not yet reviewed. Run: ./review_strategy.sh sol_ema_momentum
"""
SOL EMA Momentum Strategy
=========================
A momentum-following strategy for SOLUSDT that enters long positions during
confirmed bullish regimes and takes profits systematically.
Strategy Logic:
- ENTRY: When EMA50 > EMA200 (bullish regime) AND price > EMA20 AND EMA20 is rising
- EXIT: When price falls below EMA100 OR hits stop loss (5%) OR take profit (10%)
Key Features:
- Uses relative EMA relationships only (no specific price levels)
- Standard EMA periods (20, 50, 100, 200) - no curve-fitting
- Fixed 10% take profit to lock in gains and reduce concentration
- 5% stop loss for risk management
- Only trades in bullish regimes - stays flat in bear markets
Role: momentum
- Expected to profit in bull markets, flat/small loss in bear markets
- Validation allows: -15% loss, sharpe >= -0.5, max DD 40%
"""
import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema
def init_strategy():
return {
'name': 'sol_ema_momentum',
'role': 'momentum',
'warmup': 200,
'subscriptions': [
{'symbol': 'SOLUSDT', 'exchange': 'binance', 'timeframe': '4h'},
],
'parameters': {}
}
def process_time_step(ctx):
"""
Process each time step and return trade actions.
Entry Logic:
1. Bullish regime: EMA50 > EMA200
2. Price above EMA20 (short-term momentum)
3. EMA20 rising over last 5 bars (momentum confirmation)
Exit Logic:
1. Price falls below EMA100 (trend weakening)
2. Stop loss at 5% (risk management)
3. Take profit at 10% (lock in gains)
"""
key = ('SOLUSDT', 'binance')
bars = ctx['bars'][key]
i = ctx['i']
positions = ctx['positions']
actions = []
# Extract close prices for indicator calculation
closes = [b.close for b in bars[:i+1]]
# Calculate EMAs
ema20 = ema(closes, 20)
ema50 = ema(closes, 50)
ema100 = ema(closes, 100)
ema200 = ema(closes, 200)
price = closes[-1]
# Need valid indicator values
if ema50[-1] is None or ema200[-1] is None or ema20[-1] is None or ema100[-1] is None:
return []
if len(ema20) < 5 or ema20[-5] is None:
return []
# Entry conditions
bullish_regime = ema50[-1] > ema200[-1]
price_above_ema20 = price > ema20[-1]
ema20_rising = ema20[-1] > ema20[-5]
# Exit condition
price_below_ema100 = price < ema100[-1]
if key not in positions:
# Enter long when all conditions met
if bullish_regime and price_above_ema20 and ema20_rising:
actions.append({
'action': 'open_long',
'symbol': 'SOLUSDT',
'exchange': 'binance',
'size': 1.0,
'stop_loss_pct': 5.0,
'take_profit_pct': 10.0,
})
else:
# Exit when price falls below EMA100
if price_below_ema100:
actions.append({
'action': 'close_long',
'symbol': 'SOLUSDT',
'exchange': 'binance',
})
return actions
if __name__ == '__main__':
from strategy import backtest_strategy
results, profitable, _ = backtest_strategy(init_strategy, process_time_step)