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
| 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 |
See rule file
See rule file
"""
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
"""