← Back to list

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.

Symbol: BTC | Exchange: Bitfinex

4/6
Profitable Years
+241.6%
Total Return
48.8%
Avg Win Rate
0.38
Avg Sharpe

Year-by-Year Results

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

Entry Logic

See strategy file

Exit Logic

See strategy file

Source Code

"""
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