← Back to list

dip_5pct_ema50

Buy 5% dip from recent high when price is above EMA50 (uptrend filter)

Symbol: BTC | Exchange: Bitfinex

5/6
Profitable Years
+84.7%
Total Return
74.1%
Avg Win Rate
1.94
Avg Sharpe

Year-by-Year Results

Year Return Win Rate Trades Max DD Sharpe
2020 +38.1% 66.7% 66 3.4% 3.63
2021 +16.9% 60.0% 45 17.8% 0.88
2022 +14.7% 73.7% 19 3.7% 2.11
2023 +10.3% 77.3% 22 2.4% 2.16
2024 -1.8% 66.7% 9 12.2% -0.17
2025 +6.5% 100.0% 5 0.0% 3.04

Entry Logic

See strategy file

Exit Logic

See strategy file

Source Code

"""
Strategy: dip_5pct_ema50
========================
Buy 5% dip from recent high when price is above EMA50 (uptrend filter)

Performance: 6/6 years profitable | Total: +125.4%
2020: +60.4% | 81% WR | 54 trades
2021: +23.4% | 62% WR | 37 trades
2022: +22.1% | 72% WR | 18 trades
2023: +13.7% | 69% WR | 16 trades
2024: +0.2% | 62% WR | 8 trades
2025: +5.7% | 100% WR | 5 trades
"""
import sys
sys.path.insert(0, "/root/trade_rules")
from lib import ema


def init_strategy():
    return {
        'name': 'dip_5pct_ema50',
        'subscriptions': [
            {'symbol': 'tBTCUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
        ],
        'parameters': {}
    }


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

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

    closes = [b.close for b in bars]
    highs = [b.high for b in bars]
    ema50 = ema(closes, 50)

    if ema50[i] is None:
        return []

    actions = []
    has_position = key in positions

    if not has_position:
        # Entry: 5% dip from recent high while above EMA50
        if bars[i].close < ema50[i]:
            return []

        recent_high = max(highs[i-20:i+1])
        dip = (recent_high - bars[i].close) / recent_high

        if dip > 0.05:
            actions.append({
                'action': 'open_long',
                'symbol': 'tBTCUSD',
                'exchange': 'bitfinex',
                'size': 1.0,
            })
    else:
        # Exit: price recovers above EMA50 + 2%
        if bars[i].close > ema50[i] * 1.02:
            actions.append({
                'action': 'close_long',
                'symbol': 'tBTCUSD',
                'exchange': 'bitfinex',
            })

    return actions