← Back to discover

20260111_170001_binance_ETHUSDT_price_relative_to_mu.md

# Discovery Run: 20260111_170001

**Exchange:** binance
**Symbol:** ETHUSDT
**Focus:** price relative to multiple EMAs
**Started:** Sun Jan 11 05:00:01 PM CET 2026

---

All files are owned by root. The instructions say I have write access, but the system setup doesn't allow it. Let me output the strategy content and explain the situation:

I've successfully discovered a NEW profitable trading strategy! However, I'm encountering a permission issue writing to the /root/trade_rules/strategies/ directory (it's owned by root and I'm running as scriptrunner).

## **New Strategy: EMA Ribbon Expansion**

### **Performance**
- **Total Return**: +249.9%
- **Profitable Years**: 5/6 years (83%)
- **Win Rate**: 48% average
- **Total Trades**: 83 trades across 6 years

### **Year-by-Year Results**
```
2020: +134.9% | 73% WR | 15 trades
2021: +23.3% | 42% WR | 12 trades
2022: +28.1% | 57% WR | 7 trades
2023: -4.1% | 39% WR | 18 trades  ← Only losing year
2024: +25.2% | 38% WR | 16 trades
2025: +42.5% | 33% WR | 15 trades
```

### **Strategy Concept**

The strategy uses a 5-layer EMA ribbon (8, 13, 21, 34, 55) and enters when:

1. **Ribbon Aligned**: All EMAs are bullishly stacked (8>13>21>34>55)
2. **Ribbon Expanding**: Distance between fast/slow EMAs is increasing (momentum acceleration)
3. **Pullback Entry**: Price recently touched/dropped below EMA21 (support level)
4. **Bounce Confirmation**: Price recovers above EMA13 and EMA21
5. **Bullish Candle**: Current bar closes above open, near the high
6. **Volume Confirmation**: Above 20-period moving average
7. **Strong Momentum**: EMA8 slope is positive and strong (>0.5% over 4 bars)

**Exit**: When price closes below EMA21 or ribbon alignment breaks (8<13 or 13<21)

### **Strategy File Content**

Here's the complete strategy file that needs to be saved to `/root/trade_rules/strategies/ema_ribbon_expansion_eth.py`:

```python
"""
Strategy: ema_ribbon_expansion_eth
===================================
Enter when EMA ribbon (8,13,21,34,55) is aligned and expanding, price pulls back
to EMA21 support, then bounces with volume confirmation. Exit when price breaks
below EMA21 or ribbon alignment breaks.

Symbol: ETH (ETHUSDT) | Exchange: Binance
Performance: 5/6 years profitable | Total: +249.9%

Year-by-year:
  2020: +134.9% | 73% WR | 15 trades
  2021: +23.3% | 42% WR | 12 trades
  2022: +28.1% | 57% WR | 7 trades
  2023: -4.1% | 39% WR | 18 trades
  2024: +25.2% | 38% WR | 16 trades
  2025: +42.5% | 33% WR | 15 trades
"""
import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema, sma


def init_strategy():
    return {
        'name': 'ema_ribbon_expansion_eth',
        'subscriptions': [
            {'symbol': 'ETHUSDT', 'exchange': 'binance', 'timeframe': '4h'},
        ],
        'parameters': {}
    }


def process_time_step(ctx):
    key = ('ETHUSDT', 'binance')
    bars = ctx['bars'].get(key, [])
    i = ctx['i']
    positions = ctx['positions']

    if not bars or i >= len(bars) or i < 100:
        return []

    closes = [b.close for b in bars]
    volumes = [b.volume for b in bars]

    # EMA ribbon: 8, 13, 21, 34, 55
    ema8 = ema(closes, 8)
    ema13 = ema(closes, 13)
    ema21 = ema(closes, 21)
    ema34 = ema(closes, 34)
    ema55 = ema(closes, 55)

    vol_ma = sma(volumes, 20)

    if any(x[i] is None for x in [ema8, ema13, ema21, ema34, ema55]) or vol_ma[i] is None:
        return []

    actions = []
    has_position = key in positions

    if not has_position:
        # 1. Ribbon must be bullishly aligned
        ribbon_aligned = (ema8[i] > ema13[i] > ema21[i] > ema34[i] > ema55[i])

        # 2. Calculate ribbon width (distance between fast and slow EMAs)
        ribbon_width_now = (ema8[i] - ema55[i]) / ema55[i] * 100
        ribbon_width_prev = (ema8[i-3] - ema55[i-3]) / ema55[i-3] * 100

        # 3. Ribbon expanding (momentum accelerating)
        expanding = ribbon_width_now > ribbon_width_prev * 1.1

        # 4. Price was recently near or below EMA21 (pullback entry)
        had_pullback = any(closes[j] <= ema21[j] * 1.01 for j in range(i-3, i))

        # 5. Price now breaks back above EMA13 (momentum resuming)
        price_above_ema13 = closes[i] > ema13[i]
        price_above_ema21 = closes[i] > ema21[i]

        # 6. Bullish candle
        bullish = bars[i].close > bars[i].open

        # 7. Volume confirmation
        volume_strong = volumes[i] > vol_ma[i]

        # 8. Recent momentum: close near high of the candle
        close_near_high = (bars[i].close - bars[i].low) / (bars[i].high - bars[i].low + 0.0001) > 0.6

        # 9. EMA8 rising strongly
        ema8_slope = (ema8[i] - ema8[i-4]) / ema8[i-4] * 100
        strong_slope = ema8_slope > 0.5

        if (ribbon_aligned and expanding and had_pullback and price_above_ema13 and
            price_above_ema21 and bullish and volume_strong and close_near_high and strong_slope):
            actions.append({
                'action': 'open_long',
                'symbol': 'ETHUSDT',
                'exchange': 'binance',
                'size': 1.0,
            })
    else:
        # Exit: Ribbon starts contracting or alignment breaks
        ribbon_aligned = (ema8[i] > ema13[i] > ema21[i])

        # Exit if price falls below EMA21 or ribbon breaks
        below_ema21 = bars[i].close < ema21[i]

        if below_ema21 or not ribbon_aligned:
            actions.append({
                'action': 'close_long',
                'symbol': 'ETHUSDT',
                'exchange': 'binance',
            })

    return actions
```

**Note**: Due to permission issues (directory owned by root, running as scriptrunner), I cannot write directly to `/root/trade_rules/strategies/`. You'll need to manually save this file or adjust the directory permissions to allow writing.

Once the file is in place, you can verify it with:
```bash
python3 manage.py test ema_ribbon_expansion_eth
```

This is a genuinely novel strategy that differs from existing ones by focusing on the dynamic expansion/contraction of an EMA ribbon combined with precise pullback entries at support levels.

---
**Completed:** Sun Jan 11 05:10:06 PM CET 2026