Skip to content
Home » Scripts » Simple Pair Trading Strategy

Simple Pair Trading Strategy

Want to learn about the Simple Pair Trading Strategy? It’s a trading method that doesn’t rely on market direction. Instead, it focuses on the relationship between two highly linked stocks or financial instruments. The idea is to profit from their relative price changes, not their individual performance. This strategy banks on the principle of mean reversion, believing that the prices of two linked assets will revert to their historical relationship over time.

Why Choose Pair Trading?

Pair trading is seen as less risky than traditional trading strategies. It’s because it hinges on the link between two assets, not the overall market direction. To use the Simple Pair Trading Strategy, you look for two assets that have always been strongly linked. Then, you monitor their price ratio. If it varies greatly from its historical average, it’s time to trade.

Implementing the Simple Pair Trading Strategy

To put this strategy into action, first, find a pair of assets that have a high correlation. This can be done using statistical analysis or by focusing on assets from the same industry, sector, or market. After finding a suitable pair, keep an eye on the price ratio between the two assets. If the ratio differs from its historical average, go long on the underperforming asset and short on the overperforming asset. The hope is that the price ratio will revert to its mean, resulting in profit.

Remember, the success of the Simple Pair Trading Strategy heavily depends on the chosen assets’ correlation staying stable over time. Also, consider transaction costs and other trading expenses, as these can affect overall profitability.

In the following example, we demonstrate a Simple Pair Trading Strategy with the SPY and QQQ ETFs. The algorithm computes the price ratio between the two assets and compares it to the historical average price ratio. If the current ratio deviates significantly from the historical average, the algorithm takes long and short positions in the underperforming and outperforming assets, respectively. Once the price ratio returns to the historical range, the algorithm closes any open positions.

Click on the code to copy it to your clipboard.
Click here for detailed instructions on how to use the scripts in QuantConnect.

Python
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data.Market import TradeBar

import numpy as np

class SimplePairTradingAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 1, 1)
        self.SetEndDate(2021, 1, 1)
        self.SetCash(100000)
        
        # Define the assets to be traded
        self.asset1 = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.asset2 = self.AddEquity("QQQ", Resolution.Daily).Symbol

        # Set the window size for the price ratio calculation
        self.windowSize = 20
        self.priceRatio = RollingWindow[float](self.windowSize)

        # Set the trading thresholds
        self.upperThreshold = 1.02
        self.lowerThreshold = 0.98

        # Schedule the TradePair function to execute after market open
        self.Schedule.On(self.DateRules.EveryDay(self.asset1), self.TimeRules.AfterMarketOpen(self.asset1, 5), self.TradePair)

    def TradePair(self):
        # Get the current prices of the assets
        asset1Price = self.Securities[self.asset1].Price
        asset2Price = self.Securities[self.asset2].Price

        # Calculate the current price ratio
        currentRatio = asset1Price / asset2Price

        # Add the current price ratio to the rolling window
        self.priceRatio.Add(currentRatio)

        # Check if the rolling window is ready (has enough data)
        if not self.priceRatio.IsReady:
            return

        # Calculate the average price ratio
        averageRatio = np.mean([x for x in self.priceRatio])

        # Execute trades based on the current price ratio compared to the average price ratio and thresholds
        if currentRatio > averageRatio * self.upperThreshold:
            self.SetHoldings(self.asset1, -0.5)  # Short the asset 1
            self.SetHoldings(self.asset2, 0.5)   # Long the asset 2
        elif currentRatio < averageRatio * self.lowerThreshold:
            self.SetHoldings(self.asset1, 0.5)   # Long the asset 1
            self.SetHoldings(self.asset2, -0.5)  # Short the asset 2
        else:
            self.Liquidate(self.asset1)  # Close any open positions for asset 1
            self.Liquidate(self.asset2)  # Close any open positions for asset 2
C#
using System;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Orders;

namespace QuantConnect.Algorithm.CSharp
{
    public class SimplePairTradingAlgorithm : QCAlgorithm
    {
        // Define the assets to be traded
        private Symbol _asset1 = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
        private Symbol _asset2 = QuantConnect.Symbol.Create("QQQ", SecurityType.Equity, Market.USA);

        // Set the window size for the price ratio calculation
        private int _windowSize = 20;
        private RollingWindow<decimal> _priceRatio;

        // Set the trading thresholds
        private decimal _upperThreshold = 1.02m;
        private decimal _lowerThreshold = 0.98m;

        public override void Initialize()
        {
            SetStartDate(2020, 01, 01);
            SetEndDate(2021, 01, 01);
            SetCash(100000);

            // Add the assets to the algorithm
            AddEquity(_asset1.Value, Resolution.Daily);
            AddEquity(_asset2.Value, Resolution.Daily);

            // Initialize the rolling window for the price ratio
            _priceRatio = new RollingWindow<decimal>(_windowSize);

            // Schedule the TradePair function to execute after market open
            Schedule.On(DateRules.EveryDay(_asset1), TimeRules.AfterMarketOpen(_asset1, 5), () =>
            {
                TradePair();
            });
        }

        public void TradePair()
        {
            // Get the current prices of the assets
            decimal asset1Price = Securities[_asset1].Price;
            decimal asset2Price = Securities[_asset2].Price;
            
            // Calculate the current price ratio
            decimal currentRatio = asset1Price / asset2Price;

            // Add the current price ratio to the rolling window
            _priceRatio.Add(currentRatio);

            // Check if the rolling window is ready (has enough data)
            if (!_priceRatio.IsReady) return;

            // Calculate the average price ratio
            decimal averageRatio = _priceRatio.Sum() / _windowSize;

            // Execute trades based on the current price ratio compared to the average price ratio and thresholds
            if (currentRatio > averageRatio * _upperThreshold)
            {
                SetHoldings(_asset1, -0.5); // Short the asset 1
                SetHoldings(_asset2, 0.5);  // Long the asset 2
            }
            else if (currentRatio < averageRatio * _lowerThreshold)
            {
                SetHoldings(_asset1, 0.5);  // Long the asset 1
                SetHoldings(_asset2, -0.5); // Short the asset 2
            }
            else
            {
                Liquidate(_asset1); // Close any open positions for asset 1
                Liquidate(_asset2); // Close any open positions for asset 2
            }
        }
    }
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *