Cara Pairs Trading dan Kointegrasi Berfungsi
Kointegrasi adalah kunci utama dalam pairs trading dan ia berbeza daripada korelasi. Bina hedge ratio, spread serta z score menggunakan harga penutup sebenar secara manual.
Pairs trading dan kointegrasi
Pairs trading dan kointegrasi saling berkait rapat. Dagangan ini bergantung pada jurang antara dua harga saham yang sentiasa kembali ke tahap yang stabil. Kointegrasi ialah sifat statistik yang mengesahkan kewujudan jurang tersebut. Korelasi pula mengukur sesuatu yang berbeza. Dua saham boleh menunjukkan korelasi yang tinggi namun terus menyimpang antara satu sama lain selama-lamanya. Sebaliknya, dua saham yang pergerakan hariannya hampir tidak selari boleh mengekalkan jurang yang stabil selama bertahun-tahun.
Pembinaan model dan batasan
Halaman ini membina hedge ratio, spread, dan z score secara manual. Ia mengukur ketiga-tiga metrik tersebut berdasarkan harga penutup sebenar. Seterusnya, ia memperuntukkan ruang yang sama untuk membincangkan bagaimana pembinaan model ini boleh gagal.
Apakah itu kointegrasi dalam dagangan pasangan (pairs trading)?
Korelasi ialah tahap keakraban pergerakan peratusan harian dua saham. Ia berjulat daripada -1 hingga +1, dengan +1 bermaksud kedua-duanya naik dan turun bersama-sama pada setiap sesi dalam sampel. Ia tidak memberikan sebarang maklumat mengenai jarak antara kedua-dua harga tersebut.
Kointegrasi ialah pernyataan mengenai jarak tersebut. Ambil saham B, tolak gandaan tetap saham A, dan lihat baki yang tinggal. Jika siri baki tersebut, iaitu spread, kekal dalam julat yang terhad dan tidak melencong jauh, maka kedua-dua nama tersebut adalah berkointegrasi. Harga saham itu sendiri bebas untuk bergerak ke mana-mana. Gabungan kedua-duanya pula tidak.
Gambaran yang digunakan dalam buku teks ialah seekor anjing bertali. Pejalan kaki dan anjing itu masing-masing mengambil laluan yang tidak dapat diramal di sepanjang jalan, dan tali tersebut memastikan jarak antara mereka kekal terhad. Korelasi bertanya sama ada kedua-duanya melangkah pada saat yang sama. Kointegrasi bertanya sama ada tali tersebut masih memegang.
Panel di bawah mengukur idea pertama bagi lima pasangan yang lazim sepanjang tahun 2024 dan 2025. Lajur return_corr ialah korelasi pergerakan peratusan harian, yang biasanya dimaksudkan oleh orang ramai dengan perkataan tersebut. Lajur price_corr ialah korelasi harga penutup mentah, satu angka yang kelihatan baik bagi hampir mana-mana dua nama yang kedua-duanya meningkat.
SQL tepat di sebalik setiap nombor
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 DESCDisusun mengikut korelasi pergerakan harian, HD / LOW berada di kedudukan teratas panel pada 0.868, manakala korelasi bagi dua tahap harga sepanjang tempoh yang sama mencatatkan 0.849. Pada baris bawah, AAPL / MSFT membawa korelasi pulangan sebanyak 0.479 di samping korelasi harga sebanyak 0.508. Tiada satu pun daripada lajur tersebut menjawab soalan yang ditanya oleh pedagang pasangan. Kedua-duanya mengukur pergerakan bersama, sedangkan dagangan tersebut memerlukan ukuran jarak.
Bagaimanakah anda mengira hedge ratio dan spread?
Lima langkah, mengikut urutan, merentasi dua senarai harga penutup. Python biasa merangkumi kesemuanya dengan math sebagai satu-satunya import: tiada pakej, tiada vendor data, tiada rangkaian.
- Pusatkan setiap siri.
mean_a = sum(a) / len(a), dan perkara yang sama untuk senaraib. - Sesuaikan hedge ratio. Ia adalah cerun garis lurus B berbanding 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). Baca ia sebagai bilangan unit A yang mengimbangi satu unit B. - Bina spread.
spread = [b[i] - beta * a[i] for i in range(len(a))]. Pada pasangan yang berintegrasi bersama (cointegrated), siri ini berlegar di sekitar satu tahap dan bukannya menunjukkan arah aliran. - Ambil tetingkap susulan (trailing window). Dengan
w = spread[i - win + 1 : i + 1], min tetingkap ialahmu = sum(w) / len(w)dan sisihan piawai sampel ialahsd = math.sqrt(sum((x - mu) ** 2 for x in w) / (len(w) - 1)). Susulan bermaksud tetingkap berakhir pada hari yang dinilai dan tidak menggunakan apa-apa selepasnya. - Skor dan cetak.
z = (spread[i] - mu) / sd, kemudian cetak baris masuk semasaabs(z) > 1.5dan baris keluar sebaik sahajaabs(z) < 0.5. Z sebanyak dua meletakkan spread dua sisihan piawai di atas purata terkini sendiri.
Dua senarai harga yang dikodkan secara tetap sudah memadai untuk melihat proses ini berjalan, dan win sebanyak lima memastikan contoh mainan boleh dibaca. Kerja yang serius menggunakan sesuatu yang lebih hampir kepada enam puluh tiga sesi, kira-kira satu suku tahun. Ambang tersebut, satu perpuluhan lima untuk masuk dan sifar perpuluhan lima untuk keluar, adalah konvensyen yang diwariskan daripada satu tutorial kepada tutorial seterusnya. Ia bukanlah penemuan, dan tiada apa-apa dalam panel di bawah yang memilihnya.
Bagaimanakah skor z dagangan pasangan kelihatan pada harga sebenar?
Berikut adalah pengiraan yang sama bagi dua nama minuman isi rumah, KO dan PEP. Nisbah lindung nilai (hedge ratio) diperoleh daripada harga tutup tahun 2023 sahaja, kemudian ditetapkan kekal sepanjang tahun 2024 dan 2025, iaitu tempoh yang diliputi oleh carta tersebut. Menetapkan cerun pada sampel yang sama yang anda gunakan untuk membuat skor adalah bias pandang ke hadapan dalam ujian semula, dan memisahkan tempoh penetapan dengan tempoh pemarkahan adalah cara paling murah untuk menanganinya.
SQL tepat di sebalik setiap nombor
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 weekJejak tersebut membawa 105 bacaan mingguan. Ia membuka tetingkap pada skor z sebanyak -1.53 dan menutupnya pada -0.68. Baca bentuknya dan bukannya mana-mana titik tunggal. Pasangan yang berkelakuan seperti yang diandaikan oleh strategi akan melintasi ambangnya, menghabiskan beberapa minggu untuk kembali ke arah sifar, dan melintasinya semula. Pasangan yang telah berhenti kembali kepada purata akan kekal di luar ambang tersebut dan terus berada di sana, yang pada carta kelihatan seperti garis rata yang panjang jauh dari bahagian tengah.
Adakah spread yang terkointegrasi sentiasa kembali ke tahap asal?
Tidak, dan cara yang jujur untuk melihatnya adalah dengan mengukur apa yang berlaku selepas setiap titik permulaan. Panel di bawah mengumpulkan setiap sesi dari tahun 2019 hingga lewat 2025 mengikut skor z hari tersebut, kemudian melaporkan purata skor z bagi spread yang sama dua puluh sesi kemudian. Ia menggunakan log nisbah harga dan bukannya spread yang disesuaikan, jadi tiada regresi yang dianggarkan selepas fakta menyentuh carta ini.
SQL tepat di sebalik setiap nombor
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_startSesi yang bermula dalam baldi z below -2 mencatatkan purata -2.42 pada hari tersebut, dan spread yang sama mencatatkan purata -0.84 dua puluh sesi kemudian, merentasi 138 sesi. Pada hujung yang satu lagi, baldi z above 2 bermula pada 2.64 dan mencatatkan 0.92 selepas dua puluh sesi. Lengkung yang menarik ke arah sifar dari kedua-dua hujung adalah bentuk yang dihasilkan oleh pembalikan min (mean reversion).
Baca carta ini dengan mengambil kira lajur bilangan. Baldi luar memegang sesi paling sedikit, dan sesi di dalam baldi bertindih dengan banyak, jadi segelintir tempoh yang panjang membekalkan kebanyakan baris. Purata bukanlah satu janji mengenai mana-mana entri tunggal.
Mengapakah dagangan pasangan berhenti berfungsi?
Hedge ratio bukanlah satu pemalar. Laraskan semula nisbah ini pada setiap tahun kalendar dan ia akan berubah.
SQL tepat di sebalik setiap nombor
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 yearKecerunan PEP terhadap KO diukur 2.338 merentasi 2019 dan -0.543 merentasi 2025, dengan pasangan sektor kedua disertakan sebagai perbandingan. Ujian ke belakang (backtest) yang menetapkan satu kecerunan sepanjang sejarah penuh dan mendagangkannya dari hari pertama memberikan setiap dagangan awal satu angka yang tidak mungkin dipegang oleh sesiapa pun pada masa itu. Penyelesaiannya membosankan namun berkesan: laraskan semula pada tetingkap bergerak (trailing window), dan nilai setiap hari dengan parameter yang tersedia pada hari tersebut. Ujian ke belakang yang boleh dihasilkan semula menjadikan disiplin itu boleh diperiksa oleh pihak lain.
Tindakan korporat menulis semula satu kaki (leg) dalam sekelip mata. Pecahan saham empat-untuk-satu menukarkan satu saham kepada empat dan membahagikan harga sebut harga kepada satu perempat, dan spread yang dikira merentasi tarikh tersebut pada harga yang tidak diselaraskan akan melonjak ke tahap yang tidak pernah didagangkan. Penggabungan, pecahan syarikat (spin-off) dan perubahan indeks melakukan versi yang lebih senyap bagi perkara yang sama. Mulakan dengan sejarah harga yang diselaraskan dengan pecahan, dan ambil perhatian bahawa simbol boleh diberikan semula kepada syarikat yang sama sekali berbeza, yang merupakan sebab ticker symbols merosakkan set data.
Satu kerosakan dan satu peluang kelihatan serupa semasa ia berlaku. Z score paling luas yang pernah dicatatkan oleh sesuatu pasangan sama ada merupakan penyertaan terbaik yang pernah ditawarkan atau minggu pertama bagi hubungan yang telah berakhir. Kedua-duanya kelihatan seperti spread yang tertegang pada hari tersebut. Penentuan saiz membawa beban yang tidak mampu dipikul oleh statistik: penentuan saiz posisi kriteria Kelly dan penentuan saiz posisi penyasaran volatiliti adalah dua rangka kerja bagi menentukan berapa banyak daripada akaun yang dibenarkan untuk digerakkan oleh satu spread, dan maximum drawdown mengukur kesan tempoh panjang di sebelah yang salah daripada purata terhadap lengkung ekuiti.
Z score bergerak bukanlah ujian kointegrasi. Ujian formal wujud. Prosedur Engle-Granger menjalankan regresi, kemudian menguji spread yang tertinggal untuk stationarity, dan ujian Johansen meluaskan idea tersebut melebihi dua nama. Z score mengandaikan sifat yang diperiksa oleh ujian tersebut, dan ia akan dengan gembira mencatatkan angka yang besar pada spread yang tidak mempunyai purata stabil langsung, memandangkan siri yang mempunyai trend sentiasa berada jauh daripada purata bergeraknya sendiri.
Nota data dan perkara yang ditinggalkan oleh angka-angka ini
Panel korelasi menggunakan harga tutup harian dari 2024-01-01 hingga 2025-12-31 dan mengira pulangan daripada harga tutup berturut-turut, dengan menggugurkan sesi pertama setiap nama. Jejak z score melaraskan hedge ratio pada harga tutup 2023 sahaja, kemudian memberi skor kepada 2024 dan 2025 dengan purata 63 sesi bergerak dan sisihan piawai sampel, yang disampelkan kepada bacaan terakhir setiap minggu. Panel pembalikan memuatkan sejarah dari 2018 dan melaporkan dari 2019 seterusnya, jadi setiap hari yang diberi skor mempunyai tetingkap bergerak penuh di belakangnya, dan ia berhenti pada pertengahan November 2025 supaya setiap hari mempunyai dua puluh sesi di hadapannya di dalam sampel.
Tiada satu pun daripada panel ini merupakan strategi. Ia tidak membawa kos dagangan, tiada bid-ask spread, tiada yuran pinjaman pada kaki pendek (short leg), tiada dividen dan tiada pembiayaan. Hanya harga tutup, yang bermaksud penyertaan yang ditandakan pada harga tutup adalah penyertaan yang tidak mungkin dapat diisi oleh sesiapa pun di situ.
Soalan Lazim
Apakah perbezaan antara korelasi dan kointegrasi?
Korelasi mengukur sama ada dua saham bergerak pada hari yang sama dan dalam arah yang sama, pada skala negatif satu hingga positif satu. Kointegrasi mengukur sama ada jarak antara harga kedua-duanya kekal dalam julat yang stabil. Sesebuah pasangan boleh mendapat skor tinggi pada ukuran pertama tetapi gagal pada ukuran kedua, yang merupakan sebab biasa mengapa saringan korelasi menghasilkan pasangan yang kemudiannya bergerak menjauhi antara satu sama lain.
Bagaimanakah anda mengira hedge ratio dalam dagangan pasangan?
Padankan garis lurus harga satu saham dengan harga saham yang satu lagi dan ambil kecerunannya. Kecerunan itu ialah bilangan unit saham pertama yang mengimbangi satu unit saham kedua, dan ia merupakan kuantiti yang berubah-ubah, jadi kebanyakan pelaksanaan menetapkan semula nilai tersebut pada tetingkap susulan (trailing window) dan bukannya sekali sahaja bagi keseluruhan sampel.
Apakah z score yang digunakan oleh pedagang pasangan untuk masuk dan keluar pasaran?
Contoh tutorial biasanya masuk sekitar satu per lima hingga dua sisihan piawai daripada min susulan dan keluar berhampiran sifar perpuluhan lima. Angka-angka tersebut adalah konvensyen yang diwarisi daripada penulisan terdahulu dan bukannya optimum yang diukur, dan mengubahnya akan mengubah bilangan dagangan serta tempoh pegangan bagi setiap dagangan.
Bolehkah dua saham menjadi kointegrasi dengan korelasi yang rendah?
Ya. Korelasi dikira berdasarkan perubahan harian manakala kointegrasi dikira berdasarkan tahap jurang, jadi dua nama yang pergerakan hariannya jarang selari masih boleh mengekalkan jarak jangka panjang yang stabil. Perkara sebaliknya juga berlaku: korelasi harian yang tinggi di samping jurang yang melebar dari tahun ke tahun.
Mengapa pasangan yang berkointegrasi berhenti berfungsi?
Hubungan yang mengekalkan jurang tersebut boleh berubah: penggabungan, pecahan syarikat (spin-off), perubahan dalam campuran perniagaan sesebuah syarikat, atau perubahan indeks yang mengubah pihak yang memiliki saham tersebut. Statistik pada hari-hari sebelum berlakunya perpecahan kelihatan sama seperti hari-hari sebelum berlakunya pembalikan biasa, iaitu bahagian yang perlu diselaraskan saiznya dan bukannya diramal.
Setiap panel di sini disertakan dengan SQL yang tepat di bawahnya, jadi tetingkap, tempoh padanan, dan had baldi semuanya boleh dilihat. Untuk menjalankan spread dan z score yang sama pada pasangan yang anda ikuti, ajukan soalan dalam bahasa Inggeris yang mudah pada terminal Strasmore.