Strasmore Research
Investigasi Matt ConnorOleh Matt Connor

Pairs Trading dan Cointegration: Panduan Lengkap

Pelajari perbedaan cointegration dan correlation dalam pairs trading, lalu hitung hedge ratio, spread, dan z score dari harga penutupan aktual.

Pairs trading dan cointegration saling berkaitan. Strategi ini bertumpu pada selisih antara dua harga saham yang berulang kali kembali ke tingkat stabil. Cointegration adalah sifat statistik yang menunjukkan bahwa selisih semacam itu memang ada.

Correlation mengukur hal yang berbeda. Dua saham dapat mencatat correlation tinggi tetapi tetap bergerak menjauh tanpa batas. Sebaliknya, dua saham yang pergerakan hariannya hampir tidak sejalan dapat mempertahankan selisih yang stabil selama bertahun-tahun.

Halaman ini menghitung hedge ratio, spread, dan z score secara manual. Ketiganya diukur menggunakan harga penutupan aktual. Halaman ini juga membahas secara seimbang bagaimana konstruksi tersebut dapat gagal.

Apa yang dimaksud dengan cointegration dalam pairs trading?

Correlation mengukur keeratan pergerakan persentase harian dua saham. Nilainya berkisar dari -1 hingga +1. Nilai +1 berarti keduanya naik dan turun bersama pada setiap sesi dalam sampel. Correlation tidak menjelaskan jarak antara kedua harga.

Cointegration berkaitan dengan jarak tersebut. Ambil saham B, kurangi dengan kelipatan tetap dari saham A, lalu lihat sisanya. Jika rangkaian sisa itu, yaitu spread, tetap berada dalam rentang yang terbatas dan tidak terus menjauh, kedua saham tersebut dikatakan cointegrated. Harga masing-masing saham tetap bebas bergerak ke mana saja. Namun, kombinasi keduanya tidak.

Ilustrasi yang digunakan dalam buku teks adalah anjing yang diikat dengan tali. Pejalan kaki dan anjing itu bergerak melalui jalur yang tidak dapat diprediksi di sepanjang jalan, tetapi tali membatasi jarak di antara keduanya. Correlation menanyakan apakah keduanya melangkah pada saat yang sama. Cointegration menanyakan apakah tali tersebut tetap menahan jaraknya.

Panel di bawah ini mengukur gagasan pertama pada lima pairs yang umum digunakan sepanjang 2024 dan 2025. Kolom return_corr menunjukkan correlation pergerakan persentase harian, yang biasanya dimaksud orang ketika menggunakan istilah tersebut. Kolom price_corr menunjukkan correlation harga penutupan mentah, yaitu angka yang cenderung membuat hampir setiap dua saham terlihat berkorelasi jika keduanya sama-sama naik.

QueryKorelasi return harian vs korelasi tingkat harga, lima pasangan yang umum (2024-2025)
SQL tepat di balik setiap angka
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 DESC
Run this yourself

Jika diurutkan berdasarkan correlation pergerakan harian, HD / LOW berada di posisi teratas panel dengan nilai 0.868, sedangkan correlation kedua level harga selama periode yang sama mencapai 0.849. Pada baris terbawah, AAPL / MSFT memiliki correlation return sebesar 0.479, di samping correlation harga sebesar 0.508. Tidak satu pun dari kedua kolom tersebut menjawab pertanyaan yang diajukan pairs trader. Keduanya mengukur co-movement, sementara strategi pairs trading memerlukan ukuran jarak.

Bagaimana cara menghitung hedge ratio dan spread?

Lima langkah, secara berurutan, menggunakan dua daftar harga penutupan. Python murni sudah mencakup semuanya dengan math sebagai satu-satunya import: tanpa package, data vendor, atau jaringan.

  1. Pusatkan setiap seri. mean_a = sum(a) / len(a), dan lakukan hal yang sama untuk daftar b.
  2. Hitung hedge ratio. Nilainya adalah kemiringan garis lurus B terhadap 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). Artinya, jumlah unit A yang mengimbangi satu unit B.
  3. Bentuk spread. spread = [b[i] - beta * a[i] for i in range(len(a))]. Pada pasangan yang cointegrated, seri ini bergerak di sekitar suatu level, bukan mengikuti tren.
  4. Gunakan trailing window. Dengan w = spread[i - win + 1 : i + 1], rata-rata window adalah mu = sum(w) / len(w) dan sample standard deviation adalah sd = math.sqrt(sum((x - mu) ** 2 for x in w) / (len(w) - 1)). Trailing berarti window berakhir pada hari yang dinilai dan tidak menggunakan data setelah hari tersebut.
  5. Hitung skor dan cetak hasilnya. z = (spread[i] - mu) / sd, lalu cetak baris entry saat abs(z) > 1.5 dan baris exit setelah abs(z) < 0.5. Nilai z sebesar 2 berarti spread berada dua standard deviation di atas rata-ratanya baru-baru ini.

Dua daftar harga yang ditulis langsung dalam kode sudah cukup untuk mengamati proses ini, dan win sebesar 5 membuat contoh sederhana lebih mudah dibaca. Pekerjaan serius menggunakan sekitar 63 sesi, atau kira-kira satu kuartal. Threshold tersebut, yaitu 1,5 untuk entry dan 0,5 untuk exit, merupakan konvensi yang diwariskan dari satu tutorial ke tutorial berikutnya. Angka itu bukan hasil temuan, dan tidak ada satu pun panel di bawah ini yang menghasilkannya.

Seperti apa z score pairs trading pada harga riil?

Berikut perhitungan yang sama untuk dua saham perusahaan minuman yang dikenal luas, KO dan PEP. Hedge ratio dihitung hanya dari harga penutupan 2023, lalu ditetapkan tetap sepanjang 2024 dan 2025, yaitu periode yang tercakup dalam grafik. Menyesuaikan slope pada sampel yang sama dengan sampel yang kemudian digunakan untuk menghitung skor merupakan look-ahead bias dalam backtesting, dan memisahkan window fitting dari window scoring adalah perlindungan paling sederhana untuk mencegahnya.

QueryZ score mingguan spread KO/PEP, hedge ratio diestimasi hanya berdasarkan 2023
SQL tepat di balik setiap angka
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 week
Run this yourself

Grafik ini memuat 105 pembacaan mingguan. Window dibuka pada z score sebesar -1.53 dan ditutup pada -0.68. Perhatikan polanya, bukan satu titik tertentu. Pasangan yang berperilaku sesuai asumsi strategi akan melintasi threshold, menghabiskan beberapa minggu untuk kembali mendekati nol, lalu melintasinya lagi. Pasangan yang tidak lagi mengalami mean reversion akan bertahan melewati threshold, sehingga pada grafik terlihat sebagai rentang datar yang panjang dan jauh dari titik tengah.

Apakah spread yang cointegrated selalu kembali?

Tidak, dan cara yang tepat untuk melihatnya adalah mengukur apa yang terjadi setelah setiap titik awal. Panel di bawah mengelompokkan setiap sesi dari 2019 hingga akhir 2025 berdasarkan z score pada hari tersebut, lalu melaporkan rata-rata z score dari spread yang sama 20 sesi kemudian. Analisis ini menggunakan log rasio harga, bukan spread hasil estimasi, sehingga tidak ada regresi yang diestimasi setelah kejadian yang memengaruhi grafik.

QueryPosisi spread KO/PEP dua puluh sesi kemudian, berdasarkan z score awal (2019-2025)
SQL tepat di balik setiap angka
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_start
Run this yourself

Sesi yang dimulai dalam bucket z below -2 mencatat rata-rata -2.42 pada hari tersebut. Spread yang sama mencatat rata-rata -0.84 20 sesi kemudian, berdasarkan 138 sesi. Di sisi lain, bucket z above 2 dimulai pada 2.64 dan mencatat 0.92 setelah 20 sesi. Kurva yang bergerak menuju nol dari kedua sisi merupakan bentuk yang dihasilkan oleh mean reversion.

Perhatikan kolom jumlah sesi. Bucket terluar berisi sesi paling sedikit, dan sesi di dalam satu bucket banyak mengalami overlap. Akibatnya, sejumlah kecil periode panjang menyumbang sebagian besar baris. Rata-rata bukan jaminan untuk setiap posisi masuk.

Mengapa pairs trading berhenti bekerja?

Hedge ratio bukan konstanta. Lakukan refit pada setiap tahun kalender karena nilainya berubah.

QueryHedge ratio diestimasi ulang setiap tahun kalender, dua pasangan sektor
SQL tepat di balik setiap angka
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 year
Run this yourself

Kemiringan PEP terhadap KO yang diukur 2.338 pada periode 2019 dan -0.543 pada periode 2025, dengan pasangan sektor kedua ditampilkan sebagai pembanding. Backtest yang menggunakan satu kemiringan untuk seluruh riwayat lalu memperdagangkannya sejak hari pertama memberikan setiap transaksi awal sebuah angka yang saat itu belum mungkin dimiliki siapa pun. Solusinya sederhana dan efektif: lakukan refit pada trailing window, lalu evaluasi setiap hari menggunakan parameter yang tersedia pada hari tersebut. Backtest yang dapat direproduksi membuat disiplin ini dapat diperiksa oleh pihak lain.

Aksi korporasi dapat mengubah salah satu leg dalam semalam. Stock split 4-for-1 mengubah satu saham menjadi empat dan membagi harga yang ditampilkan menjadi seperempatnya. Spread yang dihitung melintasi tanggal tersebut menggunakan harga yang tidak disesuaikan akan melonjak ke level yang tidak pernah diperdagangkan. Merger, spin-off, dan perubahan indeks dapat menimbulkan versi yang lebih tenang dari hal yang sama. Mulailah dengan riwayat harga yang disesuaikan terhadap stock split, dan perhatikan bahwa sebuah simbol dapat dialihkan kepada perusahaan yang sepenuhnya berbeda. Inilah alasan ticker symbols merusak dataset.

Break dan peluang terlihat sama ketika sedang terjadi. Z score terlebar yang pernah dicetak oleh suatu pair bisa menjadi titik entry terbaik yang pernah ditawarkan, atau minggu pertama setelah hubungan tersebut berakhir. Pada hari itu, keduanya terlihat sebagai spread yang terlalu melebar. Position sizing menanggung beban yang tidak dapat ditanggung statistik: position sizing dengan Kelly criterion dan position sizing berbasis volatility targeting adalah dua kerangka untuk menentukan seberapa besar bagian akun yang boleh digerakkan oleh satu spread. Sementara itu, maximum drawdown mengukur dampak posisi yang lama berada di sisi yang salah dari mean terhadap kurva ekuitas.

Rolling z score bukan cointegration test. Tersedia pengujian formal. Prosedur Engle-Granger menjalankan regresi, lalu menguji stationarity dari spread residual. Johansen test memperluas gagasan tersebut hingga lebih dari dua nama. Z score mengasumsikan adanya sifat yang diuji oleh metode-metode tersebut. Z score juga akan mencetak angka besar pada spread yang tidak memiliki mean stabil, karena series yang sedang mengalami tren selalu berada jauh dari trailing average-nya sendiri.

Catatan data dan hal-hal yang tidak tercakup dalam angka ini

Panel korelasi menggunakan harga penutupan harian dari 2024-01-01 hingga 2025-12-31 dan menghitung return dari harga penutupan berturut-turut, dengan menghapus sesi pertama masing-masing nama. Jejak z score melakukan fit hedge ratio hanya pada harga penutupan 2023, lalu mengevaluasi 2024 dan 2025 menggunakan mean trailing 63 sesi dan sample standard deviation. Pengambilan sampel dilakukan pada pembacaan terakhir setiap minggu. Panel reversion memuat riwayat sejak 2018 dan menyajikan data mulai 2019. Dengan demikian, setiap hari yang dievaluasi memiliki trailing window penuh di belakangnya. Panel tersebut berhenti pada pertengahan November 2025 agar setiap hari memiliki dua puluh sesi ke depan di dalam sampel.

Tidak satu pun panel ini merupakan strategi. Panel-panel tersebut tidak memperhitungkan trading costs, bid-ask spread, borrow fee untuk leg short, dividen, maupun financing. Data hanya menggunakan harga penutupan. Artinya, entry yang ditandai pada harga penutupan adalah entry yang tidak mungkin dapat dieksekusi pada harga tersebut.

FAQ

Apa perbedaan antara korelasi dan kointegrasi?

Korelasi mengukur apakah dua saham bergerak pada hari yang sama dan ke arah yang sama, dengan skala -1 hingga +1. Kointegrasi mengukur apakah jarak antara harga keduanya tetap berada dalam kisaran yang stabil. Suatu pair dapat mencatat korelasi tinggi tetapi tidak terkointegrasi. Ini biasanya menyebabkan correlation screen menampilkan pair yang kemudian bergerak menjauh satu sama lain.

Bagaimana cara menghitung hedge ratio dalam pairs trading?

Sesuaikan garis lurus antara harga satu saham dan harga saham lainnya, lalu gunakan kemiringannya. Kemiringan tersebut menunjukkan jumlah unit saham pertama yang mengimbangi satu unit saham kedua. Nilainya berubah dari waktu ke waktu. Karena itu, sebagian besar implementasi menghitung ulang hedge ratio pada trailing window, bukan sekali untuk seluruh sample.

Z score berapa yang digunakan pairs trader untuk entry dan exit?

Contoh dalam tutorial biasanya melakukan entry ketika jarak mencapai sekitar 1,5 hingga 2 standard deviation dari trailing mean, lalu exit di sekitar 0,5. Angka tersebut merupakan konvensi dari tulisan-tulisan sebelumnya, bukan angka optimum yang diukur. Mengubahnya akan mengubah jumlah trade dan lamanya setiap posisi dipertahankan.

Apakah dua saham dapat terkointegrasi dengan korelasi rendah?

Ya. Korelasi dihitung berdasarkan perubahan harian, sedangkan kointegrasi dihitung berdasarkan level gap. Karena itu, dua saham yang pergerakan hariannya jarang searah tetap dapat mempertahankan jarak jangka panjang yang stabil. Hal sebaliknya juga dapat terjadi: korelasi harian tinggi, tetapi gap melebar dari tahun ke tahun.

Mengapa pair yang terkointegrasi berhenti bekerja?

Hubungan yang menjaga gap tetap stabil dapat berubah. Penyebabnya dapat berupa merger, spin-off, perubahan komposisi bisnis salah satu perusahaan, atau perubahan indeks yang mengubah pihak-pihak yang memiliki saham tersebut. Statistik pada hari-hari sebelum break terlihat sama dengan statistik sebelum reversion biasa. Karena itu, risikonya perlu dikelola melalui position sizing, bukan diprediksi.


Setiap panel di sini dilengkapi SQL yang digunakan secara persis, sehingga window, periode fit, dan batas bucket semuanya terlihat. Untuk menjalankan spread dan z score yang sama pada pair yang Anda ikuti, ajukan pertanyaan dalam bahasa sehari-hari di terminal Strasmore.

#pairs trading#cointegration#mean reversion#backtesting#statistics