Pairs Trading at Cointegration: Paliwanag
Kailangan ng pairs trading ang cointegration, hindi lang correlation. Alamin ang hedge ratio, spread, at z score gamit ang aktuwal na closing prices.
Magkaugnay ang pairs trading at cointegration. Nakabatay ang trade sa agwat sa pagitan ng presyo ng dalawang stock na paulit-ulit na bumabalik sa isang stable na antas. Ang cointegration naman ang statistical property na nagsasabing umiiral nga ang ganoong agwat. Iba ang sinusukat ng correlation. Maaaring mataas ang correlation ng dalawang stock ngunit patuloy pa ring lumayo ang presyo nila sa isa’t isa. Maaari ring hindi gaanong nagtutugma ang araw-araw nilang galaw, pero manatiling stable ang agwat sa loob ng maraming taon. Sa page na ito, mano-manong bubuuin ang hedge ratio, spread, at z score. Susukatin ang tatlo gamit ang aktuwal na closing prices. Pantay na tatalakayin kung paano maaaring mabigo ang construction na ito.
Ano ang cointegration sa pairs trading?
Ang correlation ay sumusukat sa pagkakahawig ng araw-araw na percentage moves ng dalawang stock. Nasa pagitan ito ng -1 at +1. Ibig sabihin ng +1, sabay silang tumaas at bumaba sa bawat session sa sample. Wala itong sinasabi tungkol sa agwat ng dalawang presyo.
Ang cointegration ay pahayag tungkol sa agwat na iyon. Kunin ang stock B, ibawas ang isang takdang multiple ng stock A, at tingnan ang natitira. Kung ang natitirang series na ito, ang spread, ay nananatili sa loob ng bounded range sa halip na patuloy na lumayo, cointegrated ang dalawang pangalan. Malaya pa ring pumunta saanman ang mismong mga presyo. Hindi ganoon ang kombinasyon ng mga ito.
Ang karaniwang ilustrasyon sa mga textbook ay aso na may tali. Parehong maaaring tumahak ang walker at ang aso sa hindi tiyak na direksiyon sa kalye, ngunit pinananatili ng tali na bounded ang distansiya sa pagitan nila. Itinatanong ng correlation kung sabay bang humahakbang ang dalawa. Itinatanong ng cointegration kung napapanatili ng tali ang distansiya.
Sinusukat ng panel sa ibaba ang unang konsepto sa limang pamilyar na pares noong 2024 at 2025. Ang return_corr column ay ang correlation ng araw-araw na percentage moves, na karaniwang tinutukoy ng mga tao kapag ginagamit ang salitang ito. Ang price_corr column ay ang correlation ng raw closing prices, isang bilang na maaaring magmukhang mataas para sa halos anumang dalawang pangalan na parehong umakyat.
Ang eksaktong SQL sa likod ng bawat numero
WITH
px AS (
SELECT
ticker,
date,
toFloat64(any(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('KO', 'PEP', 'HD', 'LOW', 'XOM', 'CVX', 'V', 'MA', 'AAPL', 'MSFT')
AND date BETWEEN '2024-01-01' AND '2025-12-31'
GROUP BY ticker, date
),
rets AS (
SELECT
ticker,
date,
close_px,
close_px / lagInFrame(close_px) OVER (
PARTITION BY ticker ORDER BY date
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW
) - 1 AS ret
FROM px
)
SELECT
p.pair AS pair,
round(corr(a.ret, b.ret), 3) AS return_corr,
round(corr(a.close_px, b.close_px), 3) AS price_corr
FROM
(
SELECT
tupleElement(t, 1) AS leg_a,
tupleElement(t, 2) AS leg_b,
tupleElement(t, 3) AS pair
FROM
(
SELECT arrayJoin([
('KO', 'PEP', 'KO / PEP'),
('HD', 'LOW', 'HD / LOW'),
('XOM', 'CVX', 'XOM / CVX'),
('V', 'MA', 'V / MA'),
('AAPL', 'MSFT', 'AAPL / MSFT')
]) AS t
)
) AS p
INNER JOIN rets AS a ON a.ticker = p.leg_a
INNER JOIN rets AS b ON b.ticker = p.leg_b AND b.date = a.date
WHERE isFinite(a.ret) AND isFinite(b.ret)
GROUP BY pair
ORDER BY return_corr DESCAyon sa ranggo batay sa correlation ng daily moves, nasa itaas ng panel ang HD / LOW sa 0.868, habang ang correlation ng dalawang price level sa parehong window ay 0.849. Sa pinakailalim na row, ang AAPL / MSFT ay may return correlation na 0.479 at price correlation na 0.508. Wala sa dalawang column ang sumasagot sa tanong ng pairs trader. Pareho nilang sinusukat ang co-movement, ngunit kailangan ng trade ng panukat ng distansiya.
Paano kinakalkula ang hedge ratio at spread?
Limang hakbang, sa tamang pagkakasunod, gamit ang dalawang listahan ng closing prices. Sapat na ang plain Python para sa lahat ng ito, at math lamang ang kailangang i-import: walang packages, data vendor, o network.
- I-center ang bawat series.
mean_a = sum(a) / len(a), at ganoon din para sa listahangb. - I-fit ang hedge ratio. Ito ang slope ng isang tuwid na linya ng B laban sa A:
beta = sum((a[i] - mean_a) * (b[i] - mean_b) for i in range(len(a))) / sum((x - mean_a) ** 2 for x in a). Basahin ito bilang bilang ng units ng A na nag-o-offset sa isang unit ng B. - Buuin ang spread.
spread = [b[i] - beta * a[i] for i in range(len(a))]. Sa cointegrated pair, umiikot ang series na ito sa isang level sa halip na patuloy na mag-trend. - Gumamit ng trailing window. Sa
w = spread[i - win + 1 : i + 1], ang window mean aymu = sum(w) / len(w)at ang sample standard deviation aysd = math.sqrt(sum((x - mu) ** 2 for x in w) / (len(w) - 1)). Ang trailing ay nangangahulugang nagtatapos ang window sa araw na sinusukat at walang ginagamit na datos pagkatapos nito. - Kalkulahin ang score at i-print ito.
z = (spread[i] - mu) / sd, pagkatapos ay mag-print ng entry line kapagabs(z) > 1.5at ng exit line kapagabs(z) < 0.5. Kapag 2 ang z, ang spread ay dalawang standard deviation na mas mataas kaysa sa sarili nitong kamakailang average.
Sapat na ang dalawang hard-coded price list para mapanood ang pagtakbo nito, at pinananatiling madaling basahin ang toy example sa pamamagitan ng win na 5. Para sa seryosong trabaho, mas karaniwang ginagamit ang humigit-kumulang 63 sessions, o halos isang quarter. Ang mga threshold na iyon—1.5 para sa entry at 0.5 para sa exit—ay mga convention na ipinapasa mula sa isang tutorial patungo sa susunod. Hindi ang mga ito resulta ng findings, at walang pinili sa mga panel sa ibaba.
Ano ang hitsura ng pairs-trading z-score sa aktuwal na prices?
Narito ang parehong kalkulasyon para sa dalawang kilalang beverage company, KO at PEP. Ang hedge ratio ay kinuha lamang mula sa mga closing price noong 2023, at nanatiling fixed sa buong 2024 at 2025, ang panahong saklaw ng chart. Ang pag-fit ng slope sa parehong sample na gagamitin mo para sa scoring ay look-ahead bias sa backtesting, at ang paghihiwalay ng fit window at scoring window ang pinakamurang depensa laban dito.
Ang eksaktong SQL sa likod ng bawat numero
WITH
daily AS (
SELECT
date,
anyIf(toFloat64(close), ticker = 'PEP') AS pep,
anyIf(toFloat64(close), ticker = 'KO') AS ko
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('KO', 'PEP')
AND date BETWEEN '2023-01-01' AND '2025-12-31'
GROUP BY date
HAVING pep > 0 AND ko > 0
),
fitted AS (
SELECT covarSamp(pep, ko) / varSamp(ko) AS beta
FROM daily
WHERE date < '2024-01-01'
),
spread AS (
SELECT
daily.date AS date,
daily.pep - fitted.beta * daily.ko AS spread_usd
FROM daily
CROSS JOIN fitted
),
scored AS (
SELECT
date,
(spread_usd - avg(spread_usd) OVER (
ORDER BY date ROWS BETWEEN 62 PRECEDING AND CURRENT ROW))
/ stddevSampStable(spread_usd) OVER (
ORDER BY date ROWS BETWEEN 62 PRECEDING AND CURRENT ROW) AS z
FROM spread
)
SELECT
toString(toMonday(date)) AS week,
round(argMax(z, date), 2) AS z_score
FROM scored
WHERE date >= '2024-01-01'
AND isFinite(z)
GROUP BY week
ORDER BY weekMay 105 weekly readings ang trace. Nagsisimula ang window sa z-score na -1.53 at nagtatapos sa -0.68. Tingnan ang hugis nito, hindi ang isang punto lamang. Ang isang pair na kumikilos ayon sa ipinapalagay ng strategy ay tatawid sa threshold nito, gugugol ng ilang linggo sa pagbalik patungo sa zero, at muling tatawid. Ang pair na tumigil na sa mean reversion ay mananatili lampas sa threshold at hindi agad babalik. Sa chart, magmumukha itong mahabang patag na bahagi na malayo sa gitna.
Palagi bang bumabalik ang cointegrated spread?
Hindi. Ang tapat na paraan para makita ito ay sukatin kung ano ang sumunod sa bawat starting point. Sa panel sa ibaba, pinapangkat ang bawat session mula 2019 hanggang huling bahagi ng 2025 ayon sa z score noong araw na iyon. Pagkatapos, inilalahad nito ang average z score ng parehong spread makalipas ang twenty sessions. Ginagamit nito ang log ng price ratio sa halip na fitted spread, kaya walang regression na tinantiya pagkatapos ng kaganapan ang nakaaapekto sa chart.
Ang eksaktong SQL sa likod ng bawat numero
WITH
daily AS (
SELECT
date,
anyIf(toFloat64(close), ticker = 'PEP') AS pep,
anyIf(toFloat64(close), ticker = 'KO') AS ko
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('KO', 'PEP')
AND date BETWEEN '2018-01-01' AND '2025-12-31'
GROUP BY date
HAVING pep > 0 AND ko > 0
),
spread AS (
SELECT
date,
log(pep / ko) AS log_ratio
FROM daily
),
scored AS (
SELECT
date,
(log_ratio - avg(log_ratio) OVER (
ORDER BY date ROWS BETWEEN 62 PRECEDING AND CURRENT ROW))
/ stddevSampStable(log_ratio) OVER (
ORDER BY date ROWS BETWEEN 62 PRECEDING AND CURRENT ROW) AS z
FROM spread
),
horizon AS (
SELECT
date,
z,
leadInFrame(z, 20) OVER (
ORDER BY date ROWS BETWEEN CURRENT ROW AND 20 FOLLOWING
) AS z_fwd
FROM scored
WHERE isFinite(z)
)
SELECT
multiIf(z < -2, 'z below -2',
z < -1, 'z -2 to -1',
z < 0, 'z -1 to 0',
z < 1, 'z 0 to 1',
z < 2, 'z 1 to 2',
'z above 2') AS z_bucket,
round(avg(z), 2) AS avg_z_start,
round(avg(z_fwd), 2) AS avg_z_20d_later,
count() AS episode_count
FROM horizon
WHERE date >= '2019-01-01'
AND date <= '2025-11-15'
AND isFinite(z_fwd)
GROUP BY z_bucket
ORDER BY avg_z_startAng mga session na nagsimula sa z below -2 bucket ay may average na -2.42 noong araw na iyon. Makalipas ang twenty sessions, ang parehong spread ay may average na -0.84, sa kabuuang 138 sessions. Sa kabilang dulo, nagsimula ang z above 2 bucket sa 2.64 at nagtala ng 0.92 makalipas ang twenty sessions. Ang kurbang humihila patungo sa zero mula sa magkabilang dulo ang hugis na nabubuo sa mean reversion.
Basahin ito kasabay ng count column. Pinakakaunti ang session sa mga outer bucket. Malaki rin ang overlap ng mga session sa loob ng isang bucket, kaya iilang mahahabang yugto ang bumubuo sa malaking bahagi ng mga row. Ang average ay hindi pangako para sa anumang indibidwal na entry.
Bakit humihinto sa paggana ang pairs trading?
Hindi constant ang hedge ratio. I-refit ito sa bawat calendar year at nagbabago ito.
Ang eksaktong SQL sa likod ng bawat numero
WITH daily AS (
SELECT
date,
anyIf(toFloat64(close), ticker = 'PEP') AS pep,
anyIf(toFloat64(close), ticker = 'KO') AS ko,
anyIf(toFloat64(close), ticker = 'LOW') AS lowes,
anyIf(toFloat64(close), ticker = 'HD') AS hd
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('KO', 'PEP', 'HD', 'LOW')
AND date BETWEEN '2019-01-01' AND '2025-12-31'
GROUP BY date
HAVING ko > 0 AND pep > 0 AND hd > 0 AND lowes > 0
)
SELECT
toYear(date) AS year,
round(covarSamp(pep, ko) / varSamp(ko), 3) AS pep_on_ko_beta,
round(covarSamp(lowes, hd) / varSamp(hd), 3) AS lowes_on_hd_beta
FROM daily
GROUP BY year
ORDER BY yearAng slope ng PEP laban sa KO na sinukat noong 2.338 sa loob ng 2019 at noong -0.543 sa loob ng 2025, kasama ang ikalawang sector pair bilang paghahambing. Sa backtest na nagfi-fit ng isang slope sa buong history at ginagamit ito sa trading mula unang araw, binibigyan ang bawat maagang trade ng numerong hindi pa maaaring hawak ng trader noong panahong iyon. Simple pero epektibo ang solusyon: i-refit ang modelo gamit ang trailing window, at i-score ang bawat araw gamit ang mga parameter na available sa araw na iyon. Ginagawang nasusuri ng ibang tao ang disiplinang ito ng isang reproducible backtest.
Binabago ng corporate actions ang isang leg nang overnight. Ginagawang apat ng 4-for-1 split ang isang share at hinahati sa apat ang quoted price. Dahil dito, ang spread na kino-compute sa petsang iyon gamit ang unadjusted prices ay biglang umaakyat sa level na hindi naman na-trade. Mas tahimik na bersyon ng parehong pangyayari ang mergers, spin-offs at index changes. Magsimula sa split-adjusted price history, at tandaan na maaaring italaga ang isang symbol sa ibang-ibang kumpanya. Ito ang dahilan kung bakit nasisira ng ticker symbols ang mga dataset.
Magkapareho ang hitsura ng isang break at isang opportunity habang nangyayari ang mga ito. Ang pinakamalawak na z score na naitala ng isang pair ay maaaring ang pinakamagandang entry na naibigay nito, o ang unang linggo ng relasyong nagtapos na. Pareho silang mukhang stretched spread sa araw na iyon. Ang position sizing ang pumupuno sa limitasyon ng statistics: ang Kelly criterion position sizing at volatility targeting position sizing ay dalawang framework para tukuyin kung gaano kalaking bahagi ng account ang maaaring maapektuhan ng isang spread. Sinusukat naman ng maximum drawdown kung ano ang ginagawa ng mahabang panahong nasa maling panig ng mean sa equity curve.
Hindi cointegration test ang rolling z score. May mga formal test para rito. Isinasagawa ng Engle-Granger procedure ang regression, pagkatapos ay sinusuri kung stationary ang natirang spread. Pinalalawak naman ng Johansen test ang ideya lampas sa dalawang pangalan. Ipinapalagay ng z score ang property na sinusuri ng mga test na ito. Madali rin itong maglabas ng malaking numero para sa spread na walang stable mean, dahil ang trending series ay laging malayo sa sarili nitong trailing average.
Mga tala sa data at mga hindi isinama ng mga numerong ito
Gumagamit ang correlation panel ng daily closes mula 2024-01-01 hanggang 2025-12-31. Kino-compute ang returns mula sa magkakasunod na closes, at inaalis ang unang session ng bawat pangalan. Ang z score trace ay nagfi-fit ng hedge ratio gamit lamang ang 2023 closes. Pagkatapos, ini-score nito ang 2024 at 2025 gamit ang trailing 63-session mean at sample standard deviation. Sine-sample ito sa huling reading ng bawat linggo. Kinakarga ng reversion panel ang history mula 2018 at nag-uulat mula 2019 pataas. Dahil dito, may buong trailing window sa likod ng bawat araw na sini-score. Humihinto ito sa kalagitnaan ng November 2025 upang magkaroon ang bawat araw ng twenty sessions sa hinaharap sa loob ng sample.
Wala sa mga panel na ito ang isang strategy. Wala silang trading costs, bid-ask spread, borrow fee para sa short leg, dividends o financing. Closing prices lamang ang ginamit. Nangangahulugan ito na ang entry na minarkahan sa isang close ay entry na walang trader na aktuwal na makapupuno sa presyong iyon.
FAQ
Ano ang pagkakaiba ng correlation at cointegration?
Sinusukat ng correlation kung gumagalaw ang dalawang stock sa parehong araw at sa parehong direksiyon, sa scale na -1 hanggang +1. Sinusukat naman ng cointegration kung nananatili sa isang stable na range ang agwat sa pagitan ng kanilang mga presyo. Maaaring mataas ang score ng isang pair sa una ngunit mababa sa ikalawa. Ito ang karaniwang dahilan kung bakit naglalabas ang correlation screen ng mga pair na kalaunan ay nagkakahiwalay ang galaw.
Paano kinakalkula ang hedge ratio sa pairs trading?
Mag-fit ng straight line sa presyo ng isang stock laban sa presyo ng isa pa, at gamitin ang slope nito. Ipinapakita ng slope ang bilang ng units ng unang stock na nag-o-offset sa isang unit ng ikalawang stock. Nagbabago ang halagang ito, kaya karaniwang nire-refit ito ng mga implementation gamit ang trailing window sa halip na isang beses lamang para sa buong sample.
Anong z score ang ginagamit ng pairs traders sa pagpasok at paglabas?
Karaniwang pumapasok ang mga tutorial example kapag nasa humigit-kumulang 1.5 hanggang 2 standard deviations ang layo mula sa trailing mean, at lumalabas malapit sa 0.5. Mga convention ang mga numerong ito na minana mula sa mga naunang write-up, hindi mga nasukat na optimum. Kapag binago ang mga ito, nagbabago rin ang bilang ng trades at ang haba ng panahon ng paghawak sa bawat trade.
Maaari bang cointegrated ang dalawang stock kahit mababa ang correlation?
Oo. Kinakalkula ang correlation batay sa daily changes, samantalang ang cointegration ay batay sa level ng gap. Kaya maaaring magkaroon ng stable long-run distance ang dalawang stock kahit bihirang magtugma ang kanilang day-to-day moves. Maaari ring mangyari ang kabaligtaran: mataas ang daily correlation ngunit patuloy na lumalaki ang gap taon-taon.
Bakit tumitigil sa paggana ang isang cointegrated pair?
Maaaring magbago ang ugnayang nagpapanatiling magkakalapit sa gap. Kabilang sa mga posibleng dahilan ang merger, spin-off, pagbabago sa business mix ng isang kumpanya, o pagbabago sa index na nakaaapekto kung sino ang may hawak ng stock. Magkapareho ang hitsura ng statistics sa mga araw bago ang isang break at sa mga araw bago ang ordinaryong reversion. Kaya kailangang iangkop ang position size sa panganib na ito sa halip na subukang hulaan ito.
Ang bawat panel dito ay may kasamang eksaktong SQL sa ilalim, kaya makikita ang mga window, fit period, at bucket edge. Para patakbuhin ang parehong spread at z score sa isang pair na sinusubaybayan mo, itanong ito sa plain English sa Strasmore terminal.