← Back to list

tmp0gdxvbwv

Buy after 3 consecutive bullish candles with increasing volume and strong momentum Entry Conditions: - 3 consecutive bullish bars (close > open), each with 0.7%+ body - Each close higher than previou

Symbol: BTC | Exchange: Binance

5/6
Profitable Years
+67.8%
Total Return
71.0%
Avg Win Rate
1.00
Avg Sharpe

Year-by-Year Results

Year Return Win Rate Trades Max DD Sharpe
2020 +38.4% 73.0% 11 10.0% 1.00
2021 -2.7% 33.0% 6 10.0% 1.00
2022 +7.4% 75.0% 4 10.0% 1.00
2023 +20.9% 88.0% 8 10.0% 1.00
2024 +3.3% 57.0% 7 10.0% 1.00
2025 +0.5% 100.0% 2 10.0% 1.00

Entry Logic

See rule file

Exit Logic

See rule file

Source Code

"""
Rule: three_bulls_volume_momentum_btc
======================================
Buy after 3 consecutive bullish candles with increasing volume and strong momentum

Entry Conditions:
- 3 consecutive bullish bars (close > open), each with 0.7%+ body
- Each close higher than previous (rising momentum)
- Price at least 1% above EMA50 (uptrend confirmation)
- Last 2 bars have 1.2x+ average volume (volume confirmation)
- Combined 3-bar gain of 1.8%+ (strong momentum)

Exit Conditions:
- Close below EMA50 (trend break)
- OR first declining close (momentum loss)

Performance: 5/6 years profitable | Total: +67.9% | WR: 70.9%

Year-by-year:
  2020: +38.4% | 73% WR | 11 trades | Sharpe 2.66
  2021:  -2.7% | 33% WR |  6 trades | Sharpe -0.77 ❌
  2022:  +7.4% | 75% WR |  4 trades | Sharpe 3.08
  2023: +20.9% | 88% WR |  8 trades | Sharpe 2.38
  2024:  +3.3% | 57% WR |  7 trades | Sharpe 0.98
  2025:  +0.5% | 100% WR | 2 trades | Sharpe 1.86
"""

def create_rule(bars):
    """Create entry/exit functions for this rule."""
    from sys import path
    path.insert(0, '/root/trade_rules')
    from lib import ema

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

    def entry_long(bars, i):
        if i < 100:
            return False

        if ema50[i] is None:
            return False

        # Price must be at least 1% above EMA50 (uptrend)
        if bars[i].close <= ema50[i] * 1.01:
            return False

        # Last 3 bars must all be bullish (close > open)
        for j in range(i-2, i+1):
            if bars[j].close <= bars[j].open:
                return False

        # Each close must be higher than previous (momentum)
        if not (bars[i-1].close > bars[i-2].close and bars[i].close > bars[i-1].close):
            return False

        # Each candle must have good body (at least 0.7%)
        for j in range(i-2, i+1):
            body_pct = (bars[j].close - bars[j].open) / bars[j].open
            if body_pct < 0.007:
                return False

        # Volume confirmation: last 2 bars above average
        avg_volume = sum(bars[j].volume for j in range(i-20, i-3)) / 17
        if bars[i-1].volume <= avg_volume * 1.2 or bars[i].volume <= avg_volume * 1.2:
            return False

        # Combined 3-bar momentum must be strong (1.8%+)
        momentum = (bars[i].close - bars[i-2].open) / bars[i-2].open
        if momentum < 0.018:
            return False

        return True

    def exit_long(bars, i):
        if i < 1:
            return False

        if ema50[i] is None:
            return False

        # Exit if price closes below EMA50 (trend break)
        if bars[i].close < ema50[i]:
            return True

        # Exit on first declining close (momentum loss)
        if bars[i].close < bars[i-1].close:
            return True

        return False

    return {
        'entry_long': entry_long,
        'exit_long': exit_long,
        'symbol': 'BTCUSDT',
        'exchange': 'binance',
    }


ENTRY_LOGIC = """
if price > EMA50 * 1.01:
    # Check last 3 bars
    bar1 = bars[i-2]
    bar2 = bars[i-1]
    bar3 = bars[i]

    # All 3 bars must be bullish with 0.7%+ body
    if all bars are bullish (close > open) AND each body > 0.7%:
        # Rising momentum
        if bar2.close > bar1.close AND bar3.close > bar2.close:
            # Volume confirmation
            avg_vol = average of bars[i-20 to i-3]
            if bar2.volume > avg_vol * 1.2 AND bar3.volume > avg_vol * 1.2:
                # Strong 3-bar momentum
                momentum = (bar3.close - bar1.open) / bar1.open
                if momentum > 1.8%:
                    BUY
"""

EXIT_LOGIC = """
if price < EMA50:
    SELL
OR
if bars[i].close < bars[i-1].close:
    SELL
"""