Pairs trading algorithm development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Pairs trading algorithm development
Complex
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1170
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1092
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    830
  • image_logo-aider_0.jpg
    AIDER company logo development
    763
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    879

Pairs Trading Algorithm Development

Pairs trading is a special case of statistical arbitrage: we trade one pair of assets, opening simultaneously a long position in one and short in the other. The strategy is market-neutral: profit doesn't depend on overall market direction, only on spread narrowing/widening between two assets.

Pair Selection

Not all pairs are suitable for trading. Requirements:

Cointegration — statistically significant (p-value < 0.05 by Engle-Granger or Johansen test). Rebalance and check every 2–4 weeks: cointegration may disappear.

Economic sense — pair must have fundamental connection:

  • BTC spot vs BTC perpetual futures
  • ETH vs stETH (Lido staked ETH)
  • Binance Coin (BNB) vs similar exchange tokens
  • Competing Layer-1: SOL vs AVAX, DOT vs ATOM
  • DeFi token basket (UNI, AAVE, CRV) against DeFi index

Liquidity: both assets must have sufficient volume for execution without significant slippage.

Half-life: period of mean reversion. 3–30 days — acceptable range. Too short — won't have time to enter, too long — capital frozen too long.

Trade Mechanics

Example: BTC/USDT spot and BTCUSDT perpetual futures

Spread = BTC_PERP - BTC_SPOT
Basis = PERP_price - SPOT_price  (usually positive due to funding)

If basis abnormally high (Z-score > 2): sell PERP, buy SPOT. Wait for narrowing. Profit = basis change.

Position sizes: for market neutrality, value of both positions should be equal (or weighted by hedge ratio β).

def calculate_position_sizes(capital, hedge_ratio, price_x, price_y):
    # Dollar-neutral
    position_value = capital / 2
    qty_y = position_value / price_y   # sell Y
    qty_x = qty_y * hedge_ratio        # buy X
    return qty_x, qty_y

Dynamic Hedge Ratio

Fixed hedge ratio becomes outdated. Use rolling window OLS or Kalman Filter for continuous updating.

Important: sharp change in hedge ratio may signal structural shift in relationships between assets. Monitor β stability.

Pairs Trading Risks

Divergence risk: spread continues widening instead of narrowing. Fundamental reason: one asset changes structurally (delisting, hack, regulatory action). Stop-loss at Z-score = 3 or 4.

Funding risk: for perpetual positions, funding rate may eat profits. Especially when high positive funding on PERP (you pay as PERP short holder).

Liquidity risk: unexpected market move may make simultaneous closing of both legs difficult.

Correlation breakdown: especially relevant in crypto — during market-wide moves (BTC dump/pump) correlations break.

P&L Calculation and Backtesting

def backtest_pairs(spread, z_scores, entry_z=2.0, exit_z=0.5, stop_z=3.5):
    position = 0  # 1 = long spread, -1 = short spread
    pnl = []
    
    for i, (spread_val, z) in enumerate(zip(spread, z_scores)):
        if position == 0:
            if z > entry_z:
                position = -1  # short spread
                entry_spread = spread_val
            elif z < -entry_z:
                position = 1   # long spread
                entry_spread = spread_val
        elif position == 1:
            current_pnl = spread_val - entry_spread
            if z > -exit_z or z < -stop_z:
                pnl.append(current_pnl)
                position = 0
        elif position == -1:
            current_pnl = entry_spread - spread_val
            if z < exit_z or z > stop_z:
                pnl.append(current_pnl)
                position = 0
    
    return pnl

Monitoring Active Positions

Every N minutes recalculate Z-score and hedge ratio. Dashboard shows:

  • Current Z-score and its history
  • P&L of current position
  • Unrealized PnL per leg
  • Funding payments (for perpetual)
  • Time in position vs expected half-life

Alert when approaching stop-loss level or on sharp hedge ratio change (>20% from previous value).

Stack: Python (statsmodels, numpy, pykalman), CCXT for order execution, PostgreSQL for trade history, Grafana for monitoring. Algorithm runs as daemon process with configurable parameters via config file or UI.