BTC/ETH Momentum Pair Trading A pair trading strategy that trades BTC vs ETH based on relative momentum. When BTC outperforms ETH (rising ratio), go long BTC / short ETH.
Symbol: BTC | Exchange: Bitfinex
| Year | Return | Win Rate | Trades | Max DD | Sharpe |
|---|---|---|---|---|---|
| 2020 | +96.6% | 50.0% | 140 | 41.9% | 0.90 |
| 2021 | +127.1% | 50.8% | 132 | 29.9% | 1.11 |
| 2022 | -11.5% | 46.7% | 150 | 59.1% | -0.12 |
| 2023 | +3.1% | 46.7% | 120 | 22.8% | 0.05 |
| 2024 | +32.7% | 48.4% | 122 | 44.2% | 0.44 |
| 2025 | -6.4% | 50.0% | 144 | 49.5% | -0.09 |
See strategy file
See strategy file
"""
Strategy: btc_eth_momentum_pair
==============================
BTC/ETH Momentum Pair Trading
A pair trading strategy that trades BTC vs ETH based on relative momentum.
When BTC outperforms ETH (rising ratio), go long BTC / short ETH.
When ETH outperforms BTC (falling ratio), go short BTC / long ETH.
Entry Conditions:
- Fast MA of BTC/ETH ratio crosses above Slow MA AND ratio above trend filter: Long BTC/Short ETH
- Fast MA of BTC/ETH ratio crosses below Slow MA AND ratio below trend filter: Short BTC/Long ETH
Exit Conditions:
- Fast MA crosses back (reversal)
Performance: 4/6 years profitable | Total: +241.6%
2020: +96.6% | 50% WR | 140 trades
2021: +127.1% | 51% WR | 132 trades
2022: -11.5% | 47% WR | 150 trades
2023: +3.1% | 47% WR | 120 trades
2024: +32.7% | 48% WR | 122 trades
2025: -6.4% | 50% WR | 144 trades
"""
import sys
sys.path.insert(0, "/root/trade_rules")
def init_strategy():
return {
'name': 'btc_eth_momentum_pair',
'subscriptions': [
{'symbol': 'tBTCUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
{'symbol': 'tETHUSD', 'exchange': 'bitfinex', 'timeframe': '4h'},
],
'parameters': {
'fast_ma': 10,
'slow_ma': 30,
'trend_filter': 50,
}
}
def process_time_step(ctx):
btc_key = ('tBTCUSD', 'bitfinex')
eth_key = ('tETHUSD', 'bitfinex')
btc_bars = ctx['bars'].get(btc_key, [])
eth_bars = ctx['bars'].get(eth_key, [])
i = ctx['i']
positions = ctx['positions']
params = ctx['parameters']
slow_ma = params['slow_ma']
fast_ma = params['fast_ma']
trend_filter = params['trend_filter']
if not btc_bars or not eth_bars or i < trend_filter + 5:
return []
# Calculate BTC/ETH ratio moving averages
def get_ratio_ma(period, offset=0):
ratios = [btc_bars[j].close / eth_bars[j].close
for j in range(i - offset - period, i - offset)]
return sum(ratios) / len(ratios)
current_ratio = btc_bars[i].close / eth_bars[i].close
fast_ratio_ma = get_ratio_ma(fast_ma)
slow_ratio_ma = get_ratio_ma(slow_ma)
trend_ratio_ma = get_ratio_ma(trend_filter)
actions = []
has_btc = btc_key in positions
has_eth = eth_key in positions
if not has_btc and not has_eth:
# Entry signals
if fast_ratio_ma > slow_ratio_ma and current_ratio > trend_ratio_ma:
# BTC outperforming - long BTC, short ETH
actions.append({
'action': 'open_long',
'symbol': 'tBTCUSD',
'exchange': 'bitfinex',
'size': 1.0,
})
actions.append({
'action': 'open_short',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
'size': 1.0,
})
elif fast_ratio_ma < slow_ratio_ma and current_ratio < trend_ratio_ma:
# ETH outperforming - short BTC, long ETH
actions.append({
'action': 'open_short',
'symbol': 'tBTCUSD',
'exchange': 'bitfinex',
'size': 1.0,
})
actions.append({
'action': 'open_long',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
'size': 1.0,
})
elif has_btc and has_eth:
# Exit signals: momentum reversal
btc_pos = positions[btc_key]
eth_pos = positions[eth_key]
should_exit = False
if btc_pos.side == 'long' and fast_ratio_ma < slow_ratio_ma:
should_exit = True
elif btc_pos.side == 'short' and fast_ratio_ma > slow_ratio_ma:
should_exit = True
if should_exit:
if btc_pos.side == 'long':
actions.append({
'action': 'close_long',
'symbol': 'tBTCUSD',
'exchange': 'bitfinex',
})
else:
actions.append({
'action': 'close_short',
'symbol': 'tBTCUSD',
'exchange': 'bitfinex',
})
if eth_pos.side == 'long':
actions.append({
'action': 'close_long',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
})
else:
actions.append({
'action': 'close_short',
'symbol': 'tETHUSD',
'exchange': 'bitfinex',
})
return actions