← Quay lại danh sách bài viết
July 12, 2026
5 phút đọc

DCC-GARCH: Tương quan động cho giao dịch cặp và rủi ro danh mục

#volatility
#GARCH
#DCC
#correlation
#portfolio
#pairs-trading
#crypto

Hỏi hầu hết các bàn giao dịch crypto về mức tương quan giữa BTC và ETH và bạn sẽ nhận được một con số duy nhất — 0.8, có thể là 0.75 — được tính trên một cửa sổ nào đó mà chẳng ai nhớ đã chọn thế nào. Con số đó là một lời nói dối, hoặc ít nhất là một sự đơn giản hóa nguy hiểm. Tương quan mẫu là một giá trị trung bình trên một giai đoạn mà trong đó cấu trúc phụ thuộc thực sự liên tục biến động. Trong thị trường yên bình, BTC và ETH tách xa nhau đủ để một cặp trung lập với thị trường trông có vẻ hấp dẫn. Trong một chuỗi thanh lý dây chuyền, chúng khóa chặt vào nhau và vào tất cả mọi thứ khác, và sự đa dạng hóa mà bạn đã trả tiền để có bốc hơi đúng vào khoảnh khắc bạn cần nó nhất.

Đây không phải là một hiệu ứng tinh tế. Lấy bất kỳ đợt sụt giảm nào của năm 2022 — cú sụp đổ LUNA vào tháng Năm, đợt tháo chạy 3AC vào tháng Sáu, sự sụp đổ FTX vào tháng Mười một — và bạn sẽ thấy tương quan trung bình theo cặp trên top 20 token tiến từ vùng 0.4-0.6 về phía 0.9+ chỉ trong vài ngày. Tương quan không phải là một hằng số thỉnh thoảng bị ước lượng sai; nó là một chuỗi thời gian với động học riêng, hiện tượng cụm riêng và các chế độ riêng của nó. Coi nó như một đại lượng vô hướng là tương đương đa biến của việc giả định độ biến động cố định — một sai lầm mà chúng ta đã dành Phần 1 của loạt bài này để tháo dỡ đối với một tài sản đơn lẻ.

Bài viết này là Phần 3 của một loạt bốn phần về độ biến động. Phần 1 xây dựng GARCH(1,1) đơn biến với thư viện arch và cho thấy độ biến động phân cụm và hồi quy về trung bình như thế nào. Phần 2 thêm tính bất đối xứng (GJR-GARCH, EGARCH) và các đổi mới Student-t để nắm bắt hiệu ứng đòn bẩy và đuôi béo. Ở đây chúng ta chuyển sang đa biến: chúng ta mô hình hóa toàn bộ ma trận hiệp phương sai có điều kiện HtH_t khi nó tiến hóa, sử dụng mô hình Tương quan Có điều kiện Động (DCC) của Engle. Điều đó mang lại cho chúng ta hai thứ mà một tương quan vô hướng không bao giờ có thể — một tỷ lệ phòng ngừa động cho giao dịch cặp, và một phương sai danh mục biến đổi theo thời gian một cách trung thực cho phân bổ dựa trên rủi ro. Phần 4 khép lại loạt bài với một backtest nhắm mục tiêu độ biến động, gắn kết các dự báo đơn biến và đa biến vào một quy tắc định cỡ vị thế.

Chúng tôi giả định bạn đã đọc Phần 1 và 2, nên chúng tôi sẽ không suy diễn lại GARCH đơn biến. Nếu bạn muốn hành vi đuôi chung — xác suất hai tài sản cùng vượt qua phân vị 1% của chúng — đó là một câu hỏi copula, và chúng tôi bàn về nó trong Mô hình Copula cho rủi ro chung. DCC và copula bổ sung cho nhau: copula cung cấp cho bạn một cấu trúc phụ thuộc đuôi tĩnh-nhưng-linh-hoạt, trong khi DCC cung cấp cho bạn một chuỗi thời gian dễ xử lý của toàn bộ ma trận tương quan. Bài viết này nói về cái sau.

Vì sao tương quan tĩnh thất bại trong crypto

Trước khi đi vào bộ máy, hãy chính xác về điều gì thất bại. Một tương quan mẫu đơn lẻ ρ^\hat{\rho} trên một cửa sổ [tw,t][t-w, t] ước lượng

ρ^ij=s(ri,srˉi)(rj,srˉj)s(ri,srˉi)2s(rj,srˉj)2\hat{\rho}_{ij} = \frac{\sum_{s} (r_{i,s} - \bar{r}_i)(r_{j,s} - \bar{r}_j)}{\sqrt{\sum_s (r_{i,s}-\bar{r}_i)^2}\sqrt{\sum_s (r_{j,s}-\bar{r}_j)^2}}

Điều này mang theo ba giả định ngầm, tất cả đều sai đối với crypto:

  1. Tính dừng của sự phụ thuộc. Cửa sổ có một ρ\rho thực duy nhất. Trong thực tế, sự phụ thuộc có các chế độ — một chế độ thị trường yên tĩnh gần 0.5 và một chế độ căng thẳng gần 0.95 — và ρ^\hat{\rho} trộn chúng thành một giá trị ở giữa vô nghĩa.
  2. Độ biến động biên cố định. Tương quan Pearson là một hiệp phương sai chuẩn hóa. Nếu bản thân σi,t\sigma_{i,t}σj,t\sigma_{j,t} đang biến động (chúng có — đó là toàn bộ tiền đề của Phần 1 và 2), thì ngay cả một hiệp phương sai cố định cũng tạo ra một tương quan biến đổi theo thời gian, và ngược lại. Bạn không thể tách hai thứ này nếu không có một mô hình độ biến động bên dưới.
  3. Đối xứng theo hướng thị trường. Tương quan tăng trong các đợt sụt giảm nhiều hơn trong các đợt tăng giá. Đây là người anh em đa biến của hiệu ứng đòn bẩy. Một cửa sổ trượt không thể biểu đạt điều này mà không trở nên ngắn đến mức chỉ còn là nhiễu thuần túy.

Cách khắc phục bằng cửa sổ trượt — tính lại ρ^\hat{\rho} trên 30 hoặc 60 ngày gần nhất — đánh đổi vấn đề này lấy vấn đề khác. Cửa sổ ngắn thì phản ứng nhanh nhưng nhiễu và trễ so với điểm gãy thực tế; cửa sổ dài thì ổn định nhưng cũ. Tệ hơn, một ma trận tương quan trượt trên dd tài sản không được đảm bảo giữ tính nửa xác định dương một khi bạn bắt đầu thu nhỏ hoặc vá nó, điều này phá vỡ mọi bộ tối ưu hóa phía sau. Chúng ta muốn một mô hình mà (a) được điều khiển bởi một quá trình độ biến động đúng đắn cho mỗi tài sản, (b) tạo ra một ma trận tương quan hợp lệ ở mỗi bước theo cấu trúc, và (c) có các tham số mà chúng ta có thể ước lượng bằng hợp lý cực đại thay vì bằng cách chọn một độ dài cửa sổ tùy tiện. Mô hình đó là DCC-GARCH.

Vấn đề đa biến: Ma trận hiệp phương sai có điều kiện

Gọi rtRdr_t \in \mathbb{R}^d là vector lợi suất cho dd tài sản tại thời điểm tt, với trung bình có điều kiện μt\mu_t (thường chỉ là một hằng số hoặc một số hạng AR nhỏ) và phần dư ϵt=rtμt\epsilon_t = r_t - \mu_t. Chúng ta giả định

ϵtFt1D(0,Ht)\epsilon_t \mid \mathcal{F}_{t-1} \sim \mathcal{D}(0, H_t)

trong đó HtH_tma trận hiệp phương sai có điều kiện d×dd \times d cho trước tập thông tin Ft1\mathcal{F}_{t-1}, và D\mathcal{D} là một phân phối có điều kiện nào đó (Gaussian hoặc, tốt hơn cho crypto, Student-t đa biến). Mọi thứ trong mô hình hóa độ biến động đa biến là một câu trả lời khác nhau cho một câu hỏi: bạn tham số hóa động học của HtH_t như thế nào để nó giữ tính đối xứng xác định dương ở mỗi bước mà không có sự bùng nổ tham số?

Hai câu trả lời cổ điển cho thấy vì sao vấn đề này khó.

VECH

Mô hình VECH (Bollerslev, Engle, Wooldridge 1988) viết nửa-vector-hóa của HtH_t như một hàm tuyến tính của các phần dư bình phương quá khứ và các hiệp phương sai quá khứ:

vech(Ht)=c+Avech(ϵt1ϵt1)+Bvech(Ht1)\mathrm{vech}(H_t) = c + A\,\mathrm{vech}(\epsilon_{t-1}\epsilon_{t-1}') + B\,\mathrm{vech}(H_{t-1})

trong đó vech()\mathrm{vech}(\cdot) xếp chồng tam giác dưới của một ma trận đối xứng thành một vector có độ dài d(d+1)/2d(d+1)/2. Điều này tổng quát tối đa — mọi phương sai và hiệp phương sai phụ thuộc vào mọi phương sai và hiệp phương sai quá khứ — và vô dụng tối đa khi vượt quá d=3d=3. Với dd tài sản, mỗi ma trận AABB có kích thước d(d+1)2×d(d+1)2\frac{d(d+1)}{2} \times \frac{d(d+1)}{2}. Ở d=5d=5, đó là hai ma trận 15×1515\times 15, khoảng 450 tham số, cộng với các ràng buộc xác định dương mà thậm chí việc biểu đạt cũng đau đầu. Bề mặt hợp lý là một đầm lầy.

BEKK

Mô hình BEKK (Engle & Kroner 1995) đảm bảo tính xác định dương theo cấu trúc bằng cách sử dụng một dạng toàn phương:

Ht=CC+Aϵt1ϵt1A+BHt1BH_t = C'C + A'\,\epsilon_{t-1}\epsilon_{t-1}'\,A + B'\,H_{t-1}\,B

với CC là tam giác trên. Vì mọi số hạng đều là một dạng toàn phương, Ht0H_t \succ 0 tự động miễn là CC0C'C \succ 0. BEKK tiết kiệm tham số hơn VECH nhưng vẫn co giãn theo O(d2)O(d^2) tham số — các ma trận AABB mỗi cái là d×dd \times d. Với d=10d=10, bạn đang ước lượng cỡ 200+ tham số cùng lúc bằng MLE, trên dữ liệu crypto hàng ngày đầy nhiễu, mà không có gì đảm bảo bộ tối ưu hóa hội tụ về bất cứ điều gì có ý nghĩa. Trong thực tế, BEKK đầy đủ bị giới hạn ở d4d \le 4, và ngay cả khi đó người ta cũng sử dụng các ràng buộc "đường chéo" hoặc "vô hướng" vốn vứt bỏ hầu hết động học chéo.

Đây là lời nguyền chiều đối với GARCH đa biến: số lượng tham số tăng theo bậc hai, nhưng lượng thông tin trong dữ liệu thì không. Bạn cạn kiệt bậc tự do trước khi bạn cạn kiệt các tài sản mà bạn quan tâm. Bất kỳ sổ crypto nào với 10-30 token đều hoàn toàn nằm ngoài tầm với của VECH hoặc BEKK.

Lối thoát, nhờ Engle, là ngừng cố gắng mô hình hóa HtH_t trực tiếp và thay vào đó phân tích nó thành thừa số thành các phần mà chúng ta đã biết cách ước lượng một cách rẻ tiền.

DCC của Engle (2002): Phân rã hai bước

Mô hình Tương quan Có điều kiện Cố định (CCC) của Bollerslev (1990) là phép phân tích thừa số tiết kiệm tham số đầu tiên. Nó viết

Ht=DtRDtH_t = D_t\, R\, D_t

trong đó Dt=diag(σ1,t,,σd,t)D_t = \mathrm{diag}(\sigma_{1,t}, \ldots, \sigma_{d,t}) là ma trận đường chéo của các độ lệch chuẩn có điều kiện — một GARCH đơn biến cho mỗi tài sản — và RR là một ma trận tương quan cố định. Đây là một sự đơn giản hóa lớn: bạn khớp dd mô hình GARCH đơn biến độc lập, rồi ước lượng một ma trận tương quan mẫu duy nhất của các phần dư chuẩn hóa. Tính xác định dương là tự động miễn là RR là một ma trận tương quan hợp lệ và tất cả σi,t>0\sigma_{i,t} > 0.

Vấn đề của CCC nằm ngay trong tên gọi của nó — tương quan là cố định, đó chính xác là giả định mà chúng ta đã bác bỏ ngay khi mở đầu bài viết này. Tương quan Có điều kiện Động của Engle (2002) giữ nguyên phép phân tích thừa số tuyệt đẹp của CCC nhưng cho phép ma trận tương quan "hít thở":

Ht=DtRtDtH_t = D_t\, R_t\, D_t

Bây giờ RtR_t biến đổi theo thời gian. Điểm thiên tài là các độ biến động và các tương quan được ước lượng trong hai bước riêng biệt, nên chúng ta không bao giờ phải đối mặt với bài toán tối ưu hóa chung O(d2)O(d^2) đầy đủ.

Bước 1: GARCH đơn biến cho mỗi tài sản

Với mỗi tài sản ii, khớp một mô hình GARCH đơn biến chính xác như trong Phần 1 và 2 — GARCH(1,1), GJR-GARCH, hoặc EGARCH với các đổi mới Student-t, tùy cái nào khớp tốt nhất cho chuỗi đó. Điều này cho các phương sai có điều kiện σi,t2\sigma_{i,t}^2 và do đó Dt=diag(σ1,t,,σd,t)D_t = \mathrm{diag}(\sigma_{1,t}, \ldots, \sigma_{d,t}).

Từ các mô hình đã khớp, chúng ta trích xuất các phần dư chuẩn hóa:

zi,t=ϵi,tσi,tz_{i,t} = \frac{\epsilon_{i,t}}{\sigma_{i,t}}

Theo cấu trúc, mỗi zi,tz_{i,t} có phương sai có điều kiện (xấp xỉ) bằng đơn vị. Xếp chồng chúng thành một vector zt=(z1,t,,zd,t)z_t = (z_{1,t}, \ldots, z_{d,t})'. Các phần dư chuẩn hóa này là nguyên liệu thô cho bước tương quan — chúng đã bị lột bỏ động học độ biến động riêng lẻ, nên bất kỳ đồng chuyển động nào còn lại đều là sự phụ thuộc thuần túy, không phải một hiện tượng nhân tạo của độ biến động. (Đây cũng chính là logic kiểu PIT mà bài viết về copula sử dụng trước khi khớp các biên; ở đây chúng ta dừng ở chuẩn hóa thay vì đi hết đường tới phân phối đều.)

Bước 2: Đệ quy tương quan DCC

Chúng ta mô hình hóa một quá trình phụ trợ QtQ_t, một ma trận đối xứng xác định dương d×dd \times d, với một đệ quy kiểu GARCH được điều khiển bởi các tích ngoài của các phần dư chuẩn hóa:

Qt=(1ab)Qˉ+azt1zt1+bQt1Q_t = (1 - a - b)\,\bar{Q} + a\, z_{t-1} z_{t-1}' + b\, Q_{t-1}

trong đó:

  • Qˉ=1Tt=1Tztzt\bar{Q} = \frac{1}{T}\sum_{t=1}^{T} z_t z_t' là ma trận tương quan không điều kiện của các phần dư chuẩn hóa (đây là nhắm mục tiêu tương quan — sẽ nói thêm bên dưới),
  • a0a \ge 0 chi phối mức độ mạnh mẽ mà cú sốc hôm nay zt1zt1z_{t-1}z_{t-1}' kéo tương quan,
  • b0b \ge 0 chi phối tính bền bỉ — bao nhiêu phần của Qt1Q_{t-1} hôm qua được chuyển tiếp,
  • và ràng buộc hồi quy về trung bình là a+b<1a + b < 1 (với a,b>0a, b > 0), tương tự trực tiếp với α+β<1\alpha + \beta < 1 trong GARCH đơn biến.

Lưu ý rằng cấu trúc này giống hệt một đệ quy GARCH(1,1) vô hướng, nhưng trên các ma trận: một mỏ neo dài hạn Qˉ\bar{Q}, một số hạng cú sốc, và một số hạng bền bỉ. Vì nó là một tổ hợp lồi của các ma trận nửa xác định dương (Qˉ\bar{Q}, tích ngoài hạng-1, và Qt1Q_{t-1} trước đó), QtQ_t giữ tính xác định dương miễn là Qˉ0\bar{Q} \succ 0 và các trọng số không âm. Đây là điều mua cho chúng ta các ma trận hiệp phương sai hợp lệ được đảm bảo miễn phí.

QtQ_t gần như là một ma trận tương quan nhưng chưa hẳn — đường chéo của nó không chính xác bằng 1. Vì vậy chúng ta chuẩn hóa nó:

Rt=(diag(Qt))1/2Qt(diag(Qt))1/2R_t = \left(\mathrm{diag}(Q_t)\right)^{-1/2}\, Q_t\, \left(\mathrm{diag}(Q_t)\right)^{-1/2}

Theo từng phần tử, tương quan có điều kiện giữa tài sản iijj

ρij,t=qij,tqii,tqjj,t\rho_{ij,t} = \frac{q_{ij,t}}{\sqrt{q_{ii,t}\, q_{jj,t}}}

RtR_t này là một ma trận tương quan đúng đắn — đường chéo bằng đơn vị, các phần tử ngoài đường chéo trong [1,1][-1,1], xác định dương — ở mỗi bước thời gian đơn lẻ, theo cấu trúc. Lắp ráp lại ma trận hiệp phương sai có điều kiện đầy đủ:

Ht=DtRtDt,hij,t=ρij,tσi,tσj,tH_t = D_t\, R_t\, D_t, \qquad h_{ij,t} = \rho_{ij,t}\,\sigma_{i,t}\,\sigma_{j,t}

Dạng theo từng phần tử cuối cùng đó là dạng mà bạn sẽ dùng thường xuyên: hiệp phương sai có điều kiện của hai tài sản là tương quan động của chúng nhân với mỗi độ biến động động của chúng. Mọi thành phần ở vế phải đều biến đổi theo thời gian và đến từ một mô hình mà bạn có thể ước lượng.

Toàn bộ mô hình chỉ có hai tham số tương quan, aabb, bất kể d=2d = 2 hay d=50d = 50. Phía độ biến động co giãn tuyến tính (một GARCH đơn biến cho mỗi tài sản, mỗi cái với ~4-5 tham số, tất cả được khớp độc lập và song song một cách hiển nhiên). Đây là lý do vì sao DCC co giãn được ở nơi mà BEKK và VECH không thể: lời nguyền chiều bị giới hạn trong Qˉ\bar{Q}, vốn được nhắm mục tiêu (cắm vào như một ước lượng mẫu) thay vì được tối ưu hóa.

Ràng buộc vô hướng và cái giá của nó

Các đại lượng vô hướng a,ba, b có nghĩa là mọi cặp tài sản đều chia sẻ cùng một động học tương quan — cùng tốc độ điều chỉnh và cùng tính bền bỉ. Tương quan BTC-ETH và tương quan DOGE-SHIB dịch chuyển theo cùng một nhịp điệu mặc dù kinh tế học của chúng khác nhau. Đây là cái giá của tính dễ xử lý, và thường là một cái giá chấp nhận được. Các dạng tổng quát hóa (DCC Tổng quát hóa với ma trận A,BA, B; DCC bất đối xứng Cappiello-Engle-Sheppard) nới lỏng nó với cái giá là tham số và tính ổn định ước lượng. Chúng tôi đề cập đến aDCC bên dưới.

Hàm chuẩn hợp lý logarit của DCC

Để ước lượng aabb, chúng ta cần hàm hợp lý. Kết quả then chốt của Engle là hàm hợp lý logarit Gaussian tách rời thành một phần độ biến động và một phần tương quan, đó là điều biện minh cho bộ ước lượng hai bước. Giả sử ϵtFt1N(0,Ht)\epsilon_t \mid \mathcal{F}_{t-1} \sim \mathcal{N}(0, H_t), phần đóng góp vào hàm hợp lý logarit tại thời điểm tt

t=12(dlog(2π)+logHt+ϵtHt1ϵt)\ell_t = -\frac{1}{2}\left( d\log(2\pi) + \log|H_t| + \epsilon_t' H_t^{-1} \epsilon_t \right)

Thay Ht=DtRtDtH_t = D_t R_t D_t. Khi đó Ht=Dt2Rt|H_t| = |D_t|^2 |R_t|Ht1=Dt1Rt1Dt1H_t^{-1} = D_t^{-1} R_t^{-1} D_t^{-1}, và sử dụng zt=Dt1ϵtz_t = D_t^{-1}\epsilon_t:

t=12(dlog(2π)+2logDt+logRt+ztRt1zt)\ell_t = -\frac{1}{2}\left( d\log(2\pi) + 2\log|D_t| + \log|R_t| + z_t' R_t^{-1} z_t \right)

Bây giờ tách nó ra bằng cách cộng và trừ ztztz_t'z_t:

t=12(dlog(2π)+2logDt+ϵtDt2ϵt)phaˆˋn độ bieˆˊn động   tV  12(logRt+ztRt1ztztzt)phaˆˋn tương quan   tC\ell_t = \underbrace{-\frac{1}{2}\left( d\log(2\pi) + 2\log|D_t| + \epsilon_t' D_t^{-2}\epsilon_t \right)}_{\text{phần độ biến động }\;\ell_t^{V}} \;\underbrace{-\frac{1}{2}\left( \log|R_t| + z_t' R_t^{-1} z_t - z_t' z_t \right)}_{\text{phần tương quan }\;\ell_t^{C}}

Phần độ biến động tV\ell_t^V chỉ phụ thuộc vào các tham số GARCH đơn biến (thông qua DtD_t) — cực đại hóa nó chính là khớp dd mô hình GARCH đơn biến độc lập, điều chúng ta đã làm ở Bước 1. Phần tương quan tC\ell_t^C phụ thuộc vào aabb (thông qua RtR_t), cho trước các phần dư chuẩn hóa từ Bước 1. Vậy nên ở Bước 2, chúng ta chỉ cực đại hóa

LC(a,b)=12t=1T(logRt+ztRt1zt)\mathcal{L}^C(a, b) = -\frac{1}{2}\sum_{t=1}^{T}\left( \log|R_t| + z_t' R_t^{-1} z_t \right)

(số hạng ztztz_t'z_t không phụ thuộc vào a,ba, b, nên chúng ta bỏ nó đi). Đây là một bài toán tối ưu hóa hai tham số bất kể có bao nhiêu tài sản — đó là toàn bộ điểm mấu chốt. Nó được gọi là hàm chuẩn hợp lý vì bộ ước lượng hai bước là nhất quán nhưng không hoàn toàn hiệu quả; các sai số chuẩn cần một hiệu chỉnh (Engle & Sheppard 2001), nhưng để tạo tín hiệu thì các ước lượng điểm mới là điều quan trọng.

Đối với crypto, các đổi mới Gaussian đánh giá thấp rủi ro đuôi. Thay bằng hàm hợp lý Student-t đa biến là một thay đổi kiểu cắm-vào cho t\ell_t (thay nhân Gaussian bằng mật độ tt đa biến và thêm một tham số bậc tự do ν\nu). Chúng tôi giữ hàm chuẩn hợp lý Gaussian trong bộ ước lượng bên dưới cho rõ ràng và ghi chú nơi ν\nu đi vào — việc chuẩn hóa từ Phần 1-2 đã sử dụng các đổi mới t trên các biên, điều nắm bắt hầu hết lợi ích về đuôi.

Triển khai bằng Python

Một sự thật thẳng thừng nhưng quan trọng: thư viện arch không làm GARCH đa biến hay DCC. arch là một cỗ máy đơn biến tuyệt vời (chúng ta dựa vào nó chính xác cho việc đó), nhưng không có dcc_model trong đó. Các lựa chọn thực tế của bạn là:

  1. Tự xây DCC trên nền arch — khớp các mô hình đơn biến với arch, trích xuất các phần dư chuẩn hóa, triển khai đệ quy QQ và hàm chuẩn hợp lý tương quan trong NumPy/SciPy, và tối ưu hóa hai đại lượng vô hướng. Đây là điều chúng ta làm bên dưới. Nó khoảng 60 dòng và hoàn toàn minh bạch.
  2. Gói mgarch trên PyPI — một triển khai DCC-GARCH thuần Python nhẹ nhàng. Tiện lợi cho một lần khớp nhanh, kém linh hoạt hơn nếu bạn muốn các biên GJR hoặc các đổi mới t được đấu nối chính xác.
  3. rmgarch của R (Alexios Galanos) — triển khai tham chiếu. dccspec / dccfit hỗ trợ DCC, aDCC, GARCH-copula, Student-t, và các sai số chuẩn đúng đắn. Nếu bạn đang nghiên cứu nghiêm túc về độ biến động đa biến, rmgarch (gọi từ Python qua rpy2 nếu bắt buộc) là tiêu chuẩn vàng.

Chúng ta xây dựng lựa chọn 1 vì nó làm cho mọi bộ phận chuyển động trở nên tường minh và tái sử dụng các kỹ năng đơn biến từ Phần 1-2.

Bước 1: Khớp các biên GARCH đơn biến với arch

import numpy as np
import pandas as pd
from arch import arch_model
from scipy.optimize import minimize

def fetch_returns(symbols, start="2022-01-01", end="2025-12-31"):
    """
    Daily log returns for a list of crypto symbols.
    Replace with your data source (ccxt for 24/7 exchange data,
    yfinance for a quick sketch).
    """
    import yfinance as yf
    px = yf.download([f"{s}-USD" for s in symbols],
                     start=start, end=end)["Close"]
    px.columns = symbols
    rets = np.log(px / px.shift(1)).dropna()
    return rets

symbols = ["BTC", "ETH", "SOL", "BNB"]
returns = fetch_returns(symbols)

def fit_univariate(series, dist="t"):
    """
    Fit GJR-GARCH(1,1) with Student-t innovations (Part 2 model).
    Returns the fitted result and the *scaled* series it was fit on.
    We scale returns by 100 for the optimizer's numerical health,
    exactly as in Parts 1 and 2.
    """
    scaled = series * 100.0
    model = arch_model(scaled, mean="Constant",
                       vol="GARCH", p=1, o=1, q=1, dist=dist)
    res = model.fit(disp="off")
    return res

fits = {s: fit_univariate(returns[s]) for s in symbols}

Z = pd.DataFrame({s: fits[s].std_resid for s in symbols}).dropna()

Sigma = pd.DataFrame({s: fits[s].conditional_volatility
                      for s in symbols}).loc[Z.index]

print(Z.describe())

Một kiểm tra nhanh sự hợp lý của các phần dư chuẩn hóa là quan trọng. Nếu bất kỳ cột nào có độ lệch chuẩn khác xa 1, hoặc còn tự tương quan mạnh trong bình phương của nó (Ljung-Box trên zi,t2z_{i,t}^2), thì biên đơn biến bị đặc tả sai và bước DCC sẽ kế thừa lỗi đó. Hãy sửa biên trước — đó là mục đích của Phần 2.

Bước 2: Đệ quy DCC và hàm chuẩn hợp lý logarit

def dcc_negloglik(params, Z):
    """
    Negative DCC quasi-log-likelihood (Gaussian) in (a, b).
    Z : (T, d) array of standardized residuals from Step 1.

    Implements:
        Q_t = (1-a-b) Qbar + a z_{t-1} z_{t-1}' + b Q_{t-1}
        R_t = diag(Q_t)^{-1/2} Q_t diag(Q_t)^{-1/2}
        LL  = -1/2 sum_t ( log|R_t| + z_t' R_t^{-1} z_t )
    with correlation targeting: Qbar = sample corr of Z.
    """
    a, b = params
    if a <= 0 or b <= 0 or a + b >= 1.0:
        return 1e10

    Z = np.asarray(Z)
    T, d = Z.shape
    Qbar = np.cov(Z, rowvar=False, bias=True)   # unconditional (targeted)
    dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
    Qbar = dinv @ Qbar @ dinv

    Q = Qbar.copy()          # initialize Q_1 at the target
    ll = 0.0
    for t in range(T):
        q_diag = np.sqrt(np.diag(Q))
        R = Q / np.outer(q_diag, q_diag)
        sign, logdet = np.linalg.slogdet(R)
        if sign <= 0:
            return 1e10
        z = Z[t]
        Rinv_z = np.linalg.solve(R, z)
        ll += -0.5 * (logdet + z @ Rinv_z)
        Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
    return -ll

def fit_dcc(Z):
    """Estimate (a, b) by maximizing the DCC quasi-log-likelihood."""
    res = minimize(
        dcc_negloglik, x0=[0.03, 0.94], args=(np.asarray(Z),),
        method="L-BFGS-B",
        bounds=[(1e-6, 0.5), (1e-6, 0.999)],
    )
    a, b = res.x
    print(f"DCC estimates: a = {a:.4f}, b = {b:.4f}, a+b = {a+b:.4f}")
    print(f"log-likelihood: {-res.fun:.2f}")
    return a, b

a_hat, b_hat = fit_dcc(Z)

Chạy đoạn này trên một sổ BTC/ETH/SOL/BNB qua vài năm dữ liệu hàng ngày tạo ra kết quả có dạng như sau (các con số bên dưới chỉ mang tính minh họa, không phải từ một thí nghiệm có ngày tháng cụ thể — hãy chạy nó trên dữ liệu của chính bạn):

DCC estimates: a = 0.0287, b = 0.9401, a+b = 0.9688
log-likelihood: -3812.44

Cách đọc nó:

  • a=0.029a = 0.029 là nhỏ — ma trận tương quan không lảo đảo vì cú sốc của một ngày duy nhất. Mỗi ngày chỉ đẩy RtR_t về phía tích ngoài zt1zt1z_{t-1}z_{t-1}' khoảng ~3%.
  • b=0.940b = 0.940 là lớn — các tương quan rất bền bỉ. Một khi sổ ghép cặp với nhau trong một sự kiện căng thẳng, nó vẫn ghép cặp trong một thời gian, phân rã chậm rãi về Qˉ\bar{Q}. Điều này khớp với trải nghiệm thực tế của các đợt sụt giảm crypto: các tương quan không bật lại ngay khi giá ổn định.
  • a+b=0.969<1a + b = 0.969 < 1 xác nhận sự hồi quy về trung bình. Quá trình tương quan có một mức dài hạn dừng (Qˉ\bar{Q}) mà nó quay về, với chu kỳ bán rã khoảng log(0.5)/log(a+b)22\log(0.5)/\log(a+b) \approx 22 ngày. Nếu bạn từng ước lượng a+ba + b về cơ bản bằng 1, thì quá trình tương quan là tích hợp — nó không có mỏ neo dài hạn, thường là triệu chứng của một điểm gãy cấu trúc bên trong mẫu của bạn mà mô hình đang hấp thụ như tính bền bỉ vô hạn.

Tính bền bỉ gần-đơn-vị và độ nạp cú sốc nhỏ xíu là dấu vân tay điển hình của DCC trên các lớp tài sản, và crypto không phải ngoại lệ. Đó cũng là lý do vì sao một tương quan trượt 30 ngày là một sự thay thế kém đến vậy: một cửa sổ trượt ngầm giả định aabb hoàn toàn không khớp với cấu trúc phân rã này.

Một vài ghi chú triển khai giúp tiết kiệm thời gian gỡ lỗi thực tế:

  • Khởi tạo. Bắt đầu tại [0.03, 0.94] phản ánh ước lượng crypto điển hình: aa nhỏ (các tương quan phản ứng với cú sốc nhưng không dữ dội), bb lớn (các tương quan bền bỉ). Nếu bộ tối ưu hóa của bạn lang thang tới a+b1a+b \to 1 thì quá trình tương quan là tích hợp — thường là dấu hiệu của một điểm gãy cấu trúc trong mẫu (một sự thay đổi chế độ mà mô hình đang gắng khớp như tính bền bỉ).
  • Quy ước thời điểm. Bên trong vòng lặp, chúng ta chấm điểm RtR_t dựa trên ztz_tsau đó cập nhật QQ với ztztz_t z_t' cho bước tiếp theo. Điều này giữ RtR_t chỉ là một hàm của thông tin đến t1t-1 — không nhìn trước. Sai lệch một đơn vị ở chỗ này là lỗi DCC phổ biến nhất, và nó âm thầm thổi phồng độ khớp trong mẫu.
  • Nhắm mục tiêu tương quan. Chúng ta cắm Qˉ\bar{Q} vào như tương quan mẫu thay vì ước lượng nó. Đây là điều làm cho bài toán tối ưu hóa trở thành hai chiều. Cái giá là Qˉ\bar{Q} sử dụng toàn bộ mẫu, nên trong một walk-forward nghiêm ngặt, bạn phải ước lượng lại nó chỉ trên cửa sổ huấn luyện (xem bên dưới).

Bước 3: Tái tạo các quỹ đạo tương quan và hiệp phương sai

Một khi a,ba, b được cố định, chạy đệ quy thêm một lần nữa, lần này lưu trữ toàn bộ quỹ đạo RtR_t (và HtH_t) để các chiến lược phía sau có thể sử dụng nó.

def dcc_filter(Z, Sigma, a, b):
    """
    Run the DCC recursion with fixed (a,b) and return the full paths:
      R_path : (T, d, d) conditional correlation matrices
      H_path : (T, d, d) conditional covariance matrices (scaled units)
    Sigma : (T, d) conditional volatilities aligned with Z.
    """
    Z = np.asarray(Z); Sig = np.asarray(Sigma)
    T, d = Z.shape
    Qbar = np.cov(Z, rowvar=False, bias=True)
    dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
    Qbar = dinv @ Qbar @ dinv

    Q = Qbar.copy()
    R_path = np.empty((T, d, d))
    H_path = np.empty((T, d, d))
    for t in range(T):
        q_diag = np.sqrt(np.diag(Q))
        R = Q / np.outer(q_diag, q_diag)
        R_path[t] = R
        Dt = np.diag(Sig[t])          # D_t = diag(sigma_i,t)
        H_path[t] = Dt @ R @ Dt       # H_t = D_t R_t D_t
        z = Z[t]
        Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
    return R_path, H_path

R_path, H_path = dcc_filter(Z, Sigma, a_hat, b_hat)

i, j = symbols.index("BTC"), symbols.index("ETH")
rho_btc_eth = pd.Series(R_path[:, i, j], index=Z.index, name="rho_BTC_ETH")
print(rho_btc_eth.describe())
print("min/max correlation:", rho_btc_eth.min().round(3),
      rho_btc_eth.max().round(3))

Chuỗi rho_btc_eth là phần thưởng của toàn bộ bài tập: thay vì một con số, giờ bạn có một tương quan hàng ngày mà bạn có thể vẽ đồ thị, đặt ngưỡng, hoặc đưa vào một chiến lược. Trên dữ liệu crypto thực, bạn thường sẽ thấy nó dao động từ khoảng 0.5 trong các đoạn yên tĩnh đến trên 0.9 trong lúc căng thẳng — chính là khoảng cách mà một tương quan mẫu đơn lẻ đã lấy trung bình và làm biến mất.

Dự báo một bước phía trước

Đối với giao dịch trực tiếp, bạn cần Ht+1H_{t+1} của kỳ tiếp theo từ thông tin có sẵn ngay bây giờ. Phía độ biến động đến từ dự báo một bước của mỗi mô hình arch; phía tương quan là thêm một lượt của đệ quy:

def dcc_forecast_next(Z, a, b, fits, symbols):
    """One-step-ahead H_{t+1} using info through the last observation."""
    Z = np.asarray(Z); T, d = Z.shape
    Qbar = np.cov(Z, rowvar=False, bias=True)
    dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
    Qbar = dinv @ Qbar @ dinv

    Q = Qbar.copy()
    for t in range(T):
        z = Z[t]
        Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
    q_diag = np.sqrt(np.diag(Q))
    R_next = Q / np.outer(q_diag, q_diag)

    sig_next = np.array([
        np.sqrt(fits[s].forecast(horizon=1, reindex=False)
                .variance.iloc[-1, 0])
        for s in symbols
    ])
    Dt = np.diag(sig_next)
    H_next = Dt @ R_next @ Dt
    return R_next, H_next, sig_next

R_next, H_next, sig_next = dcc_forecast_next(Z, a_hat, b_hat, fits, symbols)

Hãy nhớ rằng mọi thứ đều ở đơn vị đã co giãn (×100) vì chúng ta khớp arch trên series * 100. Chia các độ biến động cho 100 (và các hiệp phương sai cho 1002=10,000100^2 = 10{,}000) để quay lại đơn vị lợi suất thô trước khi đưa vào một chiến lược. Giữ cho việc co giãn thẳng thắn là mệt mỏi nhưng là một nguồn lỗi âm thầm thường gặp.

Ứng dụng 1: Tỷ lệ phòng ngừa động cho giao dịch cặp

Cặp trung lập với thị trường cổ điển — mua một tài sản, bán khống một lượng có trọng số beta của một tài sản khác — sống hay chết tùy vào tỷ lệ phòng ngừa β\beta. Ước lượng nó bằng OLS tĩnh trên một cửa sổ huấn luyện và bạn kế thừa chính xác vấn đề tương quan cũ mà toàn bộ bài viết này nói về: hàng phòng ngừa từng trung lập hóa mức phơi nhiễm thị trường quý trước là sai vào quý này.

DCC cung cấp cho bạn tỷ lệ phòng ngừa như một chuỗi thời gian. Hàng phòng ngừa phương sai cực tiểu của mức phơi nhiễm ETH sử dụng BTC là hệ số hồi quy có điều kiện

βt=Covt(rETH,rBTC)Vart(rBTC)=hETH,BTC,tσBTC,t2=ρETH,BTC,tσETH,tσBTC,t\beta_t = \frac{\mathrm{Cov}_t(r_{\text{ETH}}, r_{\text{BTC}})}{\mathrm{Var}_t(r_{\text{BTC}})} = \frac{h_{\text{ETH,BTC},t}}{\sigma_{\text{BTC},t}^2} = \rho_{\text{ETH,BTC},t}\,\frac{\sigma_{\text{ETH},t}}{\sigma_{\text{BTC},t}}

Mọi số hạng ở vế phải đều là một đầu ra của DCC. Tỷ lệ phòng ngừa dịch chuyển vì hai lý do riêng biệt, và DCC tách chúng ra một cách gọn gàng: tương quan ρt\rho_t thay đổi (các tài sản ghép cặp hoặc tách rời), và tỷ số độ biến động σETH,t/σBTC,t\sigma_{\text{ETH},t}/\sigma_{\text{BTC},t} thay đổi (một tài sản trở nên biến động tương đối cao hơn). Một beta OLS trượt bôi cả hai hiệu ứng vào nhau với một độ trễ; DCC quy chúng về đúng nguồn.

def dynamic_hedge_ratio(R_path, Sigma, base="BTC", target="ETH",
                        symbols=symbols, index=Z.index):
    """
    beta_t to hedge `target` exposure with `base`:
        beta_t = rho_t * sigma_target,t / sigma_base,t
    (Scaling cancels in the ratio, so scaled units are fine here.)
    """
    i = symbols.index(target)
    j = symbols.index(base)
    rho = R_path[:, i, j]
    sig = np.asarray(Sigma)
    beta = rho * sig[:, i] / sig[:, j]
    return pd.Series(beta, index=index, name=f"beta_{target}_{base}")

beta_t = dynamic_hedge_ratio(R_path, Sigma)
print(beta_t.describe())

spread = (returns["ETH"] - beta_t.shift(1) * returns["BTC"]).dropna()

Đưa spread vào bất kỳ cỗ máy giao dịch cặp nào bạn chạy. Bản thân hàng phòng ngừa động không tự tạo ra lợi thế — nó làm cho spread mà bạn giao dịch thực sự trung lập với thị trường xuyên suốt thời gian, để tín hiệu hồi quy về trung bình của bạn không bị nhiễm bởi mức phơi nhiễm định hướng đang trôi dạt. Nếu bạn xây dựng các chiến lược cặp, cái này gắn trực tiếp vào các khuôn khổ trong Chênh lệch giá thống kê & Giao dịch cặp trong Cryptocách tiếp cận khoảng cách cho giao dịch cặp, thay thế tỷ lệ phòng ngừa cố định của chúng. Bản thân chuỗi tương quan cũng là một đầu vào sạch hơn cho một tín hiệu cặp dựa trên tương quan so với bất kỳ cửa sổ trượt nào — bạn nhận được một ρt\rho_t được làm mượt, nhất quán với mô hình, thay vì một ước lượng theo cửa sổ đầy nhiễu.

Hai lưu ý cụ thể khi dùng βt\beta_t trực tiếp. Thứ nhất, hãy làm trễ nó — giao dịch trên βt1\beta_{t-1}, không bao giờ trên βt\beta_t đồng thời, nếu không bạn đang nhìn trộm. Thứ hai, một tỷ lệ phòng ngừa dao động điên cuồng mỗi ngày tạo ra vòng quay giao dịch và phí; trong thị trường crypto 24/7 với chi phí funding trên chân bán khống, một hàng phòng ngừa phản ứng quá mức có thể chảy máu nhiều hơn sự trôi dạt mà nó sửa chữa. Hãy làm mượt βt\beta_t (một EWMA, hoặc chỉ tái cân bằng hàng phòng ngừa khi nó vượt qua một dải) và định cỡ toàn bộ một cách hợp lý — định cỡ vị thế từ một tín hiệu đầy nhiễu là một kỷ luật riêng, được bàn trong định cỡ theo tiêu chí Kelly.

Ứng dụng 2: Phương sai danh mục biến đổi theo thời gian

Đối với một danh mục với vector trọng số ww, phương sai có điều kiện là

σp,t2=wHtw=ijwiwjρij,tσi,tσj,t\sigma_{p,t}^2 = w'\, H_t\, w = \sum_{i}\sum_{j} w_i w_j\, \rho_{ij,t}\,\sigma_{i,t}\,\sigma_{j,t}

Với một ma trận hiệp phương sai tĩnh — mặc định của Markowitz — con số này là một hằng số mà bạn đã tính một lần rồi giả vờ rằng nó vẫn còn đúng. Nó không đúng. Rủi ro danh mục hít thở cùng với thị trường, và nó hít thở mạnh nhất chính xác khi các tương quan tăng vọt, bởi vì trong một đợt sụt giảm, cả các số hạng σi,t\sigma_{i,t} và các số hạng ρij,t\rho_{ij,t} đều cùng tăng và cùng nhân lên. Một danh mục trông như 40% vol hàng năm trong thị trường yên bình có thể đang chạy 80%+ trong một tuần căng thẳng, và một ma trận hiệp phương sai tĩnh sẽ nói với bạn rằng chẳng có gì thay đổi.

def portfolio_vol_path(H_path, weights, index=Z.index, unscale=1e4):
    """
    Conditional portfolio volatility sigma_{p,t} = sqrt(w' H_t w).
    H_path is in scaled (x100) units, so covariances carry a 100^2
    factor: divide by unscale=1e4 to return to raw-return variance.
    """
    w = np.asarray(weights)
    var_t = np.einsum("i,tij,j->t", w, H_path, w) / unscale
    return pd.Series(np.sqrt(var_t), index=index, name="port_vol")

w = np.array([0.4, 0.3, 0.2, 0.1])   # BTC, ETH, SOL, BNB
pv = portfolio_vol_path(H_path, w)
pv_annual = pv * np.sqrt(365)
print(pv_annual.describe())

σp,t\sigma_{p,t} biến đổi theo thời gian này là đầu vào trung thực mà phân bổ dựa trên rủi ro cần đến. Tối ưu hóa trung bình-phương sai (Markowitz cho crypto) với một hiệp phương sai mẫu tĩnh là đang tối ưu hóa dựa trên một điều hư cấu; đưa vào nó HtH_t (hoặc dự báo tầm ngắn của nó) làm cho chính đường biên hiệu quả trở nên biến đổi theo thời gian và buộc bộ tối ưu hóa giảm rủi ro khi bước vào các chế độ tương quan đang tăng thay vì sau khi chúng đã tăng. Các cách tiếp cận cân bằng rủi ro và phân cấp — pipeline HRP + CVaR — thậm chí còn nhạy cảm hơn với đầu vào hiệp phương sai, vì toàn bộ phân bổ chính là một hàm của ma trận rủi ro. Và nếu bạn đang so sánh các bộ phân bổ trực tiếp với nhau, như trong so sánh các thuật toán tối ưu hóa danh mục, thì việc chúng tiêu thụ hiệp phương sai tĩnh hay động thường là một yếu tố quyết định rủi ro thực hiện lớn hơn là lựa chọn thuật toán.

Ứng dụng trực tiếp là nhắm mục tiêu độ biến động cho toàn bộ danh mục: chọn một mục tiêu vol hàng năm σ\sigma^{*}, và co giãn mức phơi nhiễm gộp theo σ/σp,t\sigma^{*} / \sigma_{p,t} mỗi kỳ để rủi ro thực hiện giữ ở mức xấp xỉ không đổi thay vì phình to trong khủng hoảng. Điều đó khép lại vòng với Phần 4, nơi xây dựng và backtest chính xác quy tắc này.

Ứng dụng 3: Tương quan như một tín hiệu chế độ

Ngoài việc phòng ngừa và định cỡ, ma trận tương quan mang theo một tín hiệu vĩ mô. Đại lượng vô hướng hữu ích nhất mà bạn có thể trích xuất là tương quan trung bình theo cặp:

ρˉt=2d(d1)i<jρij,t\bar{\rho}_t = \frac{2}{d(d-1)}\sum_{i < j} \rho_{ij,t}

Khi ρˉt\bar{\rho}_t tăng trên toàn sổ, thị trường đang bước vào một chế độ risk-off — các câu chuyện đặc thù ngừng có ý nghĩa và mọi thứ giao dịch như một beta vĩ mô duy nhất. Đây là dấu vân tay định lượng của "các tương quan tiến về 1 trong một cuộc khủng hoảng." Nó có xu hướng dẫn dắt hoặc trùng khớp với các đợt sụt giảm, điều làm cho nó trở thành một chỉ báo chế độ có thể sử dụng được thay vì một bản phân tích sau tử vong bị trễ.

def avg_pairwise_corr(R_path, index=Z.index):
    T, d, _ = R_path.shape
    iu = np.triu_indices(d, k=1)          # upper-triangle off-diagonals
    avg = R_path[:, iu[0], iu[1]].mean(axis=1)
    return pd.Series(avg, index=index, name="avg_corr")

avg_corr = avg_pairwise_corr(R_path)

roll_q = avg_corr.rolling(365, min_periods=90).quantile(0.80)
risk_off = (avg_corr > roll_q)

Bạn có thể sử dụng risk_off như một cái van tiết lưu độc lập (cắt mức phơi nhiễm gộp, nới rộng các mức dừng lỗ, tạm ngừng các chiến lược hồi quy về trung bình vốn bị nghiền nát khi mọi thứ cùng xu hướng với nhau) hoặc như một đặc trưng trong một mô hình chế độ chính thức hơn. Nó ghép cặp một cách tự nhiên với cách tiếp cận Markov ẩn trong phát hiện chế độ với HMM: tương quan DCC trung bình là một trong những biến quan sát giàu thông tin hơn mà bạn có thể trao cho một HMM, bởi vì nó hướng tới tương lai về căng thẳng hệ thống theo một cách mà lợi suất trong quá khứ không có. Lưu ý trung thực: tương quan đang tăng nói với bạn rằng sự đa dạng hóa đang thất bại, chứ không phải thị trường sẽ đi theo hướng nào. Nó là một tín hiệu rủi ro, không phải một tín hiệu alpha, và nên được định cỡ như vậy — xem sự bất đối xứng của lỗ và lãi để hiểu vì sao việc coi một chế độ rủi ro như một cược định hướng lại kết thúc tồi tệ.

Những cân nhắc thực tế

Tính ổn định ước lượng và số lượng tài sản

DCC co giãn tốt hơn nhiều so với BEKK, nhưng "co giãn" không phải là "miễn phí." Ma trận nhắm mục tiêu tương quan Qˉ\bar{Q} là một tương quan mẫu d×dd \times d, và các ma trận tương quan mẫu trở nên điều kiện xấu khi dd tiến gần số lượng quan sát. Với 4 tài sản và 1000 ngày thì bạn ổn. Với 60 tài sản và 400 ngày, Qˉ\bar{Q} gần như suy biến, nghịch đảo của nó trong hàm hợp lý bùng nổ, và RtR_t có thể lang thang ra khỏi tính xác định dương do nhiễu số học. Các biện pháp giảm thiểu, đại khái theo thứ tự tần suất bạn sẽ cần chúng:

  • Thu nhỏ Qˉ\bar{Q} về phía một mục tiêu có cấu trúc (Ledoit-Wolf, hoặc về phía ma trận đơn vị / một ma trận tương quan cố định) trước khi chạy đệ quy. Đây là cách khắc phục có đòn bẩy cao nhất cho các sổ lớn.
  • Nhóm các tài sản thành một nhúm ngành (majors, L1, DeFi, meme), mô hình hóa bên trong và giữa các ngành ở cấp độ ngành, hoặc chạy DCC trên các nhân tố thành phần chính thay vì các tài sản thô.
  • Ưu tiên nhiều dữ liệu hơn là nhiều tài sản. DCC có một sự thèm khát vô độ đối với một lịch sử dài, sạch, đồng thời — đó chính xác là điều mà các token trẻ không có.

Thực tế mà nói, hãy giữ DCC trực tiếp ở mức tối đa vài chục tài sản. Đối với một vũ trụ lớn, DCC trên lợi suất nhân tố cộng với các phần dư đặc thù là cách giải quyết tiêu chuẩn.

Nhắm mục tiêu tương quan là một lối tắt có cái giá

Nhắm mục tiêu Qˉ\bar{Q} làm cho việc ước lượng trở nên dễ xử lý nhưng nướng tương quan không điều kiện toàn-mẫu vào mỗi RtR_t. Trong một backtest nghiêm ngặt, đây là một sự rò rỉ nhìn trước: ma trận tương quan của ngày tt của bạn "biết" tương quan trung bình của toàn bộ mẫu, bao gồm cả tương lai. Để đánh giá trung thực, bạn phải ước lượng lại Qˉ\bar{Q} chỉ trên cửa sổ huấn luyện và giữ nó cố định ngoài mẫu, hoặc cuộn nó về phía trước. Đây cũng là kỷ luật mà toàn bộ khuôn khổ tối ưu hóa walk-forward áp đặt, và nó dễ bị vi phạm một cách tình cờ với một np.cov(Z) tiện lợi trên toàn bộ mảng — như đoạn code minh họa ở trên của chúng ta làm. Hãy sửa nó trước khi bạn tin tưởng bất kỳ con số P&L nào.

Tần suất khớp lại và kỷ luật nhìn trước

Bạn không cần tối ưu hóa lại a,ba, b mỗi ngày — chúng là các tham số ổn định. Một tần suất sản xuất hợp lý:

  • Ước lượng lại a,ba, b và các tham số GARCH đơn biến hàng tuần hoặc hàng tháng.
  • Chạy bộ lọc (cập nhật QtQ_t, σi,t\sigma_{i,t}) mỗi kỳ với các tham số đông cứng để có RtR_tHtH_t mới. Lọc thì rẻ; khớp thì không.
  • Luôn dự báo, không bao giờ làm mượt. Sử dụng RtR_t được xây từ thông tin đến t1t-1 để giao dịch tại tt. Cấu trúc hai lượt (khớp trên một cửa sổ, rồi lọc về phía trước) là điều giữ cho bạn trung thực.

Khoảng cách giữa một backtest DCC và hiệu suất trực tiếp gần như luôn là một sự rò rỉ nhìn trước — Qˉ\bar{Q} toàn-mẫu, βt\beta_t đồng thời, hoặc khớp lại trên dữ liệu bao gồm cả giao dịch mà bạn đang đánh giá. Kỷ luật khớp backtest với điều kiện trực tiếp là một chủ đề riêng trong tương đương backtest-trực tiếp, và DCC là một mô hình trừng phạt sự cẩu thả ở đây nhiều hơn hầu hết. Nếu, sau một đánh giá walk-forward sạch, tương quan động không thêm được gì so với một ước lượng trượt đơn giản cho chiến lược của bạn, thì đó là một kết quả tiêu cực thực sự và đáng công bố — tư duy trong các kết quả tiêu cực trung thực áp dụng trực tiếp.

DCC bất đối xứng (aDCC)

Cũng như hiệu ứng đòn bẩy đơn biến (Phần 2) có nghĩa là tin xấu làm tăng độ biến động nhiều hơn tin tốt, các tương quan tăng nhiều hơn sau các cú sốc âm chung so với sau các cú sốc dương chung. Cappiello, Engle & Sheppard (2006) nắm bắt điều này với DCC bất đối xứng, thêm một số hạng được điều khiển bởi tích ngoài của các phần dư chuẩn hóa phần-âm zt=min(zt,0)z_t^- = \min(z_t, 0):

Qt=(QˉaQˉbQˉgNˉ)+azt1zt1+gzt1zt1+bQt1Q_t = (\bar{Q} - a\bar{Q} - b\bar{Q} - g\bar{N}) + a\, z_{t-1} z_{t-1}' + g\, z_{t-1}^- z_{t-1}^{-\prime} + b\, Q_{t-1}

trong đó Nˉ=1Ttztzt\bar{N} = \frac{1}{T}\sum_t z_t^- z_t^{-\prime}g0g \ge 0 đo lường cú hích tương quan phụ trội từ các chuyển động giảm giá chung. Đối với crypto, nơi tương quan-sụp-đổ là rủi ro chi phối, số hạng bất đối xứng thường có ý nghĩa và đáng với một tham số phụ trội. rmgarch khớp aDCC ngay lập tức (model="aDCC"); thêm số hạng ztz_t^- vào bộ ước lượng NumPy của chúng ta là một bài tập đơn giản.

So sánh: DCC đối chọi với các phương án khác

DCC đứng ở đâu trong số các cách mà bạn có thể lấy một ma trận hiệp phương sai cho một sổ crypto? Tóm tắt trung thực:

Cách tiếp cận Tham số Co giãn tới ρ\rho biến đổi theo thời gian? Đảm bảo PD? Phụ thuộc đuôi?
Hiệp phương sai mẫu / trượt 0 (độ dài cửa sổ) mọi dd thô sơ (trễ, nhiễu) không (cần vá) không
EWMA (RiskMetrics) 1 (λ\lambda) mọi dd có (một tốc độ phân rã) không
CCC-GARCH dd biên + Qˉ\bar{Q} hàng chục không (R cố định) không
DCC-GARCH dd biên + 2 hàng chục không
aDCC-GARCH dd biên + 3 hàng chục có, bất đối xứng một phần
BEKK O(d2)O(d^2) 4\le 4 có (phong phú) không
VECH O(d4)O(d^4) 3\le 3 có (phong phú nhất) đau đầu không
GARCH-copula dd biên + copula hàng chục (vine) copula tĩnh

Một vài cách đọc bảng này:

  • EWMA là đường cơ sở rẻ tiền mà ai cũng nên vượt qua trước khi tuyên bố DCC hữu ích. Nó là một trường hợp đặc biệt một-tham-số về mặt tinh thần — một sự phân rã hàm mũ duy nhất áp dụng trực tiếp lên hiệp phương sai — và đối với nhiều sổ, việc cải thiện nó ngoài mẫu khó đến mức đáng kinh ngạc. Nếu DCC không vượt được EWMA trong walk-forward sạch, hãy dùng EWMA.
  • CCC đối chọi DCC là toàn bộ điểm mấu chốt của bài viết này: cùng một phép phân tích thừa số, nhưng CCC đóng băng RR còn DCC để nó dịch chuyển. Hai tham số phụ trội (a,ba, b) là toàn bộ sự khác biệt, và trong crypto chúng đáng đồng tiền bát gạo.
  • BEKK/VECH mua được động học phong phú hơn — mọi hiệp phương sai có thể phản ứng với mọi cú sốc quá khứ — nhưng cái giá tham số giới hạn chúng ở các sổ nhỏ xíu. Với bất cứ thứ gì vượt quá 4 tài sản, chúng không phải là một lựa chọn thực sự.
  • GARCH-copula là hàng duy nhất với chữ "có" dưới cột phụ thuộc đuôi. Đó lại là tính bổ sung: DCC mô hình hóa phần trung tâm động của phân phối chung, còn copula mô hình hóa các đuôi tĩnh của nó. Nếu câu hỏi rủi ro của bạn là "điều gì xảy ra khi mọi thứ vỡ vụn cùng một lúc," hãy tìm đến pipeline copula; nếu là "tỷ lệ phòng ngừa / phương sai danh mục của tôi ngay bây giờ là bao nhiêu," hãy tìm đến DCC.

Mặc định thực tế cho một bàn giao dịch crypto có hệ thống: DCC (hoặc aDCC) cho tỷ lệ phòng ngừa và hiệp phương sai động ở phần thân, một lớp phủ copula cho rủi ro đuôi và CVaR, và EWMA làm đường cơ sở kiểm tra tính hợp lý giúp bạn trung thực về việc liệu bộ máy phụ trội có đáng đồng tiền hay không.

Những hạn chế

  • Động học vô hướng. Một aa và một bb cho tất cả các cặp là một ràng buộc mạnh. BTC-ETH và hai altcoin vô danh chia sẻ cùng tốc độ điều chỉnh. DCC Tổng quát hóa nới lỏng điều này nhưng tái đưa ra sự bùng nổ tham số mà DCC được thiết kế để tránh.
  • Mất hiệu quả do hai bước. Bộ ước lượng chuẩn hợp lý là nhất quán nhưng không hoàn toàn hiệu quả, và các sai số chuẩn ngây thơ là sai. Hãy dùng hiệu chỉnh Engle-Sheppard nếu bạn quan tâm đến suy diễn; để tạo tín hiệu thì các ước lượng điểm là đủ.
  • Đuôi Gaussian theo mặc định. Hàm chuẩn hợp lý Gaussian thuần túy đánh giá thấp rủi ro đuôi chung. Các đổi mới Student-t giúp ích; đối với sự phụ thuộc đuôi thực sự (xác suất của các chuyển động cực đoan đồng thời), DCC là công cụ sai và một mô hình copula là công cụ đúng. DCC cho bạn phần thân động của tương quan; copula cho bạn đuôi tĩnh. Các bàn giao dịch nghiêm túc dùng cả hai.
  • Tương quan không phải nhân quả, và không phải hướng đi. ρˉt\bar{\rho}_t đang tăng cảnh báo rằng sự đa dạng hóa đang thất bại; nó không nói gì về hướng thị trường. Đừng chất lên một tín hiệu rủi ro những kỳ vọng về hướng đi.
  • Cơn đói dữ liệu. Mọi thứ ở trên đều giả định các lịch sử dài, sạch, đồng bộ. Các token mới nhất và thú vị nhất của crypto vi phạm cả ba điều.

Tóm tắt

  • Tương quan tĩnh là một lời nói dối trong crypto. Các tương quan phân cụm, bền bỉ, và tăng vọt về 1 trong các đợt sụt giảm — chính xác khi mà sự đa dạng hóa lẽ ra phải giúp ích. Một ρ^\hat{\rho} mẫu đơn lẻ lấy trung bình một quá trình chuyển đổi chế độ thành một giá trị ở giữa vô nghĩa.
  • GARCH đa biến đầy đủ (VECH, BEKK) không co giãn. Số lượng tham số tăng theo O(d2)O(d^2); cả hai đều bị giới hạn ở một nhúm tài sản trong thực tế.
  • DCC (Engle 2002) phân tích thừa số bài toán: Ht=DtRtDtH_t = D_t R_t D_t, với DtD_t từ các lần khớp GARCH đơn biến độc lập (tái sử dụng Phần 1-2) và RtR_t từ một đệ quy hai tham số. Nó co giãn tới hàng chục tài sản vì chỉ có a,ba, b được tối ưu hóa.
  • Đệ quy Qt=(1ab)Qˉ+azt1zt1+bQt1Q_t = (1-a-b)\bar{Q} + a\,z_{t-1}z_{t-1}' + b\,Q_{t-1}, được chuẩn hóa thành RtR_t, tạo ra một ma trận tương quan xác định dương hợp lệ ở mỗi bước, với a,b>0a,b>0, a+b<1a+b<1.
  • arch không làm DCC. Khớp các biên với arch, rồi triển khai bộ ước lượng ~60 dòng NumPy/SciPy ở đây, hoặc dùng mgarch (Python) hoặc rmgarch (R, tham chiếu).
  • Ba phần thưởng cụ thể: một tỷ lệ phòng ngừa động βt=ρtσETH,t/σBTC,t\beta_t = \rho_t\,\sigma_{\text{ETH},t}/\sigma_{\text{BTC},t} cho giao dịch cặp; một phương sai danh mục biến đổi theo thời gian trung thực wHtww'H_t w cho phân bổ dựa trên rủi ro; và tương quan trung bình theo cặp như một tín hiệu chế độ risk-off.
  • Kỷ luật là tất cả. Nhắm mục tiêu tương quan rò rỉ giá trị trung bình toàn-mẫu, nên hãy ước lượng lại Qˉ\bar{Q} chỉ trên dữ liệu huấn luyện; làm trễ mọi tỷ lệ phòng ngừa; lọc về phía trước, không bao giờ làm mượt. Đánh giá walk-forward là điều không thể thương lượng.
  • aDCC thêm một số hạng bất đối xứng giảm giá và thường đáng giá trong crypto, nơi tương quan-sụp-đổ chi phối.
  • Phần 4 sử dụng các dự báo này để xây dựng và backtest một chiến lược nhắm mục tiêu độ biến động.

Tài liệu tham khảo:

  • Engle, R. (2002). Dynamic Conditional Correlation: A Simple Class of Multivariate Generalized Autoregressive Conditional Heteroskedasticity Models. Journal of Business & Economic Statistics, 20(3), 339-350. DOI
  • Engle, R. & Sheppard, K. (2001). Theoretical and Empirical Properties of Dynamic Conditional Correlation Multivariate GARCH. NBER Working Paper 8554. DOI
  • Bollerslev, T. (1990). Modelling the Coherence in Short-Run Nominal Exchange Rates: A Multivariate Generalized ARCH Model. Review of Economics and Statistics, 72(3), 498-505. DOI
  • Cappiello, L., Engle, R., & Sheppard, K. (2006). Asymmetric Dynamics in the Correlations of Global Equity and Bond Returns. Journal of Financial Econometrics, 4(4), 537-572. DOI
  • Engle, R. & Kroner, K. (1995). Multivariate Simultaneous Generalized ARCH. Econometric Theory, 11(1), 122-150. DOI
  • Bollerslev, T., Engle, R., & Wooldridge, J. (1988). A Capital Asset Pricing Model with Time-Varying Covariances. Journal of Political Economy, 96(1), 116-131. DOI
  • Galanos, A. (2022). rmgarch: Multivariate GARCH Models. R package. CRAN.
Tuyên bố miễn trừ trách nhiệm: Thông tin được cung cấp trong bài viết này chỉ nhằm mục đích giáo dục và thông tin, không cấu thành lời khuyên về tài chính, đầu tư hoặc giao dịch. Giao dịch tiền mã hóa tiềm ẩn rủi ro thua lỗ đáng kể.

MarketMaker.cc Team

Nghiên Cứu & Chiến Lược Định Lượng

Thảo luận trên Telegram
Newsletter

Đi Trước Thị Trường

Đăng ký nhận bản tin của chúng tôi để có những thông tin chuyên sâu độc quyền về AI trading, phân tích thị trường và các cập nhật nền tảng.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất kỳ lúc nào.