
Statistical Arbitrage Strategy
I develop a Statistical Arbitrage Strategy to identify and exploit mispricings in financial markets using statistical techniques. Statistical arbitrage involves simultaneously buying and selling related securities to profit from temporary price discrepancies.
Methodology:
The Statistical Arbitrage Strategy developed for the Indian stock market aims to capitalize on short-term mispricings between stocks listed on the Bombay Stock Exchange (BSE) and the National Stock Exchange (NSE). By identifying pairs of stocks with historically correlated prices, this strategy seeks to generate profits by exploiting temporary divergences in their prices.

Project Duration
26.02.24 - 03.03.24
One Week
Industry
Finance & Stock Market
My Role
Quantitative Trader
Python Programmer
Data Analyst
Deliverables
Executable Scripts for Statistical Arbitrage Strategy to identify and exploit mispricings in financial markets

Methodology
​
-
Data Collection: Collect historical price data for stocks listed on the BSE and NSE from reliable sources. Include a variety of stocks to ensure diversity and market representation.
​
-
Pair Selection & Spread Calculation: Use statistical techniques such as cointegration or correlation analysis to identify pairs of stocks with historically correlated prices. Calculate the spread between the prices of each pair to represent deviations from the expected relationship.
​
-
Z-score Calculation: Compute the z-score of the spread to standardize and assess deviations from historical norms. Generate trading signals based on the z-score to determine entry and exit points for trades.
​
-
Trade Execution & Risk Management: Execute trades based on the generated trading signals, taking long and short positions in the pairs according to the strategy's rules. Implement risk management techniques such as position sizing, stop-loss orders, and portfolio diversification to manage potential losses.
​
​
Code Implementation
​
Python code:
​
import pandas as pd
import numpy as np
import yfinance as yf
​
# Step 1: Data Collection
# Collect historical price data for selected stocks from BSE and NSE
def fetch_stock_data(symbol, start_date, end_date):
stock_data = yf.download(symbol, start=start_date, end=end_date)
return stock_data['Adj Close']
stock_symbols = ['RELIANCE.BO', 'INFY.BO', 'HDFCBANK.BO', 'ICICIBANK.BO', 'TCS.BO', 'RELIANCE.NS', 'INFY.NS', 'HDFCBANK.NS', 'ICICIBANK.NS', 'TCS.NS']
# NSE & BSE stocks
start_date = '2023-01-01'
end_date = '2023-12-31'
stock_prices = {}
for symbol in stock_symbols:
stock_prices[symbol] = fetch_stock_data(symbol, start_date, end_date)
​
# Step 2: Pair Selection & Spread Calculation
# Select pairs of stocks and calculate spread
pairs = [('RELIANCE.BO', 'RELIANCE.NS'), ('INFY.BO', 'INFY.NS'), ('HDFCBANK.BO', 'HDFCBANK.NS'),
('ICICIBANK.BO', 'ICICIBANK.NS'), ('TCS.BO', 'TCS.NS')]
spread_data = {}
for pair in pairs:
stock_A, stock_B = pair
spread_data[pair] = stock_prices[stock_A] - stock_prices[stock_B]
​
# Step 3: Z-score Calculation
# Calculate z-score of the spread
zscore_data = {}
for pair, spread in spread_data.items():
zscore_data[pair] = (spread - np.mean(spread)) / np.std(spread)
​
# Step 4: Trade Execution & Risk Management
# Execute trades based on z-score
def execute_trades(zscore_data, threshold=1.0):
trades = {}
for pair, zscore in zscore_data.items():
if zscore > threshold:
trades[pair] = 'Short ' + pair[0] + ' Long ' + pair[1]
elif zscore < -threshold:
trades[pair] = 'Long ' + pair[0] + ' Short ' + pair[1]
else:
trades[pair] = 'No Trade'
return trades
# Example trade execution with z-score threshold of 1.0
trades = execute_trades(zscore_data, threshold=1.0)
for pair, trade in trades.items():
print(pair, ':', trade)
Explanation:
​
Step 1: Data Collection
-
The fetch_stock_data function uses the yfinance library to download historical price data for selected stocks from both the Bombay Stock Exchange (BSE) and the National Stock Exchange (NSE).
-
Historical price data is collected for a specified time period (start_date to end_date) for each selected stock symbol.
​
Step 2: Pair Selection & Spread Calculation
-
Pairs of stocks are predefined, with each pair consisting of one stock listed on the BSE and the corresponding stock listed on the NSE.
-
For each pair, the difference in the adjusted closing prices between the two stocks is calculated to determine the spread. This spread represents the deviation from the expected relationship between the prices of the two stocks.
​
Step 3: Z-score Calculation
-
For each pair, the z-score of the spread is calculated. The z-score standardizes the spread by subtracting the mean spread and dividing by the standard deviation of the spread.
-
The z-score indicates how many standard deviations the spread is from the mean spread, providing a measure of how much the current spread deviates from historical norms.
​
Step 4: Trade Execution & Risk Management
-
Trades are executed based on the z-score calculated for each pair. If the z-score exceeds a predefined threshold (1.0 in this example), a trade is initiated.
-
If the z-score is above the threshold, indicating that the spread is higher than usual, a short position is taken in the stock listed on the BSE and a long position is taken in the corresponding stock listed on the NSE. Conversely, if the z-score is below the negative threshold, indicating that the spread is lower than usual, a long position is taken in the BSE stock and a short position is taken in the NSE stock.
-
If the z-score is within the threshold, no trade is executed.
-
This basic risk management approach helps control the exposure to market risk by limiting trading activity to situations where the spread deviates significantly from historical norms.
​
Results:
-
The code prints the trades executed for each pair based on the z-score threshold. Each trade specifies whether to take a long position in the BSE stock and a short position in the NSE stock, or vice versa, or to take no trade if the z-score is within the threshold.
​
Conclusion:
The Statistical Arbitrage Strategy for the Indian stock market (BSE and NSE) offers a systematic approach to exploit short-term mispricings between stocks, leveraging statistical analysis and algorithmic trading techniques. This project demonstrates proficiency in quantitative trading strategies and provides valuable insights into market dynamics and trading opportunities in the Indian financial landscape.
