top of page

Pairs Trading Strategy

Pairs trading is a statistical arbitrage strategy used by quantitative traders to exploit temporary price divergences between two related assets. In this project, we'll implement a pairs trading strategy specifically tailored for the Indian stock market.

Methodology:

  1. Data Collection

  2. Pair Selection & Spread Calculation

  3. Spread Z-score Calculation

  4. Trading Signal Generation

  5. Trade Execution & Risk Management

pair trading1112.jpeg

Project Duration

18.02.24 - 25.02.24
One Week

Industry

Finance & Stock Market

My Role

Quantitative Trader
Python Programmer
Data Analyst

Deliverables

Executable Scripts to collect financial data and analyse to make trade with proper risk management

frame_edited.png

Methodology

​

  • Data Collection: Obtain historical price data for a pair of stocks from the NSE using the yfinance library.

​

  • Pair Selection: Identify a suitable pair of stocks exhibiting cointegration, a prerequisite for pairs trading. This can be done using statistical tests such as the Augmented Dickey-Fuller (ADF) test.

​

  • Spread Calculation: Calculate the spread between the prices of the two stocks in the pair. This can be done by taking the difference between their prices or using more sophisticated methods like the Kalman Filter.

​

  • Spread Z-score Calculation: Compute the z-score of the spread to standardize it and identify deviations from its mean.

​

  • Trading Signal Generation: Generate trading signals based on the z-score exceeding predefined thresholds, indicating potential entry or exit points.

​

  • Trade Execution: Execute trades when the trading signals are triggered, taking into account considerations such as transaction costs and position sizing.

​

  • Risk Management: Implement risk management measures to limit losses and manage portfolio exposure.

​

​

Code Implementation

​

Step 1: Data Collection
​

Python code:

​

import yfinance as yf

# Define stock symbols and date range
symbol1 = 'RELIANCE.NS'
symbol2 = '
TCS.NS'
start_date = '
2023-01-01'
end_date = '
2024-01-01'

# Fetch historical price data from Yahoo Finance
data1 = yf.download(symbol1, start=start_date, end=end_date)
data2 = yf.download(symbol2, start=
start_date, end=end_date)

 

Explanation:

  • This section imports the yfinance library, which is a Python package for fetching historical market data from Yahoo Finance.

  • You specify the symbols of two stocks (RELIANCE.NS for Reliance Industries and TCS.NS for Tata Consultancy Services) and the date range for which you want historical data.

  • The yf.download() function is used to fetch historical price data for each stock within the specified date range and store it in data1 and data2.

​

Step 2: Pair Selection & Spread Calculation

​

Python code:

​

# Check for cointegration using ADF test
from statsmodels.tsa.stattools import adfuller

def test_cointegration(series1, series2):
    result = adfuller(series1 - series2)
    p_value = result[1]
    return p_value <
0.05

# Assuming 'Close' prices are used
stock1_close = data1['Close']
stock2_close = data2['Close']

# Check for cointegration
is_cointegrated = test_cointegration(stock1_close, stock2_close)
if is_cointegrated:
   
spread = stock1_close - stock2_close
 
  # Calculate spread mean and standard deviation for z-score calculation
    spread_mean = spread.mean()
   
spread_std = spread.std()
else:
    print("
Selected pair is not cointegrated. Choose another pair.")

 

Explanation:

  • In this step, we define a function test_cointegration() to check for cointegration between the two stock price series using the Augmented Dickey-Fuller (ADF) test.

  • We extract the 'Close' price data for both stocks from the fetched historical data.

  • The test_cointegration() function is then used to check if the pair of stocks is cointegrated (i.e., if there is a long-term relationship between their prices).

  • If the pair is cointegrated, we calculate the spread between the prices of the two stocks (spread) and compute the mean and standard deviation of the spread for later use in z-score calculation.

​

Step 3: Spread Z-score Calculation

​

Python code:

​

# Calculate z-score of spread
spread_z_score = (spread - spread_mean) / spre
ad_std

 

Explanation:

  • We calculate the z-score of the spread between the two stock prices. The z-score measures how many standard deviations the spread is from its mean.

  • This standardized measure helps identify deviations of the spread from its historical average, which are used to generate trading signals.

​

Step 4: Trading Signal Generation

​

Python code:

​

# Define entry and exit thresholds for trading signals
entry_threshold = 2.0
exit_threshold = 0.0

# Generate trading signals
long_signal = spread_z_score < -entry_threshold
short_signal = spread_z_score > entry_threshold
exit_signal = abs(spread_z_score) < exit_threshold

 

Explanation:

  • We define entry and exit thresholds for generating trading signals. These thresholds determine when to enter long or short positions and when to exit the positions.

  • Trading signals are generated based on whether the z-score of the spread falls below the entry threshold (indicating a long position), above the entry threshold (indicating a short position), or within the exit threshold (indicating an exit signal).

​

Step 5: Trade Execution & Risk Management

​

Python code:

​

# Assuming 'long_signal', 'short_signal', 'exit_signal', 'data_A', 'data_B', 'spread', and 'spread_zscore' are defined

# Initial capital
initial_capital = 1000000  # $1,000,000

# Position sizing
position_size = initial_capital * 0.1  # 10% of initial capital per trade

# Initialize portfolio positions
portfolio_A = 0
portfolio_B = 0

# Loop through each trading day
for i in range(len(data_A)):
   
# Check if long signal is triggered
    if long_signal[i]:
       
# Calculate number of shares to buy of stock A and short of stock B
        shares_to_buy_A = position_size / data_A[i]
       
shares_to_short_B = position_size / data_B[i]
        
       
# Update portfolio positions
        portfolio_A += shares_to_buy_A
        portfolio_B -= shares_to_short_B
    
   
# Check if short signal is triggered
    elif short_signal[i]:
       
# Calculate number of shares to short of stock A and buy of stock B
        shares_to_short_A = position_size / data_A[i]
        shares_to_buy_B = position_size / data_B[i]
        
       
# Update portfolio positions
        portfolio_A -= shares_to_short_A
        portfolio_B += shares_to_buy_B
    
   
# Check if exit signal is triggered
    elif exit_signal[i]:
       
# Close all positions
        portfolio_A = 0
        portfolio_B = 0

# Calculate final portfolio value
final_portfolio_value = portfolio_A * data_A[-1] + portfolio_B * data_B[-1]

# Print final portfolio value
print("Final Portfolio Value: $", final_portfolio_value)
 

Explanation:

  • This code snippet can be used to execute trades and manage risk based on trading signals (long, short, exit) generated by your pairs trading strategy.

  • It assumes that you have already defined the trading signals (long_signal, short_signal, exit_signal) based on your strategy's criteria and have historical price data for the two stocks (data_A, data_B) in your pair.

​

Results:

  • Backtested the pairs trading strategy using historical data to evaluate its performance in terms of profitability, risk-adjusted returns, and other relevant metrics.

  • Analyzed the sensitivity of the strategy to different parameter values and market conditions.

​

Conclusion:

Implementing a pairs trading strategy for the Indian stock market can be a profitable endeavor, provided proper research, testing, and risk management are employed. By leveraging statistical arbitrage techniques, traders can exploit mispricings and inefficiencies in the market, potentially generating consistent returns over time.

More Info
Volatility In

© 2024 Designed & Created by Saurabh Patil 

bottom of page