ATR Expansion + Momentum Breakout Volatility expansion often signals the start of strong trending moves. Enters when ATR rises above average (expanding volatility) combined
Symbol: ETH | Exchange: Binance
| Year | Return | Win Rate | Trades | Max DD | Sharpe |
|---|---|---|---|---|---|
| 2020 | +38.8% | 37.5% | 16 | 20.2% | 0.72 |
| 2021 | +10.9% | 75.0% | 4 | 11.5% | 0.63 |
| 2022 | +38.6% | 57.1% | 7 | 4.3% | 1.31 |
| 2023 | +10.7% | 33.3% | 12 | 11.1% | 0.54 |
| 2024 | +60.7% | 80.0% | 5 | 3.6% | 2.23 |
| 2025 | +35.3% | 40.0% | 10 | 7.8% | 1.05 |
See strategy file
See strategy file
"""
Strategy: atr_expansion_momentum_breakout
=========================================
ATR Expansion + Momentum Breakout
Volatility expansion often signals the start of strong trending moves.
Enters when ATR rises above average (expanding volatility) combined
with price breaking above recent highs and a strong bar range.
Performance: 6/6 years profitable | Total: +191.0%
2020: +39.8% | 38% WR | 16 trades
2021: +11.0% | 75% WR | 4 trades
2022: +34.6% | 50% WR | 8 trades
2023: +10.7% | 33% WR | 12 trades
2024: +60.6% | 80% WR | 5 trades
2025: +34.3% | 40% WR | 10 trades
"""
import sys
sys.path.insert(0, "/root/trade_rules")
from lib import atr
def init_strategy():
return {
'name': 'atr_expansion_momentum_breakout',
'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 < 50:
return []
closes = [b.close for b in bars]
highs = [b.high for b in bars]
lows = [b.low for b in bars]
# Calculate ATR
atr_14 = atr(highs, lows, closes, period=14)
# Calculate ATR moving average (30-period)
if i < 43:
return []
valid_atr = [x for x in atr_14[i-29:i+1] if x is not None]
if len(valid_atr) < 25:
return []
atr_sma_30 = sum(valid_atr) / len(valid_atr)
actions = []
has_position = key in positions
if not has_position:
# Entry logic
if atr_14[i] is None:
return []
# 1. Volatility expansion: ATR above 1.3x its 30-bar average
vol_expanding = atr_14[i] > atr_sma_30 * 1.3
# 2. Price momentum: close above 15-bar high
high_15 = max(highs[i-15:i])
momentum = closes[i] > high_15
# 3. Strong bar: current bar range > 1.2x average range
bar_range = bars[i].high - bars[i].low
avg_range = sum(highs[j] - lows[j] for j in range(i-5, i)) / 5
strong_bar = bar_range > avg_range * 1.2
if vol_expanding and momentum and strong_bar:
actions.append({
'action': 'open_long',
'symbol': 'ETHUSDT',
'exchange': 'binance',
'size': 1.0,
})
else:
# Exit logic: price breaks below 8-bar low
low_8 = min(lows[i-8:i])
if closes[i] < low_8:
actions.append({
'action': 'close_long',
'symbol': 'ETHUSDT',
'exchange': 'binance',
})
return actions