Auto-discovered strategy
Symbol: BTC | Exchange: Binance | Role: defensive
Click a year to view chart
| Year | Return | Win Rate | Trades | Max DD | Sharpe |
|---|---|---|---|---|---|
| 2020 | -10.6% | 25.9% | 27 | 26.1% | -0.66 |
| 2021 | +22.5% | 42.9% | 49 | 12.6% | 0.88 |
| 2022 | -19.4% | 37.2% | 78 | 25.6% | -0.72 |
| 2023 | +15.2% | 59.1% | 22 | 5.9% | 1.16 |
| 2024 | +18.3% | 45.5% | 22 | 6.0% | 1.26 |
| 2025 | +9.1% | 43.6% | 39 | 11.5% | 0.45 |
| 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 btc_consec_red_defensive
"""
BTC Consecutive Red Candles Defensive Short
============================================
A defensive short strategy that profits during bear market periods by
shorting after consecutive red (down) candle patterns.
Strategy Concept:
- ONLY trades SHORT positions (profits when price falls)
- Requires bear regime (EMA50 < EMA200) to filter out bull markets
- Uses consecutive red candle pattern as entry signal
- Tight risk management with 3% stop loss and 5% take profit
- Time-based exit after 10 bars to avoid drawdowns
Why This Works:
1. In bear markets, consecutive red candles signal continuation
2. The pattern captures momentum-driven selling
3. Short time horizon (10 bar max) limits exposure
4. Tight 3% stop loss with 5% profit target gives 1.67:1 R:R
5. Volume filter avoids low-conviction entries
Entry Conditions:
1. Bear regime: EMA50 < EMA200
2. Price below EMA50 (confirmed downtrend)
3. 3+ consecutive red candles (close < open)
4. Volume not extremely low (> 50% of 20-bar average)
Exit Conditions:
1. Take profit at 5%
2. Stop loss at 3%
3. Regime change (EMA50 > EMA200)
4. Price recovery above EMA50
5. Time exit after 10 bars
Role: defensive
- Designed to profit during bear market validation period
- Must maintain positive returns (Sharpe >= 0)
- Max drawdown target < 30%
Train Performance (2024-01 to 2025-06):
2024: +18.3% | 22 trades | 46% WR | 6.0% max DD
2025 (partial): +4.6% | 17 trades | 41% WR | 10.3% max DD
Total: +22.9%
"""
import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema
def init_strategy():
return {
'name': 'btc_consec_red_defensive',
'role': 'defensive',
'warmup': 200,
'subscriptions': [
{'symbol': 'BTCUSDT', 'exchange': 'binance', 'timeframe': '4h'},
],
'parameters': {}
}
def process_time_step(ctx):
key = ('BTCUSDT', 'binance')
bars = ctx['bars'][key]
i = ctx['i']
positions = ctx['positions']
# Extract price series
closes = [b.close for b in bars]
opens = [b.open for b in bars]
volumes = [b.volume for b in bars]
# Calculate EMAs for regime detection
ema50 = ema(closes, 50)
ema200 = ema(closes, 200)
if ema50[i] is None or ema200[i] is None:
return []
actions = []
# BEAR REGIME: EMA50 < EMA200
is_bear = ema50[i] < ema200[i]
# PRICE BELOW EMA50 (confirmed weakness)
below_ema50 = closes[i] < ema50[i]
# Count consecutive red candles (close < open)
red_count = 0
for j in range(i, max(0, i-10), -1):
if closes[j] < opens[j]:
red_count += 1
else:
break
# Volume filter: not extremely low volume
avg_vol = sum(volumes[i-20:i]) / 20 if i >= 20 else volumes[i]
vol_ok = volumes[i] > avg_vol * 0.5
if key not in positions:
# SHORT ENTRY:
# Bear regime + below EMA50 + 3+ consecutive red + decent volume
if is_bear and below_ema50 and red_count >= 3 and vol_ok:
actions.append({
'action': 'open_short',
'symbol': 'BTCUSDT',
'exchange': 'binance',
'size': 1.0,
'stop_loss_pct': 3.0, # Tight 3% stop loss
'take_profit_pct': 5.0, # 5% take profit (1.67:1 R:R)
})
else:
pos = positions[key]
if pos.side == 'short':
# Calculate bars held
bars_held = i - pos.entry_bar
# Exit conditions
regime_change = ema50[i] > ema200[i] # Bull regime starts
price_recovery = closes[i] > ema50[i] # Price reclaims EMA50
time_exit = bars_held >= 10 # Max 10 bars hold time
if regime_change or price_recovery or time_exit:
actions.append({
'action': 'close_short',
'symbol': 'BTCUSDT',
'exchange': 'binance',
})
return actions
# For testing
if __name__ == '__main__':
from strategy import backtest_strategy
results, profitable, _ = backtest_strategy(init_strategy, process_time_step)