← กลับไปยังบทความ
March 30, 2026
อ่าน 5 นาที

โมเดล Copula สำหรับการสร้างแบบจำลองความเสี่ยงร่วมในพอร์ตโฟลิโอคริปโต

โมเดล Copula สำหรับการสร้างแบบจำลองความเสี่ยงร่วมในพอร์ตโฟลิโอคริปโต
#ความเสี่ยง
#copula
#พอร์ตโฟลิโอ
#tail-dependence
#VaR

โมเดล Copula — การแจกแจงความเสี่ยงร่วม

ความสัมพันธ์ (Correlation) คือเครื่องมือแรกที่ผู้จัดการพอร์ตโฟลิโอส่วนใหญ่หยิบมาใช้เมื่อประเมินการกระจายความเสี่ยง แต่ในตลาดคริปโต ความสัมพันธ์นี้กลับเป็นอันตรายอย่างยิ่ง สกุลเงินดิจิทัลสองตัวอาจมีค่า Pearson correlation อยู่ที่ 0.3 ในช่วงตลาดสงบ แต่กระโดดขึ้นเป็น 0.95 ในช่วงตลาดตกต่ำ ความสัมพันธ์เชิงเส้นอาศัยสมมติฐานว่าการแจกแจงมีลักษณะเชิงวงรี ซึ่งเป็นสมมติฐานที่พังทลายลงภายใต้หางอ้วนและโครงสร้างการพึ่งพาแบบอสมมาตรที่แพร่หลายในผลตอบแทนของสกุลเงินดิจิทัล

โมเดล Copula แก้ปัญหานี้โดยแยก พฤติกรรมส่วนชาย (marginal behavior) (วิธีที่แต่ละสินทรัพย์ประพฤติตัวแยกกัน) ออกจาก โครงสร้างการพึ่งพา (dependence structure) (วิธีที่สินทรัพย์เคลื่อนที่ไปด้วยกัน) การแยกส่วนนี้ ซึ่งมีรากฐานมาจากทฤษฎีบทของ Sklar มอบกรอบงานที่ยืดหยุ่นสำหรับการสร้างแบบจำลองการแจกแจงร่วมเต็มรูปแบบของผลตอบแทนพอร์ตโฟลิโอ รวมถึงหางการแจกแจงที่ความเสี่ยงที่แท้จริงอาศัยอยู่

เหตุใดความสัมพันธ์เชิงเส้นจึงล้มเหลวกับคริปโต

พิจารณาพอร์ตโฟลิโอของ BTC, ETH, SOL และ AVAX ในช่วงที่ Terra/Luna ล่มสลายในเดือนพฤษภาคม 2022 ค่าสหสัมพันธ์ระหว่างสินทรัพย์เหล่านี้พุ่งไปที่ 1.0 พอดีในขณะที่ต้องการการกระจายความเสี่ยงมากที่สุด ผู้ปรับแต่ง mean-variance ที่สมมติว่าความสัมพันธ์มีความเสถียรจะประเมินความเสี่ยงพอร์ตโฟลิโอต่ำกว่าความเป็นจริงอย่างมาก

ปัญหาหลักของ Pearson correlation สำหรับคริปโต:

  1. การแจกแจงที่ไม่ใช่เชิงวงรี ผลตอบแทนของคริปโตแสดงความเบ้และความโด่งอย่างมีนัยสำคัญ ผลตอบแทนรายวันของ BTC มักแสดงค่า kurtosis สูงกว่า 10 (การแจกแจงแบบปกติ: 3)
  2. การพึ่งพาแบบอสมมาตร สินทรัพย์มีแนวโน้มมีความสัมพันธ์สูงขึ้นในช่วงที่ตลาดตกกว่าในช่วงที่ตลาดขึ้น ปรากฏการณ์ "correlation breakdown" นี้มีหลักฐานยืนยันแล้วในตลาดหุ้น และยิ่งเด่นชัดกว่าในคริปโต
  3. การพึ่งพาที่หาง (Tail dependence) ความน่าจะเป็นที่สินทรัพย์สองชิ้นจะประสบกับการสูญเสียสุดขั้วพร้อมกันไม่ถูกจับโดยความสัมพันธ์เชิงเส้น คุณสามารถมีสินทรัพย์สองชิ้นที่มีความสัมพันธ์เหมือนกันแต่มีการพึ่งพาที่หางแตกต่างกันอย่างสิ้นเชิง

ทฤษฎีบทของ Sklar: รากฐานสำคัญ

ทฤษฎีบทของ Sklar (1959) ระบุว่าการแจกแจงร่วมหลายตัวแปรใดๆ F(x1,x2,,xd)F(x_1, x_2, \ldots, x_d) สามารถแยกออกได้เป็น:

F(x1,x2,,xd)=C(F1(x1),F2(x2),,Fd(xd))F(x_1, x_2, \ldots, x_d) = C\bigl(F_1(x_1), F_2(x_2), \ldots, F_d(x_d)\bigr)

โดยที่ FiF_i คือฟังก์ชันการแจกแจงส่วนชาย และ C:[0,1]d[0,1]C: [0,1]^d \to [0,1] คือ copula — ฟังก์ชันที่เข้ารหัสโครงสร้างการพึ่งพาทั้งหมดระหว่างตัวแปร

ในทางกลับกัน หากส่วนชายมีความต่อเนื่อง copula CC จะเป็นค่าเฉพาะ

การแยกส่วนนี้มีพลังมากเพราะช่วยให้เรา:

  • สร้างแบบจำลองการแจกแจงส่วนชายของแต่ละสินทรัพย์แยกกัน (โดยใช้ GARCH, EVT หรือการแจกแจงใดก็ตามที่เหมาะสม)
  • สร้างแบบจำลองโครงสร้างการพึ่งพาอย่างอิสระผ่าน copula
  • รวมเข้าด้วยกันเพื่อให้ได้การแจกแจงร่วมเต็มรูปแบบ

ความหนาแน่นของการแจกแจงร่วมแยกได้เป็น:

f(x1,,xd)=c(F1(x1),,Fd(xd))i=1dfi(xi)f(x_1, \ldots, x_d) = c\bigl(F_1(x_1), \ldots, F_d(x_d)\bigr) \cdot \prod_{i=1}^{d} f_i(x_i)

โดยที่ cc คือความหนาแน่นของ copula และ fif_i คือความหนาแน่นส่วนชาย

ตระกูล Copula และคุณสมบัติของพวกมัน

การเปรียบเทียบการพึ่งพาที่หางระหว่างตระกูล copula ต่างๆ

Gaussian Copula

Gaussian copula ถูกกำหนดพารามิเตอร์โดยเมทริกซ์สหสัมพันธ์ Σ\Sigma:

CΣGauss(u1,,ud)=ΦΣ(Φ1(u1),,Φ1(ud))C_{\Sigma}^{\text{Gauss}}(u_1, \ldots, u_d) = \Phi_{\Sigma}\bigl(\Phi^{-1}(u_1), \ldots, \Phi^{-1}(u_d)\bigr)

โดยที่ ΦΣ\Phi_{\Sigma} คือ CDF ของการแจกแจงปกติหลายตัวแปร และ Φ1\Phi^{-1} คือฟังก์ชัน quantile ของการแจกแจงปกติหนึ่งตัวแปร

การพึ่งพาที่หาง: λL=λU=0\lambda_L = \lambda_U = 0 (สำหรับ ρ<1\rho < 1)

Gaussian copula มีการพึ่งพาที่หาง ศูนย์ — ซึ่งประเมินความน่าจะเป็นของเหตุการณ์รุนแรงร่วมกันต่ำเกินไปอย่างเป็นระบบ นี่คือปัจจัยสำคัญในการตั้งราคา CDO ก่อนปี 2008 และมันเป็นอันตรายพอๆ กันสำหรับการสร้างแบบจำลองความเสี่ยงคริปโต

Student's t-Copula

t-copula นำการพึ่งพาที่หางแบบสมมาตรผ่านพารามิเตอร์จำนวนองศาอิสระ ν\nu:

Cν,Σt(u1,,ud)=tν,Σ(tν1(u1),,tν1(ud))C_{\nu, \Sigma}^{t}(u_1, \ldots, u_d) = t_{\nu, \Sigma}\bigl(t_{\nu}^{-1}(u_1), \ldots, t_{\nu}^{-1}(u_d)\bigr)

การพึ่งพาที่หาง:

λL=λU=2tν+1((ν+1)(1ρ)1+ρ)\lambda_L = \lambda_U = 2 \cdot t_{\nu+1}\left(-\sqrt{\frac{(\nu+1)(1-\rho)}{1+\rho}}\right)

สำหรับ ν=4\nu = 4 และ ρ=0.5\rho = 0.5 จะได้ λ0.18\lambda \approx 0.18 — ความน่าจะเป็น 18% ที่สินทรัพย์ทั้งสองจะอยู่ใน quantile ที่แย่ที่สุดพร้อมกัน ค่า ν\nu ที่ต่ำกว่า (หางที่หนักกว่า) จะเพิ่มความน่าจะเป็นนี้ ตลาดคริปโตที่มีผลตอบแทนหางอ้วน โดยทั่วไปต้องการ ν\nu ในช่วง 3-8

t-copula เป็นการปรับปรุงที่สำคัญเหนือ Gaussian แต่มันบังคับให้มีการพึ่งพาที่หาง แบบสมมาตร (λL=λU\lambda_L = \lambda_U) ในทางปฏิบัติ สินทรัพย์คริปโตมักแสดงการพึ่งพาที่หางล่างที่แข็งแกร่งกว่า (ตกพร้อมกัน) มากกว่าการพึ่งพาที่หางบน (ขึ้นพร้อมกัน)

Clayton Copula

Clayton copula จับ การพึ่งพาที่หางล่าง — ซึ่งเป็นพฤติกรรมการรวมตัวในช่วงตกต่ำแบบอสมมาตรที่เราเห็นในคริปโตพอดี:

CθClayton(u1,u2)=(u1θ+u2θ1)1/θ,θ>0C_{\theta}^{\text{Clayton}}(u_1, u_2) = \left(u_1^{-\theta} + u_2^{-\theta} - 1\right)^{-1/\theta}, \quad \theta > 0

การพึ่งพาที่หาง: λL=21/θ\lambda_L = 2^{-1/\theta}, λU=0\lambda_U = 0

เมื่อ θ\theta เพิ่มขึ้น การพึ่งพาที่หางล่างจะแข็งแกร่งขึ้น สำหรับ θ=2\theta = 2, λL0.71\lambda_L \approx 0.71 — ความน่าจะเป็นสูงมากสำหรับการขาดทุนสุดขั้วร่วมกัน

Gumbel Copula

Gumbel copula เป็นภาพสะท้อน — มันจับ การพึ่งพาที่หางบน:

CθGumbel(u1,u2)=exp([(lnu1)θ+(lnu2)θ]1/θ),θ1C_{\theta}^{\text{Gumbel}}(u_1, u_2) = \exp\left(-\left[(-\ln u_1)^{\theta} + (-\ln u_2)^{\theta}\right]^{1/\theta}\right), \quad \theta \geq 1

การพึ่งพาที่หาง: λL=0\lambda_L = 0, λU=221/θ\lambda_U = 2 - 2^{1/\theta}

Frank Copula

Frank copula มีการพึ่งพาที่หาง ศูนย์ ในทั้งสองหาง (λL=λU=0\lambda_L = \lambda_U = 0) ทำให้เหมาะสำหรับการสร้างแบบจำลองการพึ่งพาในส่วนกลางของการแจกแจงโดยไม่มีผลที่หาง:

CθFrank(u1,u2)=1θln(1+(eθu11)(eθu21)eθ1)C_{\theta}^{\text{Frank}}(u_1, u_2) = -\frac{1}{\theta}\ln\left(1 + \frac{(e^{-\theta u_1}-1)(e^{-\theta u_2}-1)}{e^{-\theta}-1}\right)

การเลือก Copula ที่เหมาะสมสำหรับคริปโต

สำหรับพอร์ตโฟลิโอคริปโต หลักฐานเชิงประจักษ์ชี้ไปที่:

  • Clayton หรือ rotated Gumbel (survival Gumbel) สำหรับการพึ่งพาที่หางล่าง — จับการแพร่กระจายของการตกต่ำ
  • t-copula เป็นตัวเลือกอเนกประสงค์ที่แข็งแกร่งเมื่อการพึ่งพาที่หางแบบสมมาตรเป็นที่ยอมรับ
  • Joe copula สำหรับการจับการพึ่งพาที่หางบนที่แข็งแกร่งในช่วงราคาขึ้น

การวิจัยของ Bruhn และ Jeleskovic (2024) พบว่าโมเดล GARCH-copula โดยเฉพาะอย่างยิ่งที่ใช้ Student's t margins กับ t-copulas มีประสิทธิภาพเหนือกว่าแนวทาง mean-variance และ historical CVaR อย่างสม่ำเสมอทั้งในช่วงตกต่ำ (2022) ฟื้นตัว (2023) และมีเสถียรภาพ (2024) ของตลาดคริปโต

คำสาปแห่งมิติ: เข้าสู่ Vine Copulas

โครงสร้างต้นไม้ vine copula สำหรับพอร์ตโฟลิโอคริปโต

Copulas หลายตัวแปรมาตรฐาน (Gaussian, t-copula) ขยายสู่มิติสูงได้แต่กำหนดสมมติฐานที่จำกัด Archimedean copulas (Clayton, Gumbel, Frank) มีธรรมชาติเป็นสองตัวแปร — การขยายไปสู่มิติ d>2d > 2 ต้องการให้ทุกคู่แบ่งปันพารามิเตอร์การพึ่งพาเดียวกัน ซึ่งไม่สมจริง

Vine copulas แก้ปัญหานี้โดยการแยก copula มิติ dd ออกเป็นชุดของ copulas สองตัวแปรที่จัดเรียงในโครงสร้างต้นไม้ แต่ละคู่ของตัวแปร (ภายใต้เงื่อนไขของตัวอื่น) ได้รับตระกูล copulas สองตัวแปรและพารามิเตอร์ของตัวเอง

การก่อสร้าง Pair-Copula

สำหรับความหนาแน่นมิติ dd การแยกตัวประกอบ vine copula คือ:

f(x1,,xd)=i=1dfi(xi)j=1d1i=1djci,i+ji+1,,i+j1f(x_1, \ldots, x_d) = \prod_{i=1}^{d} f_i(x_i) \cdot \prod_{j=1}^{d-1}\prod_{i=1}^{d-j} c_{i,i+j|i+1,\ldots,i+j-1}

โดยที่ ci,jSc_{i,j|S} คือความหนาแน่น copula สองตัวแปรสำหรับตัวแปร ii และ jj ภายใต้เงื่อนไขของเซต SS

Vine copula มิติ dd ต้องการ (d2)=d(d1)/2\binom{d}{2} = d(d-1)/2 copulas คู่ สำหรับพอร์ตโฟลิโอคริปโต 10 สินทรัพย์ นั่นคือ 45 pair copulas โดยแต่ละอันอาจมาจากตระกูลที่แตกต่างกัน

โครงสร้าง Vine: C-Vine, D-Vine, R-Vine

C-vine (Canonical vine): แต่ละต้นไม้มีโหนดรากเดียวที่เชื่อมต่อกับโหนดอื่นทั้งหมด ดีที่สุดเมื่อตัวแปรหนึ่งครอบงำ เช่น BTC ในฐานะตัวขับเคลื่อนตลาด

Tree 1:    BTC --- ETH
           BTC --- SOL
           BTC --- AVAX
           BTC --- DOT

Tree 2:    ETH|BTC --- SOL|BTC
           ETH|BTC --- AVAX|BTC
           ETH|BTC --- DOT|BTC

D-vine (Drawable vine): โครงสร้างเส้นทางตามลำดับ ดีที่สุดเมื่อตัวแปรมีลำดับธรรมชาติ (เช่น ตาม market cap หรือกลุ่มธุรกิจ)

R-vine (Regular vine): โครงสร้างที่ทั่วไปที่สุด — ลำดับต้นไม้ที่ถูกต้องใดก็ได้ R-vines ครอบคลุมทั้ง C-vines และ D-vines

การวิจัยเกี่ยวกับพอร์ตโฟลิโอสกุลเงินดิจิทัลแนะนำว่าโครงสร้าง D-vine มักให้การพยากรณ์ VaR ที่เหนือกว่าเมื่อเปรียบเทียบกับ C-vine และ R-vine สำหรับสินทรัพย์คริปโต แม้ว่าจะขึ้นอยู่กับองค์ประกอบพอร์ตโฟลิโอเฉพาะ

เหตุใด Vine Copulas จึงสำคัญสำหรับคริปโต

พอร์ตโฟลิโอของสินทรัพย์คริปโต 8 ชิ้นที่สร้างแบบจำลองด้วย Clayton copula เดี่ยวบังคับให้ 28 คู่ทั้งหมดแบ่งปัน θ\theta เดียวกัน แต่ BTC-ETH อาจมี θClayton=3.5\theta_{\text{Clayton}} = 3.5 (การพึ่งพาในช่วงตกต่ำที่แข็งแกร่ง) ขณะที่ SOL-AVAX อาจมี θ=1.2\theta = 1.2 (ปานกลาง) Vine copulas ช่วยให้แต่ละคู่แสดงโครงสร้างการพึ่งพาของตัวเอง:

  • BTC-ETH: t-copula (ν=4\nu=4, ρ=0.72\rho=0.72)
  • BTC-SOL: Clayton (θ=2.1\theta=2.1)
  • ETH-AVAX: Frank (θ=5.3\theta=5.3)
  • SOL-DOT | BTC: Gumbel (θ=1.8\theta=1.8)

ความยืดหยุ่นนี้มีความสำคัญต่อการประมาณความเสี่ยงพอร์ตโฟลิโอที่แม่นยำ

การสร้างแบบจำลองส่วนชาย: GARCH-EVT

ก่อนที่จะปรับ copula เราต้องแปลงชุดผลตอบแทนของแต่ละสินทรัพย์ให้เป็นตัวแปรสม่ำเสมอ [0,1][0,1] ("การแปลงอินทิกรัลของความน่าจะเป็น") กระบวนการมาตรฐาน:

  1. ปรับโมเดล GARCH กับชุดผลตอบแทนของแต่ละสินทรัพย์เพื่อจับความผันผวนที่แปรผันตามเวลา
  2. แยกเศษเหลือมาตรฐาน zt=(rtμt)/σtz_t = (r_t - \mu_t) / \sigma_t
  3. ปรับหาง โดยใช้ Extreme Value Theory (EVT) — โดยเฉพาะ Generalized Pareto Distribution (GPD) สำหรับหางบนและหางล่างที่เกินเกณฑ์ (โดยทั่วไป percentile ที่ 5 และ 95)
  4. ใช้ CDF เชิงประจักษ์ สำหรับส่วนกลางของการแจกแจง
  5. ใช้การแปลงอินทิกรัลของความน่าจะเป็น เพื่อให้ได้การสังเกตแบบสม่ำเสมอเทียม ui,t=F^i(zi,t)u_{i,t} = \hat{F}_i(z_{i,t})

วิธี GARCH-EVT นี้มักเรียกว่าวิธี "กึ่งพารามิเตอร์" มันจับได้อย่างถูกต้อง:

  • การรวมกลุ่มของความผันผวน (GARCH)
  • หางอ้วน (GPD จาก EVT)
  • รูปร่างโดยรวมของการแจกแจง (CDF เชิงประจักษ์สำหรับส่วนกลาง)

สำหรับสินทรัพย์คริปโต โมเดล EGARCH(1,1) หรือ GJR-GARCH(1,1) ที่มีนวัตกรรม Student's t มีแนวโน้มทำงานได้ดี เนื่องจากมันจับการตอบสนองความผันผวนที่ไม่สมมาตร (ข่าวร้ายเพิ่มความผันผวนมากกว่าข่าวดี)

VaR และ CVaR ของพอร์ตโฟลิโอด้วย Copulas

มูลค่าความเสี่ยง (VaR)

VaR ของพอร์ตโฟลิโอที่ระดับความเชื่อมั่น α\alpha คือ:

VaRα=inf{l:P(Ll)α}\text{VaR}_\alpha = \inf\{ l : P(L \leq l) \geq \alpha \}

โดยที่ LL คือการขาดทุนของพอร์ตโฟลิโอ ด้วย copulas เราประมาณ VaR ผ่าน Monte Carlo:

  1. จำลอง NN ตัวอย่างจาก vine copula ที่ปรับแล้ว (ในพื้นที่สม่ำเสมอ)
  2. แปลงกลับไปยังพื้นที่ผลตอบแทนโดยใช้ inverse marginal CDFs
  3. คำนวณผลตอบแทนพอร์ตโฟลิโอ: rp=iwirir_p = \sum_i w_i \cdot r_i
  4. VaR คือ α\alpha-quantile ของการแจกแจงการขาดทุนพอร์ตโฟลิโอที่จำลอง

มูลค่าความเสี่ยงตามเงื่อนไข (CVaR / Expected Shortfall)

CVaR คือการขาดทุนที่คาดหวังเมื่อการขาดทุนเกิน VaR:

CVaRα=E[LLVaRα]=11αα1VaRudu\text{CVaR}_\alpha = E[L \mid L \geq \text{VaR}_\alpha] = \frac{1}{1-\alpha}\int_{\alpha}^{1}\text{VaR}_u\, du

CVaR มีความสอดคล้อง (ตอบสนองข้อกำหนด subadditivity) ทำให้เหนือกว่า VaR สำหรับการปรับแต่งพอร์ตโฟลิโอ การประมาณ Monte Carlo ตรงไปตรงมา — เฉลี่ยการขาดทุนที่เกิน VaR

เหตุใดความเสี่ยงที่อิงกับ Copula จึงชนะความเสี่ยงที่อิงกับความสัมพันธ์

พิจารณาพอร์ตโฟลิโอสองแห่งที่มีความสัมพันธ์คู่เหมือนกัน 0.5:

  • พอร์ตโฟลิโอ A: การพึ่งพาแบบ Gaussian copula (ไม่มีการพึ่งพาที่หาง)
  • พอร์ตโฟลิโอ B: การพึ่งพาแบบ Clayton copula (θ=2\theta = 2, λL=0.71\lambda_L = 0.71)

ที่ระดับความเชื่อมั่น 99% พอร์ตโฟลิโอ B จะมี VaR และ CVaR สูงกว่าอย่างมีนัยสำคัญ เพราะ Clayton copula สร้างแบบจำลองแนวโน้มที่สินทรัพย์ตกพร้อมกันได้อย่างถูกต้อง Gaussian copula ประเมินความเสี่ยงนี้ต่ำเกินไปโดยสมมติว่าการเคลื่อนที่ร่วมสุดขั้วเกิดขึ้นน้อยมาก

ในการศึกษาเชิงประจักษ์เกี่ยวกับพอร์ตโฟลิโอคริปโต ความแตกต่างใน CVaR 99% ระหว่างโมเดล Gaussian และ vine copula อาจเกิน 30-40% หมายความว่าโมเดลที่อิงกับความสัมพันธ์อาจประเมินความเสี่ยงที่หางต่ำไปถึงหนึ่งในสามหรือมากกว่า

การนำไปใช้: Python กับ pyvinecopulib

นี่คือกระบวนการสมบูรณ์สำหรับการปรับ vine copula กับผลตอบแทนคริปโตและการประมาณ VaR/CVaR ของพอร์ตโฟลิโอ

ขั้นตอนที่ 1: การเตรียมข้อมูลและการปรับส่วนชาย

import numpy as np
import pandas as pd
from arch import arch_model
from scipy import stats
import pyvinecopulib as pv

def fetch_crypto_returns(symbols, start="2023-01-01", end="2025-12-31"):
    """
    Fetch daily returns for a list of crypto symbols.
    Replace with your data source (ccxt, yfinance, etc.)
    """
    import yfinance as yf
    prices = yf.download(
        [f"{s}-USD" for s in symbols],
        start=start, end=end
    )["Close"]
    prices.columns = symbols
    returns = np.log(prices / prices.shift(1)).dropna()
    return returns

symbols = ["BTC", "ETH", "SOL", "AVAX", "DOT", "LINK", "MATIC", "ATOM"]
returns = fetch_crypto_returns(symbols)

def fit_garch_marginal(series, dist="t"):
    """
    Fit GJR-GARCH(1,1) with Student-t innovations.
    Returns standardized residuals and the fitted model.
    """
    model = arch_model(
        series * 100,  # scale for numerical stability
        vol="GARCH",
        p=1, o=1, q=1,  # GJR-GARCH
        dist=dist,
        mean="AR",
        lags=1
    )
    result = model.fit(disp="off")
    std_resid = result.std_resid.dropna()
    return std_resid, result

residuals = {}
garch_models = {}
for sym in symbols:
    std_resid, model = fit_garch_marginal(returns[sym])
    residuals[sym] = std_resid
    garch_models[sym] = model

residuals_df = pd.DataFrame(residuals).dropna()

ขั้นตอนที่ 2: การแปลงอินทิกรัลของความน่าจะเป็น

def semi_parametric_pit(residuals, tail_threshold=0.05):
    """
    Semi-parametric probability integral transform:
    - GPD for tails beyond threshold
    - Empirical CDF for the body
    Returns pseudo-uniform observations in [0, 1].
    """
    n = len(residuals)
    u = np.zeros(n)
    sorted_resid = np.sort(residuals)

    lower_thresh = np.quantile(residuals, tail_threshold)
    upper_thresh = np.quantile(residuals, 1 - tail_threshold)

    for i, x in enumerate(residuals):
        if x <= lower_thresh:
            lower_exceedances = -(residuals[residuals <= lower_thresh] - lower_thresh)
            shape, _, scale = stats.genpareto.fit(lower_exceedances, floc=0)
            u[i] = tail_threshold * (
                1 - stats.genpareto.cdf(-(x - lower_thresh), shape, scale=scale)
            )
        elif x >= upper_thresh:
            upper_exceedances = residuals[residuals >= upper_thresh] - upper_thresh
            shape, _, scale = stats.genpareto.fit(upper_exceedances, floc=0)
            u[i] = 1 - tail_threshold * (
                1 - stats.genpareto.cdf(x - upper_thresh, shape, scale=scale)
            )
        else:
            u[i] = np.mean(residuals <= x)

    u = np.clip(u, 1e-6, 1 - 1e-6)
    return u

U = np.column_stack([
    semi_parametric_pit(residuals_df[sym].values)
    for sym in symbols
])

ขั้นตอนที่ 3: ปรับ Vine Copula

controls = pv.FitControlsVinecop(
    family_set=[
        pv.BicopFamily.student,
        pv.BicopFamily.clayton,
        pv.BicopFamily.gumbel,
        pv.BicopFamily.frank,
        pv.BicopFamily.joe,
        pv.BicopFamily.bb1,       # Clayton-Gumbel mixture
        pv.BicopFamily.bb7,       # Joe-Clayton mixture
        pv.BicopFamily.gaussian,
    ],
    selection_criterion="bic",    # BIC for model selection
    tree_criterion="tau",          # Kendall's tau for tree structure
    nonparametric_method="constant",
    trunc_lvl=5,                   # Truncate after 5 trees
)

vine = pv.Vinecop(U, controls=controls)

print(f"Log-likelihood: {vine.loglik(U):.2f}")
print(f"AIC: {vine.aic(U):.2f}")
print(f"BIC: {vine.bic(U):.2f}")

for i in range(vine.order.shape[0] - 1):
    pair = vine.get_pair_copula(0, i)
    print(f"Tree 1, Edge {i}: {pair.family} "
          f"(params: {pair.parameters})")

ขั้นตอนที่ 4: Monte Carlo VaR และ CVaR

def estimate_var_cvar(vine, garch_models, symbols, weights,
                       n_sim=50_000, alpha=0.99, seed=42):
    """
    Estimate portfolio VaR and CVaR using Monte Carlo simulation
    from the fitted vine copula.
    """
    U_sim = vine.simulate(n=n_sim, seeds=[seed])

    returns_sim = np.zeros((n_sim, len(symbols)))
    for j, sym in enumerate(symbols):
        model = garch_models[sym]
        forecasts = model.forecast(horizon=1)
        mu = forecasts.mean.iloc[-1, 0] / 100  # unscale
        sigma = np.sqrt(forecasts.variance.iloc[-1, 0]) / 100

        nu = model.params.get("nu", 5)
        z_sim = stats.t.ppf(U_sim[:, j], df=nu)
        returns_sim[:, j] = mu + sigma * z_sim

    weights = np.array(weights)
    portfolio_returns = returns_sim @ weights

    losses = -portfolio_returns

    var = np.quantile(losses, alpha)

    cvar = np.mean(losses[losses >= var])

    return var, cvar, portfolio_returns

weights = [1.0 / len(symbols)] * len(symbols)

var_99, cvar_99, sim_returns = estimate_var_cvar(
    vine, garch_models, symbols, weights,
    n_sim=100_000, alpha=0.99
)

print(f"1-day 99% VaR:  {var_99*100:.2f}%")
print(f"1-day 99% CVaR: {cvar_99*100:.2f}%")

from scipy.stats import norm
mu_p = sim_returns.mean()
sigma_p = sim_returns.std()
var_gauss = -(mu_p + sigma_p * norm.ppf(0.01))
print(f"\nGaussian VaR:   {var_gauss*100:.2f}%")
print(f"Copula/Gaussian ratio: {var_99/var_gauss:.2f}x")

ขั้นตอนที่ 5: การวิเคราะห์การพึ่งพาที่หาง

def compute_tail_dependence(vine, symbols):
    """
    Extract lower and upper tail dependence coefficients
    from the first tree of the vine copula.
    """
    results = []
    order = vine.order
    n_edges = order.shape[0] - 1

    for i in range(n_edges):
        pair = vine.get_pair_copula(0, i)
        u_pair = pair.simulate(n=100_000, seeds=[42])
        q = 0.01  # 1st percentile

        mask_lower = (u_pair[:, 0] <= q)
        lambda_L = np.mean(u_pair[mask_lower, 1] <= q) if mask_lower.sum() > 0 else 0

        mask_upper = (u_pair[:, 0] >= 1 - q)
        lambda_U = np.mean(u_pair[mask_upper, 1] >= 1 - q) if mask_upper.sum() > 0 else 0

        i_idx = order[0]
        j_idx = order[i + 1]
        results.append({
            "pair": f"{symbols[i_idx]}-{symbols[j_idx]}",
            "family": str(pair.family),
            "lambda_L": round(lambda_L, 4),
            "lambda_U": round(lambda_U, 4),
        })

    return pd.DataFrame(results)

tail_dep = compute_tail_dependence(vine, symbols)
print(tail_dep.to_string(index=False))

ผลลัพธ์ทั่วไปสำหรับพอร์ตโฟลิโอคริปโตอาจมีลักษณะดังนี้:

Pair Family λL\lambda_L λU\lambda_U
BTC-ETH student 0.22 0.22
BTC-SOL clayton 0.35 0.00
BTC-AVAX bb7 0.28 0.12
BTC-DOT student 0.18 0.18
BTC-LINK clayton 0.31 0.00
BTC-MATIC frank 0.00 0.00
BTC-ATOM gumbel 0.00 0.15

สังเกตว่าแต่ละคู่สามารถมีโครงสร้างการพึ่งพาที่แตกต่างกันอย่างสิ้นเชิง BTC-SOL แสดงการพึ่งพาที่หางล่างที่แข็งแกร่ง (Clayton) โดยมีการพึ่งพาที่หางบนเป็นศูนย์ — พวกมันตกพร้อมกันแต่ไม่จำเป็นต้องขึ้นพร้อมกัน BTC-MATIC ไม่แสดงการพึ่งพาที่หางเลย (Frank) แสดงให้เห็นประโยชน์การกระจายความเสี่ยงบางส่วนแม้ในสถานการณ์รุนแรง

การ Backtest โมเดล Copula VaR

โมเดล VaR จะมีประโยชน์ก็ต่อเมื่อได้รับการปรับเทียบอย่างดี การ backtest มาตรฐานคำนวณ VaR violations — วันที่การขาดทุนจริงเกิน VaR ที่พยากรณ์ — และทดสอบว่าอัตราการละเมิดตรงกับอัตราที่คาดหวังหรือไม่

def backtest_var(returns, symbols, weights, window=500,
                 alpha=0.99, n_sim=20_000):
    """
    Rolling-window VaR backtest using vine copula.
    """
    violations = []
    var_series = []
    T = len(returns)

    for t in range(window, T):
        window_returns = returns.iloc[t-window:t]

        U_window = np.zeros((window, len(symbols)))
        models_t = {}
        for j, sym in enumerate(symbols):
            std_resid, model = fit_garch_marginal(window_returns[sym])
            models_t[sym] = model
            u = pv.to_pseudo_obs(std_resid.values.reshape(-1, 1))
            U_window[:len(u), j] = u.ravel()

        U_clean = U_window[~np.any(U_window == 0, axis=1)]
        vine_t = pv.Vinecop(U_clean, controls=controls)

        var_t, _, _ = estimate_var_cvar(
            vine_t, models_t, symbols, weights,
            n_sim=n_sim, alpha=alpha
        )
        var_series.append(var_t)

        actual_return = (returns.iloc[t][symbols].values
                         * np.array(weights)).sum()
        violations.append(-actual_return > var_t)

    violation_rate = np.mean(violations)
    expected_rate = 1 - alpha
    print(f"Expected violation rate: {expected_rate:.4f}")
    print(f"Actual violation rate:   {violation_rate:.4f}")
    print(f"Number of violations:    {sum(violations)} / {len(violations)}")

    return violations, var_series

โมเดล VaR 99% ที่ได้รับการปรับเทียบอย่างดีควรมีอัตราการละเมิดใกล้เคียง 1% หากอัตราสูงกว่าอย่างมีนัยสำคัญ แสดงว่าโมเดลประเมินความเสี่ยงต่ำเกินไป หากต่ำกว่าอย่างมีนัยสำคัญ แสดงว่าโมเดลอนุรักษ์นิยมเกินไป

ข้อพิจารณาในทางปฏิบัติ

ต้นทุนการคำนวณ

การปรับ vine copula มีความซับซ้อน O(d2n)O(d^2 \cdot n) ต่อระดับต้นไม้ สำหรับพอร์ตโฟลิโอ 10 สินทรัพย์ที่มีหน้าต่างกลิ้ง 500 วัน การ backtest เต็มรูปแบบที่มีการจำลอง Monte Carlo 50,000 ครั้งต่อขั้นตอนอาจใช้เวลาหลายชั่วโมง กลยุทธ์เพื่อจัดการนี้:

  • Truncated vines: ตั้งค่า trunc_lvl=3 หรือ trunc_lvl=4 — ต้นไม้สูงกว่าจับการพึ่งพาตามเงื่อนไขที่อ่อนแอกว่าซึ่งมีส่วนต่อความเสี่ยงน้อยกว่า
  • จำนวนการจำลองที่ลดลง: การจำลอง 10,000-20,000 ครั้งมักเพียงพอสำหรับ VaR 99%
  • การคำนวณแบบขนาน: การปรับ GARCH สำหรับแต่ละสินทรัพย์เป็นอิสระและสามารถขนานได้
  • การแคชโมเดล: ปรับ copula รายสัปดาห์แทนรายวัน โดยอัปเดตเฉพาะการพยากรณ์ GARCH

การรับรู้เรจิม

ตลาดคริปโตแสดงเรจิมที่แตกต่างกันอย่างชัดเจน (กระทิง, หมี, ราบ, เหตุการณ์ความผันผวนสูง) Vine copula เดี่ยวที่ปรับกับตัวอย่างทั้งหมดอาจไม่จับการพึ่งพาที่ขึ้นอยู่กับเรจิม พิจารณา:

  • หน้าต่างกลิ้ง 250-500 วัน
  • Copulas ที่สลับเรจิม ซึ่งพารามิเตอร์ copula ขึ้นอยู่กับสถานะ Markov แฝง
  • การสังเกตที่ถ่วงน้ำหนักแบบเอกซ์โปเนนเชียล ที่ให้น้ำหนักมากขึ้นกับข้อมูลล่าสุด

ข้อผิดพลาดทั่วไป

  1. ลืม PIT การป้อนผลตอบแทนดิบโดยตรงเข้า copula แทนการสังเกตแบบสม่ำเสมอเทียมจะให้ผลลัพธ์ที่ไม่มีความหมาย ต้องแปลงเป็น uniform margins ก่อนเสมอ
  2. การ overfit ด้วยตระกูลมากเกินไป การรวมทุกตระกูลสองตัวแปรที่เป็นไปได้ในชุดการเลือกอาจนำไปสู่การ overfit โดยเฉพาะกับตัวอย่างสั้น ใช้ BIC สำหรับการเลือกโมเดลและพิจารณาจำกัดให้เหลือ 4-5 ตระกูล
  3. ละเลยการพึ่งพาแบบอนุกรมเวลา Copulas สร้างแบบจำลองการพึ่งพาตัดขวางที่จุดเดียวในเวลา หากคุณข้ามขั้นตอน GARCH และป้อนผลตอบแทนที่มี autocorrelation เข้า copula การพึ่งพาที่ประมาณจะถูกปนเปื้อนด้วยผลแบบอนุกรมเวลา
  4. Copulas แบบคงที่ในตลาดแบบไดนามิก Copula ที่ปรับกับข้อมูลตลาดกระทิงปี 2021 จะได้รับการปรับเทียบไม่ดีสำหรับการตกต่ำปี 2022 ต้องใช้หน้าต่างกลิ้งหรือขยายเสมอ

สรุป

โมเดล Copula — โดยเฉพาะ vine copulas — มอบกรอบงานที่เข้มแข็งทางคณิตศาสตร์สำหรับการสร้างแบบจำลองความเสี่ยงร่วมของพอร์ตโฟลิโอคริปโตที่ไปไกลกว่าสิ่งที่ความสัมพันธ์เชิงเส้นสามารถจับได้ ข้อได้เปรียบหลัก:

  • การสร้างแบบจำลองส่วนชายและการพึ่งพาแยกกัน ผ่านทฤษฎีบทของ Sklar
  • การพึ่งพาที่หางที่ยืดหยุ่น ผ่านการเลือกตระกูล copula ที่เหมาะสม (Clayton สำหรับการแพร่กระจายตลาดตก, Gumbel สำหรับการเคลื่อนไหวร่วมช่วงขึ้น, t-copula สำหรับหางสมมาตร)
  • การขยายมิติสูง ผ่านการแยกตัวประกอบ vine copula ซึ่งแต่ละคู่ของสินทรัพย์ได้รับ copulas สองตัวแปรของตัวเอง
  • การประมาณ VaR/CVaR ที่แม่นยำ ที่คำนึงถึงการพึ่งพาที่ไม่เป็นเชิงเส้นและอสมมาตร — สำคัญมากสำหรับการบริหารความเสี่ยงในตลาดที่ "ทุกอย่างตกพร้อมกัน" เป็นบรรทัดฐาน ไม่ใช่ข้อยกเว้น

กระบวนการ GARCH-EVT-Copula ปัจจุบันเป็นแนวทางมาตรฐานที่กองทุนเฮดจ์เชิงปริมาณและโต๊ะความเสี่ยงที่มุ่งเน้นคริปโต ด้วยไลบรารีเช่น pyvinecopulib อุปสรรคการนำไปใช้ต่ำพอที่นักเทรดเชิงระบบใดก็ตามสามารถรวมการสร้างแบบจำลองความเสี่ยงที่อิงกับ copula เข้ากับเวิร์กโฟลว์การจัดการพอร์ตโฟลิโอของตน

โค้ดในบทความนี้ให้จุดเริ่มต้นที่ใช้งานได้ สำหรับการใช้งานจริง คุณจะเพิ่มการตรวจสอบข้ามกลุ่มที่เหมาะสมสำหรับการเลือกลำดับ GARCH โมเดลส่วนชายที่ซับซ้อนกว่า (เช่น EGARCH พร้อมผลกระทบการเลเวอเรจ หรือการวัดความผันผวนที่เกิดขึ้นจริงโดยใช้ข้อมูลระหว่างวัน) และการทดสอบความเครียดภายใต้พารามิเตอร์ copula สมมติที่ปรับเทียบกับเหตุการณ์วิกฤตในอดีต


อ้างอิง

  • Sklar, A. (1959). Fonctions de repartition a n dimensions et leurs marges. Publications de l'Institut de Statistique de l'Universite de Paris, 8, 229-231.
  • Joe, H. (2014). Dependence Modeling with Copulas. Chapman and Hall/CRC.
  • Aas, K., Czado, C., Frigessi, A., & Bakken, H. (2009). Pair-copula constructions of multiple dependence. Insurance: Mathematics and Economics, 44(2), 182-198.
  • Jeleskovic, V. & Bruhn, L. (2024). Cryptocurrency portfolio optimization: Utilizing a GARCH-Copula model within the Markowitz framework. Journal of Corporate Accounting & Finance.
  • Nagler, T. & Vatter, T. (2023). pyvinecopulib: A Python library for vine copula models. GitHub.
  • Tiwari, A. K., et al. (2020). Modeling risk dependence and portfolio VaR forecast through vine copula for cryptocurrencies. PLOS ONE, 15(1), e0242102.
ข้อจำกัดความรับผิดชอบ: ข้อมูลที่ให้ไว้ในบทความนี้มีไว้เพื่อการศึกษาและให้ข้อมูลเท่านั้น และไม่ถือเป็นคำแนะนำทางการเงิน การลงทุน หรือการเทรด การเทรดสกุลเงินดิจิทัลมีความเสี่ยงสูงที่จะขาดทุน

ผู้เขียน

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

ก้าวนำหน้าตลาด

สมัครรับจดหมายข่าวของเราเพื่อรับข้อมูลเชิงลึกการเทรดด้วย AI เฉพาะ การวิเคราะห์ตลาด และการอัปเดตแพลตฟอร์ม

เราเคารพความเป็นส่วนตัวของคุณ ยกเลิกการสมัครได้ทุกเมื่อ