Cointegration and pairs trading on the NSE

The short answer

Correlation is not cointegration, and pairs trading needs the second. Correlation measures whether two returns move together and can stay high while two price series drift apart forever. Cointegration is stronger: a specific linear combination of two non-stationary prices is itself stationary, so the spread has a fixed mean it keeps reverting to, a long-run equilibrium. A pairs trade is only sound when the spread is stationary. You test that with the Engle-Granger two-step, trade the standardised spread with a z-score, and size the horizon by the half-life of reversion.

Statistical arbitrage sells itself on a clean idea: find two stocks that belong together, trade the gap when it opens, and collect as it closes, indifferent to whether the market rises or falls. The idea is sound. The way most retail treats it is not, because it starts from correlation, and correlation is the wrong instrument. This guide sets out the distinction that decides everything, the tests that separate a tradeable spread from a coincidence, the mechanics of the trade itself, and the NSE-specific frictions and the one risk that ends these strategies: the relationship breaking.

Correlation is not cointegration

Correlation is a statement about returns. It asks whether, day to day, two series tend to move up and down together, and it is scale-free and short-memoried. Two stocks can post a correlation of returns near one and still see the gap between their price levels widen without limit, because nothing in the correlation coefficient constrains the levels. A stock compounding faster than another can march away from it while every daily wiggle stays synchronised. Correlation is high; the spread is a runaway.

Cointegration is a statement about levels. Two price series are each non-stationary: a random-walk-like series with no fixed mean, wandering wherever the last shock left it. Cointegration says that although each series wanders, there exists a fixed combination of them, price of A minus a constant times price of B, that does not wander. That combination, the spread, is stationary: it has a constant mean and variance and it reverts. The two prices are tied by an invisible spring. That spring, and only that spring, is what a pairs trade harvests.

Figure 1 Cointegration versus correlation Left panel: a cointegrated pair, where two non-stationary prices wander but remain tethered and the spread is stationary around a flat mean. Right panel: a merely correlated pair, where both prices rise together yet the spread drifts open without reverting, so it is not tradeable as a mean-reverting spread. Same-looking chart, opposite verdict COINTEGRATED · spread reverts Stock A Stock B mean Spread: stationary CORRELATED ONLY · spread drifts Stock A Stock B mean Spread: drifts open, no reversion Illustrative sketch. Correlation looks at the returns on top; cointegration looks at the spread below.
The verdict lives in the spread, not the price lines. Both panels show two lines rising and wiggling together, the picture correlation rewards. Only the left pair is cointegrated: its spread oscillates around a flat mean and reverts. The right pair is merely correlated: the spread drifts steadily open and never comes back, so there is nothing for a pairs trade to harvest, however tight the return correlation looks.
Why this is the scoop. The single most common statistical-arbitrage error is screening candidate pairs by the correlation of their returns. A high correlation is neither necessary nor sufficient for a stationary spread. Pairs can be strongly correlated and never cointegrated, and, less often, weakly correlated yet cointegrated. The test that matters is a stationarity test on the spread, not a correlation matrix. Getting that upstream judgement right is exactly what the method we teach is built around.
Table 1. Correlation and cointegration compared
PropertyCorrelationCointegration
What it measuresCo-movement of returns over a windowWhether a linear combination of price levels is stationary
Operates onReturns (differences)Price levels (non-stationary series)
MemoryShort: a rolling statisticLong-run: a persistent equilibrium relationship
Constrains the spread?No, the gap can drift without limitYes, the spread reverts to a mean
Tested withCorrelation coefficientEngle-Granger two-step, or Johansen for baskets
Tradeable as a mean-reverting spread?Not on its ownYes, if the spread stays stationary

Testing for cointegration: the Engle-Granger two-step

For a single pair, the workhorse is the Engle-Granger two-step procedure, introduced by Robert Engle and Clive Granger in 1987. Step one estimates the long-run relationship by ordinary least squares, regressing the price of one stock on the other. The slope is the hedge ratio, the number of units of B that offset one unit of A, and the regression residual is the spread. Step two tests that residual for stationarity with an Augmented Dickey-Fuller (ADF) test, whose null hypothesis is that the residual has a unit root, meaning it is non-stationary. Reject the null and the spread is stationary: the pair is cointegrated.

import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller, coint

# a and b are pandas Series of daily closing prices for two same-sector large-caps,
# aligned on a common trading calendar. Supply your own historical data.
prices = pd.concat([a, b], axis=1).dropna()
a, b = prices.iloc[:, 0], prices.iloc[:, 1]

# STEP 1  ---  OLS: regress price A on price B to get the hedge ratio and spread
X = sm.add_constant(b)                 # intercept + slope
ols = sm.OLS(a, X).fit()
hedge_ratio = ols.params.iloc[1]       # units of B per 1 unit of A
spread = a - hedge_ratio * b - ols.params.iloc[0]   # the regression residual

# STEP 2  ---  ADF test on the spread: is the residual stationary?
adf_stat, adf_p, *_ = adfuller(spread, autolag="AIC")
print(f"hedge ratio = {hedge_ratio:.3f}")
print(f"ADF p-value on spread = {adf_p:.4f}")   # small p-value => reject unit root => stationary

There is a subtlety worth stating plainly, because it is the kind of detail generic articles miss. Running adfuller on a residual you obtained from your own regression does not use the right critical values. The residual was chosen to look as stationary as possible, so the standard ADF distribution is too lenient. The correct test uses Engle-Granger critical values (MacKinnon's), which statsmodels provides directly through coint. Prefer it for the verdict, and keep the manual two-step for the hedge ratio and the spread series:

# Correct Engle-Granger test in one call (uses the proper critical values)
eg_stat, eg_p, eg_crit = coint(a, b)
print(f"Engle-Granger p-value = {eg_p:.4f}")   # NOT the same as the naive adfuller p-value
# A common decision rule: treat the pair as cointegrated only if eg_p < 0.05.

The order matters too. Because the regression is not symmetric, regressing A on B and B on A gives slightly different hedge ratios and residuals, so the verdict can wobble near the threshold depending on which series you place on the left. That asymmetry is one reason the multivariate test below exists.

The Johansen test, for baskets

When you want cointegration among three or more series at once, say a basket of same-sector names, the Engle-Granger two-step no longer fits cleanly, because it hinges on an arbitrary choice of dependent variable and can only find one relationship. The Johansen test handles the general case. It estimates the cointegration rank, how many independent stationary combinations exist among the series, using a trace statistic and a maximum-eigenvalue statistic, and it returns the cointegrating vectors directly rather than assuming one.

from statsmodels.tsa.vector_ar.vecm import coint_johansen

# basket: a DataFrame whose columns are price levels of the candidate names
result = coint_johansen(basket, det_order=0, k_ar_diff=1)
# compare each trace statistic against its 90/95/99% critical value
for i, (trace, crit) in enumerate(zip(result.lr1, result.cvt)):
    print(f"rank <= {i}:  trace = {trace:.2f}   95% crit = {crit[1]:.2f}")
# the first i where trace < the 95% critical value estimates the cointegration rank

For a two-stock pair, Engle-Granger is simpler and usually enough. Johansen earns its keep on baskets and when you need the relationship itself, not just a yes or no.

The trade: spread, z-score, and thresholds

A cointegration verdict gives you a stationary spread. The trade standardises it. Subtract a rolling mean and divide by a rolling standard deviation to get a z-score, a spread expressed in units of its own deviation, oscillating around zero. A z-score of +2 says the spread sits two deviations above its recent normal: unusually wide. The rule then trades the extremes back toward the middle. When the z-score stretches past a positive threshold, the spread is rich, so you short the spread, selling the leg that has run up and buying the leg that has lagged, in the hedge ratio. When it stretches past the negative threshold you do the mirror. You exit as the z-score reverts toward zero.

Figure 2 The z-score trade mechanic The standardised spread oscillates around zero. Entry bands sit at plus and minus two deviations and an exit band sits near zero. Crossing above plus two triggers a short of the rich leg and a long of the cheap leg; crossing below minus two triggers the mirror; the trade is exited as the z-score reverts toward zero. Trade the spread, standardised 0 +2 −2 exit band (|z| near 0) z > +2: short rich leg, long cheap leg z < −2: the mirror trade revert to 0: exit time → Illustrative. The bands at ±2 and the exit near 0 are choices, not fixed rules; they are set and tested, not assumed.
Enter on the stretch, exit on the reversion. The z-score turns an abstract spread into a bounded oscillator. Crossing an outer band is the entry signal, short the rich leg and long the cheap leg in the hedge ratio; the return toward zero is the exit. Wider bands trade less often but with a cleaner edge per trade; tighter bands trade more but bleed to costs. The thresholds are parameters you set and test, which is where overfitting creeps in.

The half-life of mean reversion

A stationary spread is not enough; you need to know how fast it reverts, because that sets your holding period and decides whether the edge survives costs. Model the spread as an Ornstein-Uhlenbeck process, the continuous-time analogue of a first-order autoregression. Its speed is captured by fitting an AR(1): regress the daily change in the spread on the lagged level of the spread. The slope, call it lambda, is negative for a mean-reverting series, and the half-life, the expected time to close half the distance to the mean, is minus the natural logarithm of two divided by lambda.

# Ornstein-Uhlenbeck / AR(1) half-life of the spread
lag = spread.shift(1)
delta = (spread - lag).dropna()
lag = lag.loc[delta.index]

reg = sm.OLS(delta, sm.add_constant(lag)).fit()
lam = reg.params.iloc[1]                 # slope on the lagged level; negative if mean-reverting
half_life = -np.log(2) / lam
print(f"lambda = {lam:.4f}   half-life = {half_life:.1f} periods")

Read the number with judgement. A very short half-life, a day or two, usually means you are fitting microstructure noise rather than a real equilibrium, and costs will dominate. A very long half-life ties capital up for months against a small per-trade edge, and gives a slow-moving relationship more time to break. There is no universal sweet spot to quote, and quoting one would be false precision; the point is that the half-life, the threshold, the transaction and borrow costs, and the capital tied up have to be weighed together before a spread is worth trading. The arithmetic below is illustrative, with round numbers chosen only to show the shape of the trade, not a claim about any real pair.

Table 2. The pairs-trade workflow, step by step (illustrative figures)
StepMethodOutput (illustrative)
1. Pick candidatesSame sector, shared economic drivers; screen on economic logic, not correlation aloneTwo same-sector large-caps, call them A and B
2. Estimate the relationshipOLS of price A on price BHedge ratio ≈ 1.40; spread = A − 1.40×B − c
3. Test the spreadEngle-Granger via coint, decision rule p < 0.05p below 0.05: treat as cointegrated
4. Measure reversion speedAR(1) half-life on the spreadHalf-life around 20 periods (illustrative)
5. StandardiseRolling z-score of the spreadz oscillating around 0
6. Enter|z| beyond about 2Short the rich leg, long the cheap leg
7. Exitz reverts toward 0, or a hard stop on divergenceClose both legs together

NSE specifics: the short leg and its frictions

A pairs trade is market-neutral only because it is long one leg and short the other. The short leg is where Indian-market reality bites. Regulation prohibits naked short selling: you cannot sell stock for delivery that you have not arranged to deliver. To hold a genuine cash-segment short you must borrow the stock through the Securities Lending and Borrowing (SLB) framework, an exchange-run, clearing-corporation-secured mechanism under the SEBI short-selling rules. Borrow is not free and not always available: the lending pool for a given name can be thin, the fee varies, and a hard-to-borrow stock can make one leg of an otherwise valid pair impractical.

For this reason many pairs are constructed in the derivatives segment, taking the short leg in single-stock futures where the name is available there, which sidesteps the stock-borrow step but introduces its own frictions: fixed lot sizes that will not match your computed hedge ratio exactly, so you round and accept a small residual imbalance; the roll from one expiry to the next; and, for positions carried into expiry, physical settlement obligations on the equity that underlies the future. None of this changes the statistics. It changes which cointegrated pairs are actually tradeable, and at what cost, which is a different and equally binding filter. If you want the mechanics of the short leg itself, see the companion guide on short selling in India.

The failure modes: where pairs trades die

The central risk is not that the spread wiggles. It is that the spring breaks. Cointegration is an empirical relationship that holds only while the two businesses keep sharing the drivers that pinned their prices together. A merger, a demerger, a regulatory change, a broken supply chain, a balance-sheet shock, a shift in the competitive order, any of these can end the equilibrium. The spread then stops reverting and starts trending away, and the trade is now long a diverging spread with no mean to return to. Because you are short one leg, the loss on that side has no natural ceiling. This regime break, not ordinary noise, is what ends most pairs strategies, and it is why a hard stop on divergence is not optional.

Figure 3 When cointegration breaks A formerly stationary spread oscillates around a flat mean, then at a regime-change point the relationship breaks and the spread trends away without reverting. The stationary region is marked as normal and the divergent tail is marked as the tail risk, where the loss on the short leg is unbounded. The tail risk: the relationship breaks mean Stationary: spread reverts regime change trends away, no reversion loss on short leg unbounded time → Illustrative. A stationarity test on past data cannot see a future break; only a divergence stop can cap it.
A test on the past cannot see the break coming. For the shaded stretch the spread is stationary and every reversion pays. At the regime change the relationship dissolves and the spread trends away with no mean to pull it back. The strategy that assumed reversion is now short a runaway. A cointegration test certifies the past, not the future, which is why the divergence stop, not the entry signal, is the part that keeps you solvent.

Two quieter failure modes compound the first. The per-trade edge in a stationary spread is typically small, so transaction costs, the borrow fee on the short leg, the bid-ask on both legs, and slippage can quietly eat it; a spread that looks profitable gross is often flat or worse net. And when you scan many pairs looking for the ones that test as cointegrated, you invite multiple-testing bias: run enough tests on the same history and a handful will pass by chance, look wonderful in-sample on the very window you searched, then fail out of sample. This is the same trap that undoes naive backtests, and the discipline that avoids it, honest out-of-sample testing and a costs-first mindset, is covered in the guides on backtesting with pandas and the backtesting mistakes retail makes.

Table 3. The risk catalogue for cointegration pairs trading
RiskMechanismMitigation
Regime breakA structural change ends the equilibrium; the spread trends away, loss on the short leg is unboundedHard divergence stop; cap per-pair capital; re-test cointegration on a rolling basis and retire pairs that decay
Costs exceed edgeSmall per-trade edge consumed by brokerage, borrow fee, bid-ask and slippageModel all costs before trading; require the net, not gross, edge to clear; widen thresholds so trades are less frequent
Overfitting / multiple testingScanning many pairs and tuning thresholds finds spurious in-sample winners that fail liveOut-of-sample and walk-forward validation; adjust for the number of pairs searched; prefer economic logic to a pure data scan
Short-leg constraintNaked shorting is barred; SLB borrow may be scarce or costly; futures have lot sizes and expiry settlementConfirm borrow or a futures route before committing; round to lot sizes; avoid carrying into expiry unintentionally
Unstable hedge ratioThe OLS hedge ratio drifts over time and depends on which series is the dependent oneRe-estimate on a rolling window; consider Johansen for a stabler vector; watch the ADF or Engle-Granger verdict near the threshold

Where this fits

Cointegration pairs trading is a genuine, statistically grounded style, but it is not a shortcut. Its edge is thin, its short leg is constrained by Indian rules, and its defining risk is a relationship quietly ceasing to hold. The value is in the discipline the method demands: testing the right thing, sizing the horizon by the half-life, respecting costs, and stopping on divergence rather than hoping. That upstream statistical judgement, telling a real equilibrium from a coincidence and a survivable trade from an overfit one, is the harder and more durable half of the skill, and it is where careful quantitative work in India actually lives. The same mean-reversion-and-arbitrage family also shows up in ETF arbitrage on the NSE, where the equilibrium is enforced by a creation-redemption mechanism rather than a statistical one.

Frequently asked questions

Correlation measures whether two series move together, typically the co-movement of their returns over a window. It says nothing about the gap between the price levels. Two prices can be highly correlated and still drift apart without limit, because correlation is scale-free and short-memoried. Cointegration is a statement about the levels: a specific linear combination of two non-stationary price series is itself stationary, so their spread has a fixed mean it keeps returning to. Pairs trading needs a stationary, mean-reverting spread, which is cointegration, not correlation.

The Engle-Granger two-step test is the standard for a single pair. Step one regresses the price of stock A on the price of stock B by ordinary least squares; the slope is the hedge ratio and the regression residual is the spread. Step two runs an Augmented Dickey-Fuller test on that residual to check whether it is stationary. If the ADF test rejects the unit-root null, the spread is stationary and the pair is cointegrated. In statsmodels, coint() runs this with correct Engle-Granger critical values; adfuller() runs the residual test manually.

The hedge ratio is how many units of stock B you trade against one unit of stock A so that the combined position, the spread, is as close to stationary as the data allow. It is the slope from regressing the price of A on the price of B. If the hedge ratio is 1.4, the spread is defined as price of A minus 1.4 times price of B, plus the regression intercept. The ratio matters because you trade the spread, not the two stocks separately, and the wrong ratio leaves a residual trend that never mean-reverts.

You standardise the spread into a z-score by subtracting its rolling mean and dividing by its rolling standard deviation, so it oscillates around zero in units of deviation. A stretched z-score means the spread is unusually wide relative to its own history. A common rule enters when the magnitude passes a threshold near two, shorting the leg that has become rich and buying the leg that has become cheap, and exits as the z-score reverts toward zero. The thresholds are choices, not laws; they trade signal frequency against reliability, and they must clear costs.

The half-life is the expected time for the spread to close half the distance back to its mean. It comes from modelling the spread as an Ornstein-Uhlenbeck process, whose discrete form is an AR(1). You regress the daily change in the spread on the lagged spread; the slope, lambda, is negative for a mean-reverting series, and the half-life equals minus the natural log of two divided by lambda. It sets the expected holding period. A very short half-life is often just noise, and a very long one ties up capital longer than the edge can survive costs.

The Johansen test handles cointegration among three or more series at once, which the Engle-Granger two-step cannot do cleanly because it depends on which series you place on the left of the regression. Johansen estimates how many independent cointegrating relationships exist, the cointegration rank, using a trace statistic and a maximum-eigenvalue statistic, and returns the cointegrating vectors directly. In statsmodels it is coint_johansen in the vecm module. For a two-stock pair, Engle-Granger is simpler and usually sufficient; Johansen earns its keep on baskets.

A pairs trade is long the cheap leg and short the rich leg, so it profits from the spread closing regardless of the market direction. The short leg needs the stock to be borrowed or sold through a permitted route. Indian regulation prohibits naked short selling; a delivery short must be covered through the Securities Lending and Borrowing framework, and many traders instead take the short in single-stock futures where the underlying is in the derivatives segment. Borrow availability, cost and lot sizes all constrain which pairs are practical, not just which pairs test as cointegrated.

That cointegration is not permanent. The relationship rests on the two businesses sharing the drivers that pin their prices together. A structural change, a merger, a regulatory shift, a broken supply chain, a balance-sheet shock, can break the equilibrium so the spread trends away instead of reverting. The trade is then long a diverging spread with no mean to return to, and because you are short one leg the loss on that side is unbounded in principle. This regime-break risk, not day-to-day noise, is what ends most pairs strategies.

No. A passing test is a necessary condition, not a sufficient one. The per-trade edge in a stationary spread is usually small, and transaction costs, the borrow cost on the short leg, and slippage can consume it entirely; the half-life decides whether the edge clears those costs in a workable time. Scanning many pairs also invites multiple-testing bias: run enough tests and some will pass by chance on the sample you searched, then fail out of sample. A cointegration test tells you a spread was stationary in the past, which is not the same as tradeable now.

Where the facts come from

  • Engle and Granger (1987). The original two-step representation, estimation and testing of co-integration, which defines the regress-then-test-the-residual procedure used above. Engle, R. F. and Granger, C. W. J., "Co-integration and error correction," Econometrica 55(2).
  • statsmodels documentation. The coint function implements the Engle-Granger test with the correct (MacKinnon) critical values, distinct from a naive adfuller on the residual; coint_johansen in the vecm module returns the trace and maximum-eigenvalue statistics for the multivariate case. statsmodels.org
  • NSE Securities Lending and Borrowing. The exchange-run, clearing-corporation-secured SLB scheme is the route to borrow a stock for a cash-segment short leg. nseindia.com
  • SEBI short-selling framework. The regulator's framework permits short selling only through disclosed, covered routes and prohibits naked short selling, which is why the short leg of a pairs trade needs SLB or a futures position. sebi.gov.in
Educational note. This guide explains cointegration and pairs trading as a set of statistical methods and their Indian-market constraints. It is not a recommendation to trade or invest, it is not investment advice, and it makes no claim about the profitability of any method or pair. The variable names and figures are illustrative placeholders, not signals. Bharath Shiksha is an educational publisher, not a SEBI-registered investment adviser or research analyst. Statistical-arbitrage strategies carry real divergence, borrow, and cost risk, including the risk that a relationship breaks and a short leg loses without bound.

Learn to tell a real edge from an overfit one

Bharath Shiksha is a 30-volume curriculum across 6 stages, from chart reading (Stage 1 at ₹14,999) through capital raising, or the full bundle at ₹1,49,999. The quantitative track builds the statistical judgement this article assumes: stationarity, mean reversion, honest out-of-sample testing, and costs-first thinking. Start with the free diagnostic to see where you stand.

Take the free diagnostic →

Related guides