P.Thai Capital P.Thai Capital Journal

Pairs Trading & Cointegration: Statistical Arbitrage cho TTCK VN

QUANT STRATEGY · STATISTICAL ARBITRAGE Giao dịch cặp — Đồng tích hợp Pairs Trading (Cointegration) Họ chiến lược Statistical Arbitrage Khung phân tích Định lượng / Backtest Áp dụng cho VN30 / VN30F1M

Pairs trading là chiến lược market-neutral kinh điển: chọn 2 cổ phiếu có quan hệ kinh tế chặt (cùng ngành, cùng chuỗi cung ứng), kỳ vọng spread giữa 2 mã sẽ mean-revert. Khi spread lệch xa khỏi giá trị cân bằng → long mã underperform, short mã outperform → thoát khi spread quay về.

Phiên bản đầu tiên do nhóm Morgan Stanley (Bamberger, Tartaglia) phát triển thập niên 1980, sau đó được mainstream hoá bởi Vidyamurthy (2004). Phiên bản nghiêm túc dùng cointegration test (Engle-Granger hoặc Johansen) thay vì correlation đơn giản — vì 2 chuỗi có thể correlated cao trong ngắn hạn nhưng diverge dài hạn.

1. Định nghĩa & cơ sở lý thuyết

Cointegration Engle-Granger 2-step:

Step 1: hồi quy $P_{A,t} = \alpha + \beta P_{B,t} + \varepsilon_t$ → spread $\varepsilon_t$.

Step 2: ADF test trên $\varepsilon_t$ — bác bỏ $H_0$ unit root (p < 0.05) → cặp cointegrated.

Z-score chuẩn hoá: $$ z_t = \frac{\varepsilon_t - \mu_\varepsilon}{\sigma_\varepsilon} $$

Half-life mean reversion (Ornstein-Uhlenbeck): $$ h = -\frac{\ln 2}{\lambda}, \quad \lambda \text{ từ AR(1) trên } \Delta\varepsilon_t $$

Half-life càng ngắn → spread mean-revert càng nhanh → cặp càng “tradable”.

Trong đó:

2. Pseudocode triển khai

from statsmodels.tsa.stattools import coint, adfuller
from statsmodels.regression.linear_model import OLS

def find_cointegrated_pairs(prices_df, p_threshold=0.05):
    """
    prices_df: DataFrame giá đóng cửa, columns = mã.
    Trả về list các cặp cointegrated.
    """
    n = prices_df.shape[1]
    pairs = []
    for i in range(n):
        for j in range(i+1, n):
            s1, s2 = prices_df.iloc[:, i], prices_df.iloc[:, j]
            _, pval, _ = coint(s1, s2)
            if pval < p_threshold:
                pairs.append((s1.name, s2.name, pval))
        return pairs

def pairs_signal(p1, p2, entry_z=2.0, exit_z=0.5, lookback=60):
    """Tín hiệu pairs trading: long spread khi z < -entry, short khi z > entry."""
    beta = OLS(p1, p2).fit().params[0]
    spread = p1 - beta * p2
    mu = spread.rolling(lookback).mean()
    sd = spread.rolling(lookback).std()
    z = (spread - mu) / sd

    sig = pd.Series(0, index=z.index)
    sig[z > entry_z]  = -1   # short spread (short p1, long p2)
    sig[z < -entry_z] = +1   # long spread (long p1, short p2)
    sig[z.abs() < exit_z] = 0
    return sig, beta

Code mẫu trên là khung tham khảo — triển khai production cần thêm: validate input, handle NaN, log signal, hook vào execution engine (REST API qua TCBS/SSI/Vndirect), và unit test cho từng nhánh logic.

3. Tham số & khoảng walk-forward

Tham số Mặc định Khoảng walk-forward Ghi chú
Cointegration p-value 0.05 0.01 – 0.10 Càng thấp càng strict
Lookback z-score 60 phiên 30 – 120 Dùng để chuẩn hoá spread
Entry z ±2.0 1.5 – 3.0 Cao hơn → ít trade, hit rate cao
Exit z ±0.5 0 – 1.0 Thoát quanh trung bình
Stop loss z ±4.0 3 – 5 Cắt khi cointegration phá vỡ

Lưu ý về walk-forward optimization: không nên fix tham số “tốt nhất” trên toàn bộ lịch sử. Quy trình chuẩn là rolling window — fit tham số trên 252 phiên gần nhất, áp dụng 63 phiên tiếp theo (tỷ lệ ~80/20), sau đó shift cửa sổ. Báo cáo distribution của Sharpe, max DD, Calmar trên các fold thay vì 1 con số tổng.

4. Đặc thù thị trường Việt Nam

Pairs trading trên VN cực kỳ khó vì hạn chế thể chế:

5. Năm cạm bẫy phổ biến khi áp dụng

  1. Spurious cointegration: Engle-Granger có thể false positive trong sample nhỏ. Dùng Johansen test hoặc bootstrap để confirm.

  2. Beta drift: β thay đổi theo thời gian. Static β = sai. Dùng Kalman filter hoặc rolling OLS.

  3. Crowded pair: nếu nhiều quỹ trade cùng pair, spread không mean-revert nữa (Khandani & Lo 2007).

  4. Stop loss khi cointegration phá vỡ: spread đi quá z = ±4 thường là dấu hiệu relationship vỡ. Cắt lỗ thay vì ‘double down’.

  5. Overfitting universe: data-mining 1000 cặp tìm cointegrated → false positive bias. Cần multiple-testing correction (Bonferroni).

6. Khi nào nên dùng — khi nào không

✅ Nên dùng khi

❌ Không nên dùng khi

7. Vị trí trong hệ thống chiến lược định lượng

Chiến lược “Giao dịch cặp — Đồng tích hợp” không hoạt động độc lập — trong portfolio định lượng đa chiến lược, nó được kết hợp với các chiến lược khác để tận dụng correlation thấp giữa các họ tín hiệu (mean reversion ↔ trend following thường có correlation âm trong giai đoạn sideway).

Các chiến lược liên quan đã trình bày trong chuỗi bài này:

8. Tham khảo học thuật


Ghi chú phương pháp: Bài viết tổng hợp khung định lượng trên cơ sở lý thuyết và quy ước cộng đồng quant. Các giả định về phí giao dịch, slippage, regime filter là giả định mô hình — kết quả backtest thực tế phụ thuộc dataset, universe, và cách xử lý survivorship bias. Người đọc tự kiểm chứng bằng dữ liệu của mình trước khi triển khai vốn thật.


Miễn trừ trách nhiệm: Nội dung mang tính phân tích định lượng, không phải khuyến nghị đầu tư. Nhà đầu tư tự chịu trách nhiệm với quyết định của mình.

Miễn trừ trách nhiệm: Nội dung là phân tích định lượng dựa trên dữ liệu lịch sử, mang tính tham khảo. KHÔNG phải khuyến nghị mua/bán. Giao dịch có rủi ro, kết quả backtest không đảm bảo hiệu suất tương lai. Nhà đầu tư tự chịu trách nhiệm cho quyết định của mình.
FAQ · Câu hỏi thường gặp

Câu hỏi đi sâu chủ đề này

Pairs Trading dựa trên cointegration nên được xem xét thận trọng trong những điều kiện thị trường nào của Việt Nam, và vì sao?

Chiến lược Pairs Trading dựa trên cointegration cần đặc biệt thận trọng khi thị trường Việt Nam rơi vào các xu hướng (trend) mạnh, đặc biệt là xu hướng tăng hoặc giảm liên tục của cả ngành hoặc nhóm ngành mà cặp cổ phiếu thuộc về. Khi đó, dù có mối quan hệ cointegration, spread có thể "break out" và diverge (phân kỳ) vĩnh viễn, hoặc rất lâu mới quay về, dẫn đến lỗ lớn. Ví dụ, nếu một cổ phiếu trong cặp có sự thay đổi cơ bản lớn (M&A, thay đổi chính sách ngành, lợi nhuận đột biến) mà cổ phiếu kia không có, cointegration sẽ bị phá vỡ. Ngoài ra, thị trường có thanh khoản thấp (như một số mã trên HNX/UPCOM) cũng không phù hợp, bởi việc thực thi long/short sẽ gặp slippage lớn, ảnh hưởng nặng nề đến lợi nhuận. Tóm lại, không nên áp dụng khi thị trường biến động mạnh theo xu hướng, có thông tin cơ bản bất thường hoặc thanh khoản kém.

Việc xác định một cặp cổ phiếu "cointegrated" khác gì so với việc chỉ đơn thuần tìm kiếm các cặp có "tương quan cao" (high correlation) trên thị trường chứng khoán Việt Nam?

Đây là điểm khác biệt cốt lõi mà nhà đầu tư định lượng cần nắm rõ. Tương quan cao (ví dụ, hệ số Pearson > 0.9) chỉ cho biết hai chuỗi giá di chuyển cùng chiều với nhau trong một khoảng thời gian nhất định. Tuy nhiên, hai chuỗi có thể tương quan cao nhưng vẫn "phân kỳ" vĩnh viễn trong dài hạn, nghĩa là spread giữa chúng không ổn định và không có xu hướng quay về giá trị cân bằng. Ngược lại, cointegration ngụ ý rằng tồn tại một sự kết hợp tuyến tính giữa hai chuỗi giá mà sự kết hợp đó là chuỗi dừng (stationary). Điều này có nghĩa là spread (phần dư $\varepsilon_t$ từ hồi quy $P_{A,t} = \alpha + \beta P_{B,t} + \varepsilon_t$) sẽ dao động quanh một giá trị trung bình và có xu hướng "mean-revert". Đối với chiến lược statistical arbitrage, khả năng mean-revert của spread là yếu tố then chốt, và đó là điều mà cointegration test (như ADF test trên spread) xác nhận, chứ không phải tương quan đơn thuần.

Với cơ chế T+2.5 và biên độ giao động ±7% của HOSE, những thách thức cụ thể nào nhà đầu tư định lượng cần lường trước khi thực thi lệnh giao dịch Pairs Trading?

Cơ chế T+2.5 và biên độ ±7% trên HOSE tạo ra các thách thức đáng kể. T+2.5 nghĩa là vị thế mua chỉ được bán sau 2.5 ngày giao dịch. Điều này làm tăng rủi ro nếu spread đảo chiều nhanh chóng, đặc biệt khi half-life mean reversion của cặp quá ngắn (ví dụ, dưới 5 ngày). Chúng ta có thể bị kẹt vị thế long một mã và short một mã (qua hợp đồng tương lai hoặc bán khống nếu có) trong khi spread đã quay đầu. Biên độ ±7% trên HOSE, hoặc ±10%/±15% trên HNX/UPCOM, có thể khiến spread biến động rất mạnh trong phiên. Điều này có thể đẩy z-score lên mức cực đoan (ví dụ, ±3.0) rồi đảo chiều nhanh chóng trước khi lệnh được khớp hoàn toàn hoặc trước khi nhà đầu tư kịp phản ứng. Cần có chiến lược đặt lệnh linh hoạt (như sử dụng lệnh limit order thông minh) và stop-loss chặt chẽ trên spread để quản lý rủi ro slippage và biến động giá cực đoan. Ví dụ, đặt cut-loss khi z-score vượt quá ±3.5 thay vì chỉ ±2.5.

Ngoài các cặp cổ phiếu trong VN30, liệu có tiềm năng nào để áp dụng chiến lược Pairs Trading trên các nhóm cổ phiếu khác trên sàn HOSE, HNX hay UPCOM không? Cần lưu ý gì khi mở rộng ra?

Có tiềm năng nhưng cũng đi kèm rủi ro cao hơn. Ngoài VN30, nhà đầu tư có thể tìm các cặp cointegrated trong các ngành cụ thể trên HOSE (mid-cap, small-cap) hoặc thậm chí trên HNX và UPCOM. Ví dụ, hai công ty cùng ngành bất động sản, công nghệ, hoặc vật liệu xây dựng có mô hình kinh doanh và yếu tố vĩ mô tương đồng. Tuy nhiên, khi mở rộng ra, vấn đề thanh khoản là yếu tố hàng đầu cần lưu ý. Nhiều cổ phiếu ngoài VN30 trên HOSE, và phần lớn trên HNX/UPCOM, có thanh khoản rất thấp (khối lượng giao dịch bình quân dưới 100.000 cổ phiếu/phiên). Thanh khoản kém sẽ dẫn đến slippage lớn khi khớp lệnh, làm giảm đáng kể lợi nhuận của chiến lược statistical arbitrage vốn dựa trên biên lợi nhuận nhỏ. Biên độ giao dịch lớn hơn trên HNX (±10%) và UPCOM (±15%) cũng làm tăng rủi ro biến động spread, đòi hỏi quản lý vị thế và stop-loss chặt chẽ hơn.