โมเดล 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 สำหรับคริปโต:
- การแจกแจงที่ไม่ใช่เชิงวงรี ผลตอบแทนของคริปโตแสดงความเบ้และความโด่งอย่างมีนัยสำคัญ ผลตอบแทนรายวันของ BTC มักแสดงค่า kurtosis สูงกว่า 10 (การแจกแจงแบบปกติ: 3)
- การพึ่งพาแบบอสมมาตร สินทรัพย์มีแนวโน้มมีความสัมพันธ์สูงขึ้นในช่วงที่ตลาดตกกว่าในช่วงที่ตลาดขึ้น ปรากฏการณ์ "correlation breakdown" นี้มีหลักฐานยืนยันแล้วในตลาดหุ้น และยิ่งเด่นชัดกว่าในคริปโต
- การพึ่งพาที่หาง (Tail dependence) ความน่าจะเป็นที่สินทรัพย์สองชิ้นจะประสบกับการสูญเสียสุดขั้วพร้อมกันไม่ถูกจับโดยความสัมพันธ์เชิงเส้น คุณสามารถมีสินทรัพย์สองชิ้นที่มีความสัมพันธ์เหมือนกันแต่มีการพึ่งพาที่หางแตกต่างกันอย่างสิ้นเชิง
ทฤษฎีบทของ Sklar: รากฐานสำคัญ
ทฤษฎีบทของ Sklar (1959) ระบุว่าการแจกแจงร่วมหลายตัวแปรใดๆ สามารถแยกออกได้เป็น:
โดยที่ คือฟังก์ชันการแจกแจงส่วนชาย และ คือ copula — ฟังก์ชันที่เข้ารหัสโครงสร้างการพึ่งพาทั้งหมดระหว่างตัวแปร
ในทางกลับกัน หากส่วนชายมีความต่อเนื่อง copula จะเป็นค่าเฉพาะ
การแยกส่วนนี้มีพลังมากเพราะช่วยให้เรา:
- สร้างแบบจำลองการแจกแจงส่วนชายของแต่ละสินทรัพย์แยกกัน (โดยใช้ GARCH, EVT หรือการแจกแจงใดก็ตามที่เหมาะสม)
- สร้างแบบจำลองโครงสร้างการพึ่งพาอย่างอิสระผ่าน copula
- รวมเข้าด้วยกันเพื่อให้ได้การแจกแจงร่วมเต็มรูปแบบ
ความหนาแน่นของการแจกแจงร่วมแยกได้เป็น:
โดยที่ คือความหนาแน่นของ copula และ คือความหนาแน่นส่วนชาย
ตระกูล Copula และคุณสมบัติของพวกมัน

Gaussian Copula
Gaussian copula ถูกกำหนดพารามิเตอร์โดยเมทริกซ์สหสัมพันธ์ :
โดยที่ คือ CDF ของการแจกแจงปกติหลายตัวแปร และ คือฟังก์ชัน quantile ของการแจกแจงปกติหนึ่งตัวแปร
การพึ่งพาที่หาง: (สำหรับ )
Gaussian copula มีการพึ่งพาที่หาง ศูนย์ — ซึ่งประเมินความน่าจะเป็นของเหตุการณ์รุนแรงร่วมกันต่ำเกินไปอย่างเป็นระบบ นี่คือปัจจัยสำคัญในการตั้งราคา CDO ก่อนปี 2008 และมันเป็นอันตรายพอๆ กันสำหรับการสร้างแบบจำลองความเสี่ยงคริปโต
Student's t-Copula
t-copula นำการพึ่งพาที่หางแบบสมมาตรผ่านพารามิเตอร์จำนวนองศาอิสระ :
การพึ่งพาที่หาง:
สำหรับ และ จะได้ — ความน่าจะเป็น 18% ที่สินทรัพย์ทั้งสองจะอยู่ใน quantile ที่แย่ที่สุดพร้อมกัน ค่า ที่ต่ำกว่า (หางที่หนักกว่า) จะเพิ่มความน่าจะเป็นนี้ ตลาดคริปโตที่มีผลตอบแทนหางอ้วน โดยทั่วไปต้องการ ในช่วง 3-8
t-copula เป็นการปรับปรุงที่สำคัญเหนือ Gaussian แต่มันบังคับให้มีการพึ่งพาที่หาง แบบสมมาตร () ในทางปฏิบัติ สินทรัพย์คริปโตมักแสดงการพึ่งพาที่หางล่างที่แข็งแกร่งกว่า (ตกพร้อมกัน) มากกว่าการพึ่งพาที่หางบน (ขึ้นพร้อมกัน)
Clayton Copula
Clayton copula จับ การพึ่งพาที่หางล่าง — ซึ่งเป็นพฤติกรรมการรวมตัวในช่วงตกต่ำแบบอสมมาตรที่เราเห็นในคริปโตพอดี:
การพึ่งพาที่หาง: ,
เมื่อ เพิ่มขึ้น การพึ่งพาที่หางล่างจะแข็งแกร่งขึ้น สำหรับ , — ความน่าจะเป็นสูงมากสำหรับการขาดทุนสุดขั้วร่วมกัน
Gumbel Copula
Gumbel copula เป็นภาพสะท้อน — มันจับ การพึ่งพาที่หางบน:
การพึ่งพาที่หาง: ,
Frank Copula
Frank copula มีการพึ่งพาที่หาง ศูนย์ ในทั้งสองหาง () ทำให้เหมาะสำหรับการสร้างแบบจำลองการพึ่งพาในส่วนกลางของการแจกแจงโดยไม่มีผลที่หาง:
การเลือก 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

Copulas หลายตัวแปรมาตรฐาน (Gaussian, t-copula) ขยายสู่มิติสูงได้แต่กำหนดสมมติฐานที่จำกัด Archimedean copulas (Clayton, Gumbel, Frank) มีธรรมชาติเป็นสองตัวแปร — การขยายไปสู่มิติ ต้องการให้ทุกคู่แบ่งปันพารามิเตอร์การพึ่งพาเดียวกัน ซึ่งไม่สมจริง
Vine copulas แก้ปัญหานี้โดยการแยก copula มิติ ออกเป็นชุดของ copulas สองตัวแปรที่จัดเรียงในโครงสร้างต้นไม้ แต่ละคู่ของตัวแปร (ภายใต้เงื่อนไขของตัวอื่น) ได้รับตระกูล copulas สองตัวแปรและพารามิเตอร์ของตัวเอง
การก่อสร้าง Pair-Copula
สำหรับความหนาแน่นมิติ การแยกตัวประกอบ vine copula คือ:
โดยที่ คือความหนาแน่น copula สองตัวแปรสำหรับตัวแปร และ ภายใต้เงื่อนไขของเซต
Vine copula มิติ ต้องการ 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 คู่ทั้งหมดแบ่งปัน เดียวกัน แต่ BTC-ETH อาจมี (การพึ่งพาในช่วงตกต่ำที่แข็งแกร่ง) ขณะที่ SOL-AVAX อาจมี (ปานกลาง) Vine copulas ช่วยให้แต่ละคู่แสดงโครงสร้างการพึ่งพาของตัวเอง:
- BTC-ETH: t-copula (, )
- BTC-SOL: Clayton ()
- ETH-AVAX: Frank ()
- SOL-DOT | BTC: Gumbel ()
ความยืดหยุ่นนี้มีความสำคัญต่อการประมาณความเสี่ยงพอร์ตโฟลิโอที่แม่นยำ
การสร้างแบบจำลองส่วนชาย: GARCH-EVT
ก่อนที่จะปรับ copula เราต้องแปลงชุดผลตอบแทนของแต่ละสินทรัพย์ให้เป็นตัวแปรสม่ำเสมอ ("การแปลงอินทิกรัลของความน่าจะเป็น") กระบวนการมาตรฐาน:
- ปรับโมเดล GARCH กับชุดผลตอบแทนของแต่ละสินทรัพย์เพื่อจับความผันผวนที่แปรผันตามเวลา
- แยกเศษเหลือมาตรฐาน
- ปรับหาง โดยใช้ Extreme Value Theory (EVT) — โดยเฉพาะ Generalized Pareto Distribution (GPD) สำหรับหางบนและหางล่างที่เกินเกณฑ์ (โดยทั่วไป percentile ที่ 5 และ 95)
- ใช้ CDF เชิงประจักษ์ สำหรับส่วนกลางของการแจกแจง
- ใช้การแปลงอินทิกรัลของความน่าจะเป็น เพื่อให้ได้การสังเกตแบบสม่ำเสมอเทียม
วิธี GARCH-EVT นี้มักเรียกว่าวิธี "กึ่งพารามิเตอร์" มันจับได้อย่างถูกต้อง:
- การรวมกลุ่มของความผันผวน (GARCH)
- หางอ้วน (GPD จาก EVT)
- รูปร่างโดยรวมของการแจกแจง (CDF เชิงประจักษ์สำหรับส่วนกลาง)
สำหรับสินทรัพย์คริปโต โมเดล EGARCH(1,1) หรือ GJR-GARCH(1,1) ที่มีนวัตกรรม Student's t มีแนวโน้มทำงานได้ดี เนื่องจากมันจับการตอบสนองความผันผวนที่ไม่สมมาตร (ข่าวร้ายเพิ่มความผันผวนมากกว่าข่าวดี)
VaR และ CVaR ของพอร์ตโฟลิโอด้วย Copulas
มูลค่าความเสี่ยง (VaR)
VaR ของพอร์ตโฟลิโอที่ระดับความเชื่อมั่น คือ:
โดยที่ คือการขาดทุนของพอร์ตโฟลิโอ ด้วย copulas เราประมาณ VaR ผ่าน Monte Carlo:
- จำลอง ตัวอย่างจาก vine copula ที่ปรับแล้ว (ในพื้นที่สม่ำเสมอ)
- แปลงกลับไปยังพื้นที่ผลตอบแทนโดยใช้ inverse marginal CDFs
- คำนวณผลตอบแทนพอร์ตโฟลิโอ:
- VaR คือ -quantile ของการแจกแจงการขาดทุนพอร์ตโฟลิโอที่จำลอง
มูลค่าความเสี่ยงตามเงื่อนไข (CVaR / Expected Shortfall)
CVaR คือการขาดทุนที่คาดหวังเมื่อการขาดทุนเกิน VaR:
CVaR มีความสอดคล้อง (ตอบสนองข้อกำหนด subadditivity) ทำให้เหนือกว่า VaR สำหรับการปรับแต่งพอร์ตโฟลิโอ การประมาณ Monte Carlo ตรงไปตรงมา — เฉลี่ยการขาดทุนที่เกิน VaR
เหตุใดความเสี่ยงที่อิงกับ Copula จึงชนะความเสี่ยงที่อิงกับความสัมพันธ์
พิจารณาพอร์ตโฟลิโอสองแห่งที่มีความสัมพันธ์คู่เหมือนกัน 0.5:
- พอร์ตโฟลิโอ A: การพึ่งพาแบบ Gaussian copula (ไม่มีการพึ่งพาที่หาง)
- พอร์ตโฟลิโอ B: การพึ่งพาแบบ Clayton copula (, )
ที่ระดับความเชื่อมั่น 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 | ||
|---|---|---|---|
| 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 มีความซับซ้อน ต่อระดับต้นไม้ สำหรับพอร์ตโฟลิโอ 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 แฝง
- การสังเกตที่ถ่วงน้ำหนักแบบเอกซ์โปเนนเชียล ที่ให้น้ำหนักมากขึ้นกับข้อมูลล่าสุด
ข้อผิดพลาดทั่วไป
- ลืม PIT การป้อนผลตอบแทนดิบโดยตรงเข้า copula แทนการสังเกตแบบสม่ำเสมอเทียมจะให้ผลลัพธ์ที่ไม่มีความหมาย ต้องแปลงเป็น uniform margins ก่อนเสมอ
- การ overfit ด้วยตระกูลมากเกินไป การรวมทุกตระกูลสองตัวแปรที่เป็นไปได้ในชุดการเลือกอาจนำไปสู่การ overfit โดยเฉพาะกับตัวอย่างสั้น ใช้ BIC สำหรับการเลือกโมเดลและพิจารณาจำกัดให้เหลือ 4-5 ตระกูล
- ละเลยการพึ่งพาแบบอนุกรมเวลา Copulas สร้างแบบจำลองการพึ่งพาตัดขวางที่จุดเดียวในเวลา หากคุณข้ามขั้นตอน GARCH และป้อนผลตอบแทนที่มี autocorrelation เข้า copula การพึ่งพาที่ประมาณจะถูกปนเปื้อนด้วยผลแบบอนุกรมเวลา
- 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.
ผู้เขียน
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.