Strasmore Research
İncelemeler Matt ConnorYazan Matt Connor

Pairs Trading ve Eşbütünleşme Analizi Nasıl Yapılır

Pairs trading stratejisinde eşbütünleşme ve korelasyon farklarını inceleyin. Hedge ratio, spread ve z-score hesaplamalarını gerçek hisse kapanış verileriyle adım adım öğrenin.

Pairs trading ve eşbütünleşme (cointegration) bir bütündür: İşlem, iki hisse senedi fiyatı arasındaki farkın istikrarlı bir seviyeye geri dönme eğilimine dayanır; eşbütünleşme ise bu farkın varlığını kanıtlayan istatistiksel özelliktir. Korelasyon ise farklı bir durumu ölçer. İki hisse senedi yüksek korelasyona sahip olsa dahi birbirinden sonsuza dek uzaklaşabilir; günlük hareketleri birbirine pek uymayan iki hisse senedi ise yıllarca sabit bir farkı koruyabilir. Bu sayfa, hedge ratio, spread ve z-score değerlerini manuel olarak oluşturur, her üçünü de gerçek kapanış fiyatları üzerinden ölçer ve ardından bu kurgunun hangi durumlarda başarısız olduğuna eşit ağırlıkta yer verir.

Pairs trading'de eşbütünleşme (cointegration) nedir?

Korelasyon, iki hissenin günlük yüzde değişimlerinin birbirine yakınlığını ifade eder. -1 ile +1 arasında değer alır; +1 değeri, örneklemdeki her seansta iki hissenin birlikte yükselip düştüğü anlamına gelir. Bu değer, iki fiyat arasındaki mesafe hakkında hiçbir bilgi vermez.

Eşbütünleşme ise bu mesafe ile ilgili bir durumdur. B hissesini alın, A hissesinin sabit bir katını çıkarın ve geriye kalana bakın. Eğer bu kalan seri, yani spread, uzaklaşıp gitmek yerine belirli bir aralıkta kalıyorsa, bu iki isim eşbütünleşiktir. Fiyatların kendileri her yöne gidebilir ancak kombinasyonları gidemez.

Ders kitaplarında kullanılan klasik benzetme, tasmalı bir köpektir. Yürüyüşçü ve köpek sokakta öngörülemez yollar izler ancak tasma, aralarındaki mesafenin sınırlı kalmasını sağlar. Korelasyon, ikisinin aynı anda adım atıp atmadığını sorgular. Eşbütünleşme ise tasmanın kopup kopmadığını sorgular.

Aşağıdaki panel, 2024 ve 2025 yılları boyunca beş tanıdık çift üzerinde ilk fikri ölçmektedir. return_corr sütunu, insanların genellikle bu kelimeyle kastettiği günlük yüzde değişim korelasyonudur. price_corr sütunu ise ham kapanış fiyatlarının korelasyonudur; bu sayı, her ikisi de yükselen neredeyse tüm hisse çiftleri için yanıltıcı derecede yüksek bir sonuç verir.

SorgulaGünlük getiri korelasyonu ve fiyat seviyesi korelasyonu karşılaştırması, beş tanıdık çift (2024-2025)
Her verinin arkasındaki tam SQL
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

Günlük değişim korelasyonuna göre sıralandığında, HD / LOW panelin en üstünde 0.868 değeriyle yer alırken, aynı dönemde iki fiyat seviyesinin korelasyonu 0.849 olarak ölçülmüştür. En alt satırda ise AAPL / MSFT, 0.479 getiri korelasyonuna karşılık 0.508 fiyat korelasyonuna sahiptir. Her iki sütun da bir pairs trader'ın sorduğu soruya yanıt vermez. İkisi de eş yönlü hareketi ölçer, oysa yapılan işlem bir mesafe ölçümü gerektirir.

Hedge oranı ve spread nasıl hesaplanır?

Kapanış fiyatlarından oluşan iki liste üzerinde, sırasıyla beş adım. math dışında hiçbir paket, veri sağlayıcı veya ağ bağlantısı gerektirmeyen yalın Python kodu tüm süreci kapsar.

  1. Her seriyi merkezleyin. mean_a = sum(a) / len(a) ve aynı işlem b listesi için uygulanır.
  2. Hedge oranını belirleyin. Bu, B'nin A'ya karşı çizilen düz bir doğrunun eğimidir: 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). Bu değer, bir birim B'yi dengeleyen A birim sayısı olarak okunur.
  3. Spread'i oluşturun. spread = [b[i] - beta * a[i] for i in range(len(a))]. Eşbütünleşik bir çiftte bu seri, trend oluşturmak yerine belirli bir seviye etrafında hareket eder.
  4. Hareketli bir pencere kullanın. w = spread[i - win + 1 : i + 1] ile pencere ortalaması mu = sum(w) / len(w), örneklem standart sapması ise sd = math.sqrt(sum((x - mu) ** 2 for x in w) / (len(w) - 1)) olur. Hareketli ifadesi, pencerenin değerlendirilen günde bittiğini ve sonrasındaki verileri içermediğini belirtir.
  5. Puanlayın ve yazdırın. z = (spread[i] - mu) / sd, ardından abs(z) > 1.5 olduğunda bir giriş satırı, abs(z) < 0.5 olduğunda ise bir çıkış satırı yazdırılır. İki z değeri, spread'in kendi yakın dönem ortalamasının iki standart sapma üzerinde olduğunu gösterir.

Süreci izlemek için iki adet sabit fiyat listesi yeterlidir ve beş birimlik bir win, örnek uygulamanın okunabilir kalmasını sağlar. Ciddi çalışmalarda, yaklaşık bir çeyreğe denk gelen altmış üç seanslık bir süre kullanılır. Giriş için bir buçuk, çıkış için sıfır virgül beş olan bu eşikler, bir eğitimden diğerine aktarılan geleneksel değerlerdir. Bunlar birer bulgu değildir ve aşağıdaki panellerde yer alan hiçbir veri bu değerleri seçmemiştir.

Gerçek fiyatlar üzerinde pairs trading z-skoru nasıl görünür?

Aynı hesaplamayı iki hanehalkı içecek markası olan KO ve PEP üzerinde uygulayalım. Hedge oranı yalnızca 2023 kapanış verilerinden elde edilmiş olup, grafiğin kapsadığı 2024 ve 2025 yılları boyunca sabit tutulmuştur. Eğimi, skorlama yapacağınız örneklem üzerinde hesaplamak backtesting'de ileriye dönük önyargı (look-ahead bias) yaratır; uyum penceresi ile skorlama penceresini ayrı tutmak buna karşı alınabilecek en basit önlemdir.

SorgulaKO/PEP spread'inin haftalık z skoru, 2023 verisiyle uyarlanmış hedge oranı
Her verinin arkasındaki tam SQL
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

İzleme grafiği 105 haftalık okuma içerir. Pencereyi -1.53 z-skorunda açar ve -0.68 seviyesinde kapatır. Tek bir noktadan ziyade genel şekli okuyun. Stratejinin varsaydığı şekilde hareket eden bir çift, eşiğini geçer, birkaç hafta boyunca sıfıra dönmek için çaba sarf eder ve tekrar kesişir. Ortalama dönüşü (mean reversion) durmuş bir çift ise eşiğin ötesinde park eder ve orada kalır; bu durum grafikte orta çizgiden uzak, uzun ve düz bir hat olarak görünür.

Kointegre bir spread her zaman geri döner mi?

Hayır; bunu görmenin en dürüst yolu, her başlangıç noktasından sonra neyin gerçekleştiğini ölçmektir. Aşağıdaki panel, iki bin on dokuzdan iki bin yirmi beşin sonlarına kadar olan her seansı o günün z-skoruna göre gruplandırır ve ardından aynı spread’in yirmi seans sonraki ortalama z-skorunu raporlar. Regresyon sonrası tahminlerin grafiği etkilememesi için, uyarlanmış bir spread yerine fiyat oranının logaritması kullanılır.

SorgulaBaşlangıç z skoruna göre yirmi seans sonrası KO/PEP spread durumu (2019-2025)
Her verinin arkasındaki tam SQL
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

z below -2 grubunda başlayan seanslar gün içinde ortalama -2.42 değerini almış, aynı spread yirmi seans sonra 138 adet seans genelinde ortalama -0.84 seviyesinde gerçekleşmiştir. Diğer uçta ise z above 2 grubu 2.64 seviyesinden başlamış ve yirmi seans sonra 0.92 olarak ölçülmüştür. Her iki uçtan sıfıra doğru çekilen bir eğri, ortalamaya dönüşün (mean reversion) oluşturduğu şekildir.

Bunu, seans sayısı sütununu dikkate alarak okuyun. Dış gruplar en az sayıda seansı içerir ve bir grup içindeki seanslar büyük ölçüde örtüşür; bu nedenle satırların çoğunu az sayıda uzun dönem oluşturur. Bir ortalama, herhangi bir tekil giriş için bir vaat teşkil etmez.

Pairs trading neden işlevini yitirir?

Hedge oranı sabit değildir. Her takvim yılında yeniden hesaplandığında değişir.

SorgulaHer takvim yılı için yeniden hesaplanan hedge oranı, iki sektör çifti
Her verinin arkasındaki tam SQL
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

PEP'in KO üzerindeki eğimi 2.338 döneminde 2019, -0.543 döneminde ise 2025 olarak ölçülmüştür; karşılaştırma için ikinci sektör çifti de yanına eklenmiştir. Tüm geçmişi kapsayan tek bir eğim belirleyen ve bunu ilk günden itibaren işleme koyan bir geriye dönük test (backtest), o dönemde kimsenin elinde tutamayacağı bir rakamı her erken işleme atfeder. Çözüm sıkıcı ancak etkilidir: Hareketli bir pencere üzerinde yeniden hesaplama yapın ve her günü, o gün mevcut olan parametrelerle puanlayın. Tekrarlanabilir bir backtest, bu disiplinin başkaları tarafından denetlenebilmesini sağlar.

Kurumsal aksiyonlar bir bacağı bir gecede yeniden yazar. Dört-bir oranındaki bir bölünme, bir hisseyi dörde böler ve fiyatı dörtte birine indirir; düzeltilmemiş fiyatlar üzerinden o tarih boyunca hesaplanan bir spread, hiç gerçekleşmemiş bir seviyeye sıçrar. Birleşmeler, bölünmeler (spin-off) ve endeks değişiklikleri bunun daha sessiz versiyonlarını gerçekleştirir. Bölünme düzeltmeli fiyat geçmişi ile başlayın ve bir ticker sembolünün tamamen farklı bir şirkete atanabileceğini unutmayın; ticker sembollerinin veri setlerini bozmasının nedeni budur.

Bir kırılma ile bir fırsat, gerçekleştiği sırada aynı görünür. Bir çiftin bugüne kadar verdiği en geniş z-skoru, ya sunduğu en iyi giriş noktasıdır ya da sona ermiş bir ilişkinin ilk haftasıdır. Her ikisi de o gün, genişlemiş bir spread gibi görünür. Pozisyon büyüklüğü, istatistiklerin taşıyamadığı yükü üstlenir: Kelly kriteri ile pozisyon büyüklüğü ve volatilite hedefli pozisyon büyüklüğü, bir spread'in hesapta ne kadar yer kaplayacağına dair iki çerçevedir; maksimum düşüş (drawdown) ise ortalamanın yanlış tarafında uzun süre kalmanın öz sermaye eğrisine etkisini ölçer.

Hareketli z-skoru bir eşbütünleşme (cointegration) testi değildir. Resmi testler mevcuttur. Engle-Granger prosedürü regresyonu çalıştırır, ardından kalan spread'in durağanlığını test eder; Johansen testi ise bu fikri iki ismin ötesine taşır. Z-skoru, bu testlerin kontrol ettiği özelliği varsayar ve trend gösteren bir seri kendi hareketli ortalamasından her zaman uzak kalacağı için, sabit bir ortalaması olmayan bir spread üzerinde de rahatlıkla büyük bir rakam üretir.

Veri notları ve bu rakamların dışarıda bıraktıkları

Korelasyon paneli, 01-01-2024 ile 31-12-2025 arasındaki günlük kapanışları kullanır ve her ismin ilk seansını hariç tutarak ardışık kapanışlardan getirileri hesaplar. Z-skoru izi, hedge oranını yalnızca 2023 kapanışlarına göre belirler; ardından 2024 ve 2025 verilerini, her haftanın son okumasına göre örneklenmiş 63 seanslık hareketli ortalama ve örneklem standart sapması ile puanlar. Geri dönüş paneli 2018'den itibaren geçmişi yükler ve 2019'dan itibaren raporlama yapar; böylece puanlanan her günün arkasında tam bir hareketli pencere bulunur. Kasım 2025 ortasında durur, böylece her günün örneklem içinde önünde yirmi seanslık bir alan kalır.

Bu panellerin hiçbiri bir strateji değildir. İşlem maliyetleri, bid-ask spread, kısa bacakta ödünç alma ücreti, temettüler veya finansman maliyetleri içermezler. Yalnızca kapanış fiyatları baz alınmıştır; bu da kapanışta işaretlenen bir girişin, kimsenin o seviyeden gerçekleştiremeyeceği bir giriş olduğu anlamına gelir.

Sıkça Sorulan Sorular

Korelasyon ve eşbütünleşme (cointegration) arasındaki fark nedir?

Korelasyon, iki hissenin aynı günlerde ve aynı yönde hareket edip etmediğini eksi bir ile artı bir ölçeğinde ölçer. Eşbütünleşme ise fiyatları arasındaki mesafenin istikrarlı bir aralıkta kalıp kalmadığını ölçer. Bir çift, ilkinde yüksek puan alıp ikincisinde başarısız olabilir; korelasyon taramalarının birbirinden uzaklaşan çiftleri getirmesinin yaygın nedeni budur.

Çift ticaretinde (pairs trading) hedge oranı nasıl hesaplanır?

Bir hissenin fiyatını diğerine göre doğrusal bir regresyona tabi tutun ve eğimi alın. Bu eğim, ikinci hissenin bir birimini dengelemek için gereken ilk hisse birimi sayısıdır. Bu değişken bir değer olduğundan, çoğu uygulama bunu tüm örneklem üzerinde tek seferde hesaplamak yerine hareketli bir pencere üzerinde yeniden hesaplar.

Çift ticareti yapanlar giriş ve çıkış için hangi z-skorunu kullanır?

Eğitim örneklerinde genellikle hareketli ortalamadan bir buçuk ila iki standart sapma uzaklıkta giriş yapılır ve sıfır virgül beş civarında çıkış yapılır. Bu sayılar ölçülmüş optimum değerlerden ziyade önceki çalışmalardan devralınan geleneklerdir; bu değerleri değiştirmek hem işlem sayısını hem de her bir işlemin elde tutulma süresini değiştirir.

İki hisse düşük korelasyonla eşbütünleşik olabilir mi?

Evet. Korelasyon günlük değişimler üzerinden, eşbütünleşme ise fiyat farkının seviyesi üzerinden hesaplanır. Bu nedenle günlük hareketleri nadiren örtüşen iki isim, uzun vadede istikrarlı bir mesafe koruyabilir. Bunun tersi de gerçekleşir: Yıllar geçtikçe genişleyen bir fiyat farkına rağmen yüksek günlük korelasyon görülebilir.

Eşbütünleşik bir çift neden çalışmayı durdurur?

Fiyat farkını bir arada tutan bağ değişebilir: Bir birleşme, bölünme (spin-off), şirketlerden birinin iş karmasındaki bir değişim veya hissenin sahiplik yapısını değiştiren bir endeks değişikliği buna neden olabilir. Kırılmadan önceki günlerdeki istatistikler, sıradan bir ortalamaya dönüşten önceki günlerle aynı görünür; bu durum tahmin edilmek yerine pozisyon büyüklüğü ayarlanarak yönetilmesi gereken kısımdır.


Buradaki her panel, altında yer alan SQL sorgusuyla birlikte sunulmaktadır; böylece pencereler, uyum dönemi ve aralık sınırlarının tümü görülebilir. Takip ettiğiniz bir çift üzerinde aynı spread ve z-skorunu çalıştırmak için Strasmore terminalinde sorunuzu yalın bir dille iletmeniz yeterlidir.

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