क्रिप्टो पोर्टफोलियो में संयुक्त जोखिम मॉडलिंग के लिए कोपुला मॉडल

रैखिक सहसंबंध से आगे - क्रिप्टोकरेंसी पोर्टफोलियो में सटीक VaR और CVaR अनुमान के लिए टेल डिपेंडेंस और संयुक्त जोखिम को पकड़ने हेतु कोपुला मॉडल का उपयोग।

कोपुला मॉडल — संयुक्त जोखिम वितरण

सहसंबंध वह पहला उपकरण है जिसकी ओर अधिकांश पोर्टफोलियो प्रबंधक विविधीकरण का आकलन करते समय रुख करते हैं। लेकिन क्रिप्टो बाज़ारों में, सहसंबंध खतरनाक रूप से भ्रामक होता है। शांत बाज़ारों के दौरान दो टोकन का पियर्सन सहसंबंध 0.3 दिख सकता है, फिर क्रैश के दौरान यह 0.95 तक उछल सकता है। रैखिक सहसंबंध अण्डाकार (elliptical) वितरणों को मानता है — एक धारणा जो क्रिप्टोकरेंसी रिटर्न में व्याप्त भारी टेल और असममित निर्भरता संरचनाओं के तहत ध्वस्त हो जाती है।

कोपुला मॉडल इसे मार्जिनल व्यवहार (प्रत्येक एसेट व्यक्तिगत रूप से कैसा व्यवहार करता है) को निर्भरता संरचना (एसेट एक साथ कैसे चलते हैं) से अलग करके हल करते हैं। स्क्लार के प्रमेय में निहित यह पृथक्करण, पोर्टफोलियो रिटर्न के पूर्ण संयुक्त वितरण को मॉडल करने के लिए एक लचीला ढांचा देता है — जिसमें वे टेल भी शामिल हैं जहां जोखिम वास्तव में रहता है।

रैखिक सहसंबंध क्रिप्टो के लिए क्यों विफल होता है

BTC, ETH, SOL, और AVAX के पोर्टफोलियो पर विचार करें। मई 2022 में Terra/Luna के पतन के दौरान, इन एसेट के बीच सहसंबंध 1.0 की ओर अभिसरित हुए, ठीक तब जब विविधीकरण की सबसे अधिक आवश्यकता थी। एक मीन-वेरिएंस ऑप्टिमाइज़र जिसने स्थिर सहसंबंधों को माना था, पोर्टफोलियो जोखिम को नाटकीय रूप से कम आंकता।

क्रिप्टो के लिए पियर्सन सहसंबंध की मूल समस्याएं:

  1. गैर-अण्डाकार वितरण। क्रिप्टो रिटर्न महत्वपूर्ण स्क्यूनेस और कर्टोसिस प्रदर्शित करते हैं। BTC के दैनिक रिटर्न नियमित रूप से 10 से ऊपर कर्टोसिस मान दिखाते हैं (सामान्य वितरण: 3)।
  2. असममित निर्भरता। एसेट रैली की तुलना में गिरावट के दौरान अधिक सहसंबद्ध होते हैं। यह "सहसंबंध टूटना" घटना इक्विटी बाज़ारों में अच्छी तरह प्रलेखित है और क्रिप्टो में और भी अधिक स्पष्ट है।
  3. टेल डिपेंडेंस। दो एसेट के एक साथ चरम नुकसान अनुभव करने की संभावना रैखिक सहसंबंध द्वारा कैप्चर नहीं होती। समान सहसंबंध वाले लेकिन बहुत भिन्न टेल डिपेंडेंस वाले दो एसेट हो सकते हैं।

स्क्लार का प्रमेय: नींव

स्क्लार का प्रमेय (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] कोपुला है — एक फलन जो चरों के बीच संपूर्ण निर्भरता संरचना को एनकोड करता है।

इसके विपरीत, यदि मार्जिनल्स सतत हैं, तो कोपुला CC अद्वितीय है।

यह विघटन शक्तिशाली है क्योंकि यह हमें अनुमति देता है:

  • प्रत्येक एसेट के मार्जिनल वितरण को अलग से मॉडल करना (GARCH, EVT, या किसी भी उपयुक्त वितरण का उपयोग करके)
  • कोपुला के माध्यम से निर्भरता संरचना को स्वतंत्र रूप से मॉडल करना
  • पूर्ण संयुक्त वितरण प्राप्त करने के लिए उन्हें संयोजित करना

संयुक्त वितरण की डेंसिटी इस प्रकार गुणनखंडित होती है:

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 कोपुला डेंसिटी है और fif_i मार्जिनल डेंसिटी हैं।

कोपुला परिवार और उनके गुण

कोपुला परिवारों में टेल डिपेंडेंस की तुलना

गॉसियन कोपुला

गॉसियन कोपुला एक सहसंबंध मैट्रिक्स Σ\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} एकचर सामान्य क्वांटाइल फलन है।

टेल डिपेंडेंस: λL=λU=0\lambda_L = \lambda_U = 0 (जब ρ<1\rho < 1)।

गॉसियन कोपुला में शून्य टेल डिपेंडेंस होती है — यह संयुक्त चरम घटनाओं की संभावना को व्यवस्थित रूप से कम आंकता है। यह 2008 से पहले CDO की गलत कीमत निर्धारण में एक प्रमुख कारक था, और यह क्रिप्टो जोखिम मॉडलिंग के लिए समान रूप से खतरनाक है।

स्टूडेंट का t-कोपुला

t-कोपुला डिग्री-ऑफ-फ्रीडम पैरामीटर ν\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=2⋅tν+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% संभावना। कम ν\nu (भारी टेल) इस संभावना को बढ़ाता है। क्रिप्टो बाज़ार, अपने मोटे-टेल रिटर्न के साथ, आमतौर पर ν\nu को 3-8 की सीमा में आवश्यक करते हैं।

t-कोपुला गॉसियन पर एक महत्वपूर्ण सुधार है, लेकिन यह सममित टेल डिपेंडेंस (λL=λU\lambda_L = \lambda_U) लागू करता है। व्यवहार में, क्रिप्टो एसेट अक्सर ऊपरी-टेल डिपेंडेंस (साथ रैली) की तुलना में अधिक मजबूत निचले-टेल डिपेंडेंस (साथ क्रैश) प्रदर्शित करते हैं।

क्लेटन कोपुला

क्लेटन कोपुला निचले टेल डिपेंडेंस को कैप्चर करता है — ठीक उसी प्रकार का असममित क्रैश-क्लस्टरिंग व्यवहार जो हम क्रिप्टो में देखते हैं:

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=2−1/θ\lambda_L = 2^{-1/\theta}, λU=0\lambda_U = 0।

जैसे-जैसे θ\theta बढ़ता है, निचला टेल डिपेंडेंस मजबूत होता है। θ=2\theta = 2 के लिए, λL≈0.71\lambda_L \approx 0.71 — संयुक्त चरम नुकसान की बहुत उच्च संभावना।

गम्बेल कोपुला

गम्बेल कोपुला दर्पण छवि है — यह ऊपरी टेल डिपेंडेंस को कैप्चर करता है:

CθGumbel(u1,u2)=exp⁡(−[(−ln⁡u1)θ+(−ln⁡u2)θ]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=2−21/θ\lambda_U = 2 - 2^{1/\theta}।

फ्रैंक कोपुला

फ्रैंक कोपुला में दोनों टेल में शून्य टेल डिपेंडेंस होती है (λL=λU=0\lambda_L = \lambda_U = 0), जो इसे बिना टेल प्रभाव के वितरण के मुख्य भाग में निर्भरता को मॉडल करने के लिए उपयुक्त बनाता है:

CθFrank(u1,u2)=−1θln⁡(1+(e−θu1−1)(e−θu2−1)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)

क्रिप्टो के लिए सही कोपुला चुनना

क्रिप्टो पोर्टफोलियो के लिए, अनुभवजन्य साक्ष्य इंगित करता है:

  • निचले टेल डिपेंडेंस के लिए क्लेटन या रोटेटेड गम्बेल (सर्वाइवल गम्बेल) — क्रैश संक्रमण को कैप्चर करना
  • t-कोपुला एक मजबूत सामान्य-उद्देश्य विकल्प के रूप में जब सममित टेल डिपेंडेंस स्वीकार्य हो
  • रैली चरणों में मजबूत ऊपरी टेल डिपेंडेंस को कैप्चर करने के लिए जो कोपुला

Bruhn और Jeleskovic (2024) के शोध में पाया गया कि GARCH-कोपुला मॉडल, विशेष रूप से वे जो स्टूडेंट के t मार्जिनल्स को t-कोपुला के साथ उपयोग करते हैं, क्रिप्टो में गिरावट (2022), रिकवरी (2023), और स्थिरता (2024) बाज़ार स्थितियों में लगातार मीन-वेरिएंस और ऐतिहासिक CVaR दृष्टिकोणों से बेहतर प्रदर्शन करते हैं।

आयामीता का अभिशाप: वाइन कोपुला का प्रवेश

क्रिप्टो पोर्टफोलियो के लिए वाइन कोपुला ट्री संरचना

मानक बहुचर कोपुला (गॉसियन, t-कोपुला) उच्च आयामों तक स्केल करते हैं लेकिन प्रतिबंधात्मक धारणाएं लागू करते हैं। आर्किमिडियन कोपुला (क्लेटन, गम्बेल, फ्रैंक) स्वाभाविक रूप से द्विचर होते हैं — उन्हें d>2d > 2 आयामों तक विस्तारित करने के लिए आवश्यक है कि सभी जोड़े समान निर्भरता पैरामीटर साझा करें, जो अवास्तविक है।

वाइन कोपुला एक dd-आयामी कोपुला को एक ट्री संरचना में व्यवस्थित द्विचर कोपुला के एक झरने में विघटित करके इसे हल करते हैं। चरों की प्रत्येक जोड़ी (अन्य पर सशर्त) को अपना स्वयं का द्विचर कोपुला परिवार और पैरामीटर मिलता है।

पेयर-कोपुला निर्माण

dd-आयामी डेंसिटी के लिए, वाइन कोपुला गुणनखंडन है:

f(x1,…,xd)=∏i=1dfi(xi)⋅∏j=1d−1∏i=1d−jci,i+j∣i+1,…,i+j−1f(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,j∣Sc_{i,j|S} चरों ii और jj के लिए सेट SS पर सशर्त एक द्विचर कोपुला डेंसिटी है।

एक dd-आयामी वाइन कोपुला को (d2)=d(d−1)/2\binom{d}{2} = d(d-1)/2 द्विचर कोपुला की आवश्यकता होती है। 10-एसेट क्रिप्टो पोर्टफोलियो के लिए, यह 45 पेयर कोपुला हैं — प्रत्येक संभावित रूप से एक अलग परिवार से।

वाइन संरचनाएं: C-वाइन, D-वाइन, R-वाइन

C-वाइन (कैनोनिकल वाइन): प्रत्येक ट्री में एक एकल रूट नोड होता है जो अन्य सभी नोड्स से जुड़ा होता है। सबसे अच्छा तब जब एक चर हावी होता है — जैसे बाज़ार चालक के रूप में 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-वाइन (ड्रॉएबल वाइन): एक अनुक्रमिक पथ संरचना। सबसे अच्छा तब जब चरों का एक प्राकृतिक क्रम होता है (जैसे मार्केट कैप या सेक्टर द्वारा)।

R-वाइन (रेगुलर वाइन): सबसे सामान्य संरचना — कोई भी वैध ट्री अनुक्रम। R-वाइन दोनों C-वाइन और D-वाइन को समाहित करता है।

क्रिप्टोकरेंसी पोर्टफोलियो पर शोध बताता है कि D-वाइन संरचनाएं अक्सर क्रिप्टो एसेट के लिए C-वाइन और R-वाइन की तुलना में बेहतर VaR पूर्वानुमान उत्पन्न करती हैं, हालांकि यह विशिष्ट पोर्टफोलियो संरचना पर निर्भर करता है।

वाइन कोपुला क्रिप्टो के लिए क्यों महत्वपूर्ण हैं

एक ही क्लेटन कोपुला के साथ मॉडल किए गए 8 क्रिप्टो एसेट के पोर्टफोलियो में सभी 28 जोड़ों को समान θ\theta साझा करने के लिए मजबूर किया जाता है। लेकिन BTC-ETH में θClayton=3.5\theta_{\text{Clayton}} = 3.5 (मजबूत क्रैश निर्भरता) हो सकता है जबकि SOL-AVAX में θ=1.2\theta = 1.2 (मध्यम) हो सकता है। वाइन कोपुला प्रत्येक जोड़ी को अपनी निर्भरता संरचना व्यक्त करने देते हैं:

  • BTC-ETH: t-कोपुला (ν=4\nu=4, ρ=0.72\rho=0.72)
  • BTC-SOL: क्लेटन (θ=2.1\theta=2.1)
  • ETH-AVAX: फ्रैंक (θ=5.3\theta=5.3)
  • SOL-DOT | BTC: गम्बेल (θ=1.8\theta=1.8)

यह लचीलापन सटीक पोर्टफोलियो जोखिम अनुमान के लिए महत्वपूर्ण है।

मार्जिनल्स को मॉडल करना: GARCH-EVT

कोपुला को फिट करने से पहले, हमें प्रत्येक एसेट की रिटर्न श्रृंखला को यूनिफॉर्म [0,1][0,1] चरों में बदलने की आवश्यकता है ("प्रोबेबिलिटी इंटीग्रल ट्रांसफॉर्म")। मानक पाइपलाइन:

  1. समय-परिवर्ती अस्थिरता को कैप्चर करने के लिए प्रत्येक एसेट की रिटर्न श्रृंखला पर GARCH मॉडल फिट करें
  2. मानकीकृत अवशेष निकालें zt=(rt−μt)/σtz_t = (r_t - \mu_t) / \sigma_t
  3. एक्सट्रीम वैल्यू थ्योरी (EVT) का उपयोग करके टेल फिट करें — विशेष रूप से, थ्रेशोल्ड (आमतौर पर 5वें और 95वें प्रतिशतक) से परे ऊपरी और निचली टेल के लिए जनरलाइज्ड पारेटो डिस्ट्रीब्यूशन (GPD)
  4. वितरण के मुख्य भाग के लिए अनुभवजन्य CDF का उपयोग करें
  5. छद्म-यूनिफॉर्म अवलोकन ui,t=F^i(zi,t)u_{i,t} = \hat{F}_i(z_{i,t}) प्राप्त करने के लिए प्रोबेबिलिटी इंटीग्रल ट्रांसफॉर्म लागू करें

इस GARCH-EVT दृष्टिकोण को अक्सर "अर्ध-पैरामीट्रिक" विधि कहा जाता है। यह ठीक से कैप्चर करता है:

  • अस्थिरता क्लस्टरिंग (GARCH)
  • भारी टेल (EVT से GPD)
  • वितरण का समग्र आकार (मुख्य भाग के लिए अनुभवजन्य CDF)

क्रिप्टो एसेट के लिए, स्टूडेंट के t इनोवेशन के साथ EGARCH(1,1) या GJR-GARCH(1,1) मॉडल अच्छी तरह काम करता है, क्योंकि यह असममित अस्थिरता प्रतिक्रिया को कैप्चर करता है (बुरी खबर अच्छी खबर की तुलना में अस्थिरता को अधिक बढ़ाती है)।

कोपुला के साथ पोर्टफोलियो VaR और CVaR

वैल्यू-एट-रिस्क (VaR)

विश्वास स्तर α\alpha पर पोर्टफोलियो VaR है:

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

जहां LL पोर्टफोलियो नुकसान है। कोपुला के साथ, हम मॉन्टे कार्लो के माध्यम से VaR का अनुमान लगाते हैं:

  1. फिट किए गए वाइन कोपुला से NN नमूनों का अनुकरण करें (यूनिफॉर्म स्पेस में)
  2. इनवर्स मार्जिनल CDF का उपयोग करके रिटर्न स्पेस में वापस बदलें
  3. पोर्टफोलियो रिटर्न की गणना करें: rp=∑iwi⋅rir_p = \sum_i w_i \cdot r_i
  4. VaR सिम्युलेटेड पोर्टफोलियो नुकसान वितरण का α\alpha-क्वांटाइल है

सशर्त वैल्यू-एट-रिस्क (CVaR / एक्सपेक्टेड शॉर्टफॉल)

CVaR अपेक्षित नुकसान है यह देखते हुए कि नुकसान VaR से अधिक है:

CVaRα=E[L∣L≥VaRα]=11−α∫α1VaRu du\text{CVaR}_\alpha = E[L \mid L \geq \text{VaR}_\alpha] = \frac{1}{1-\alpha}\int_{\alpha}^{1}\text{VaR}_u\, du

CVaR सुसंगत है (सबएडिटिविटी को संतुष्ट करता है), जो इसे पोर्टफोलियो अनुकूलन के लिए VaR से बेहतर बनाता है। मॉन्टे कार्लो अनुमान सीधा है — उन नुकसानों का औसत लें जो VaR से अधिक हैं।

कोपुला-आधारित जोखिम सहसंबंध-आधारित जोखिम से बेहतर क्यों है

समान जोड़ीवार सहसंबंध 0.5 वाले दो पोर्टफोलियो पर विचार करें:

  • पोर्टफोलियो A: गॉसियन कोपुला निर्भरता (कोई टेल डिपेंडेंस नहीं)
  • पोर्टफोलियो B: क्लेटन कोपुला निर्भरता (θ=2\theta = 2, λL=0.71\lambda_L = 0.71)

99% विश्वास स्तर पर, पोर्टफोलियो B में काफी अधिक VaR और CVaR होगा क्योंकि क्लेटन कोपुला एसेट के एक साथ क्रैश होने की प्रवृत्ति को सही ढंग से मॉडल करता है। गॉसियन कोपुला यह मानकर इस जोखिम को कम आंकता है कि चरम सह-गतियां लुप्तप्राय रूप से दुर्लभ हैं।

क्रिप्टो पोर्टफोलियो पर अनुभवजन्य अध्ययनों में, गॉसियन और वाइन कोपुला मॉडल के बीच 99% CVaR में अंतर 30-40% से अधिक हो सकता है, जिसका अर्थ है कि सहसंबंध-आधारित मॉडल टेल जोखिम को एक तिहाई या उससे अधिक कम आंक सकते हैं।

कार्यान्वयन: pyvinecopulib के साथ Python

क्रिप्टो रिटर्न पर वाइन कोपुला फिट करने और पोर्टफोलियो 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

# Fit GARCH to each asset and collect standardized residuals
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:
            # Fit GPD to lower tail (negate for positive values)
            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:
            # Fit GPD to upper tail
            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:
            # Empirical CDF for the body
            u[i] = np.mean(residuals <= x)

    # Clip to avoid exact 0 or 1
    u = np.clip(u, 1e-6, 1 - 1e-6)
    return u

# Transform all residuals to pseudo-uniform
U = np.column_stack([
    semi_parametric_pit(residuals_df[sym].values)
    for sym in symbols
])

चरण 3: वाइन कोपुला फिट करें

# Configure the vine copula fit
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
)

# Fit the vine copula
vine = pv.Vinecop(U, controls=controls)

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

# Print pair copula families for the first tree
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: मॉन्टे कार्लो 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.
    """
    # Simulate from vine copula (uniform space)
    U_sim = vine.simulate(n=n_sim, seeds=[seed])

    # Transform back to return space via inverse marginals
    returns_sim = np.zeros((n_sim, len(symbols)))
    for j, sym in enumerate(symbols):
        model = garch_models[sym]
        # Get last conditional volatility and mean
        forecasts = model.forecast(horizon=1)
        mu = forecasts.mean.iloc[-1, 0] / 100  # unscale
        sigma = np.sqrt(forecasts.variance.iloc[-1, 0]) / 100

        # Inverse PIT: uniform -> standardized residual -> return
        # Using t-distribution inverse CDF with fitted dof
        nu = model.params.get("nu", 5)
        z_sim = stats.t.ppf(U_sim[:, j], df=nu)
        returns_sim[:, j] = mu + sigma * z_sim

    # Portfolio returns
    weights = np.array(weights)
    portfolio_returns = returns_sim @ weights

    # Losses (negative returns)
    losses = -portfolio_returns

    # VaR
    var = np.quantile(losses, alpha)

    # CVaR (Expected Shortfall)
    cvar = np.mean(losses[losses >= var])

    return var, cvar, portfolio_returns

# Equal-weighted portfolio
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}%")

# Compare with Gaussian assumption
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)
        # Compute tail dependence from the bivariate copula
        # Using simulation-based estimation
        u_pair = pair.simulate(n=100_000, seeds=[42])
        q = 0.01  # 1st percentile

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

        # Upper tail dependence
        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))

एक क्रिप्टो पोर्टफोलियो के लिए विशिष्ट आउटपुट कुछ इस तरह दिख सकता है:

PairFamilyλL\lambda_LλU\lambda_U
BTC-ETHstudent0.220.22
BTC-SOLclayton0.350.00
BTC-AVAXbb70.280.12
BTC-DOTstudent0.180.18
BTC-LINKclayton0.310.00
BTC-MATICfrank0.000.00
BTC-ATOMgumbel0.000.15

ध्यान दें कि प्रत्येक जोड़ी में पूरी तरह से अलग निर्भरता संरचना हो सकती है। BTC-SOL शून्य ऊपरी टेल डिपेंडेंस के साथ मजबूत निचली टेल डिपेंडेंस (क्लेटन) दिखाता है — वे साथ क्रैश होते हैं लेकिन जरूरी नहीं कि साथ रैली करें। BTC-MATIC कोई टेल डिपेंडेंस नहीं दिखाता (फ्रैंक), जो चरम स्थितियों में भी कुछ विविधीकरण लाभ का सुझाव देता है।

कोपुला VaR मॉडल का बैकटेस्टिंग

एक VaR मॉडल तभी उपयोगी है जब वह अच्छी तरह कैलिब्रेटेड हो। मानक बैकटेस्ट VaR उल्लंघनों की गणना करता है — वे दिन जब वास्तविक नुकसान अनुमानित 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):
        # Rolling window of returns
        window_returns = returns.iloc[t-window:t]

        # 1. Fit GARCH marginals
        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
            # Simple empirical PIT for speed
            u = pv.to_pseudo_obs(std_resid.values.reshape(-1, 1))
            U_window[:len(u), j] = u.ravel()

        # 2. Fit vine copula
        U_clean = U_window[~np.any(U_window == 0, axis=1)]
        vine_t = pv.Vinecop(U_clean, controls=controls)

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

        # 4. Check violation
        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

एक अच्छी तरह कैलिब्रेटेड 99% VaR मॉडल की उल्लंघन दर 1% के करीब होनी चाहिए। यदि दर काफी अधिक है, तो मॉडल जोखिम को कम आंकता है। यदि काफी कम है, तो यह बहुत रूढ़िवादी है।

व्यावहारिक विचार

कम्प्यूटेशनल लागत

वाइन कोपुला फिटिंग प्रति ट्री स्तर O(d2⋅n)O(d^2 \cdot n) है। 500-दिन के रोलिंग विंडो वाले 10-एसेट पोर्टफोलियो के लिए, प्रति चरण 50,000 मॉन्टे कार्लो सिमुलेशन के साथ पूर्ण बैकटेस्ट में घंटों लग सकते हैं। इसे प्रबंधित करने की रणनीतियां:

  • ट्रंकेटेड वाइन: trunc_lvl=3 या trunc_lvl=4 सेट करें — उच्च ट्री कमजोर सशर्त निर्भरता को कैप्चर करते हैं जो जोखिम में कम योगदान करती हैं
  • कम सिमुलेशन गणना: 99% VaR के लिए अक्सर 10,000-20,000 सिमुलेशन पर्याप्त होते हैं
  • समानांतर गणना: प्रत्येक एसेट के लिए GARCH फिट स्वतंत्र हैं और समानांतर किए जा सकते हैं
  • मॉडल कैशिंग: दैनिक के बजाय साप्ताहिक रूप से कोपुला को फिर से फिट करें, केवल GARCH पूर्वानुमानों को अपडेट करते हुए

रेजीम जागरूकता

क्रिप्टो बाज़ार अलग-अलग रेजीम प्रदर्शित करते हैं (बुल, बियर, साइडवेज, उच्च-अस्थिरता घटनाएं)। पूरे नमूने पर फिट किया गया एक ही वाइन कोपुला रेजीम-निर्भर निर्भरता को कैप्चर नहीं कर सकता। विचार करें:

  • 250-500 दिनों की रोलिंग विंडो
  • रेजीम-स्विचिंग कोपुला जहां कोपुला पैरामीटर एक छिपे हुए मार्कोव स्टेट पर निर्भर करते हैं
  • एक्सपोनेंशियली-वेटेड ऑब्जर्वेशन जो हाल के डेटा को अधिक भार देते हैं

सामान्य गलतियां

  1. PIT को भूलना। छद्म-यूनिफॉर्म अवलोकनों के बजाय सीधे कच्चे रिटर्न को कोपुला में फीड करने से अर्थहीन परिणाम मिलेंगे। हमेशा पहले यूनिफॉर्म मार्जिन में बदलें।
  2. बहुत अधिक परिवारों के साथ ओवरफिटिंग। चयन सेट में हर संभव द्विचर परिवार को शामिल करने से ओवरफिटिंग हो सकती है, विशेष रूप से छोटे नमूनों के साथ। मॉडल चयन के लिए BIC का उपयोग करें और 4-5 परिवारों तक सीमित करने पर विचार करें।
  3. सीरियल डिपेंडेंस को नज़रअंदाज़ करना। कोपुला एक ही समय बिंदु पर क्रॉस-सेक्शनल निर्भरता को मॉडल करते हैं। यदि आप GARCH चरण को छोड़ देते हैं और स्वतःसहसंबद्ध रिटर्न को कोपुला में फीड करते हैं, तो अनुमानित निर्भरता सीरियल प्रभावों से दूषित हो जाएगी।
  4. गतिशील बाज़ारों में स्थैतिक कोपुला। 2021 बुल मार्केट डेटा पर फिट किया गया कोपुला 2022 क्रैश के लिए खराब रूप से कैलिब्रेटेड होगा। हमेशा रोलिंग या विस्तारित विंडो का उपयोग करें।

निष्कर्ष

कोपुला मॉडल — विशेष रूप से वाइन कोपुला — क्रिप्टो पोर्टफोलियो के संयुक्त जोखिम को मॉडल करने के लिए एक गणितीय रूप से कठोर ढांचा प्रदान करते हैं जो रैखिक सहसंबंध की तुलना में बहुत आगे जाता है। मुख्य लाभ:

  • स्क्लार के प्रमेय के माध्यम से अलग मार्जिनल और निर्भरता मॉडलिंग
  • उपयुक्त कोपुला परिवार चयन के माध्यम से लचीला टेल डिपेंडेंस (क्रैश संक्रमण के लिए क्लेटन, रैली सह-गति के लिए गम्बेल, सममित टेल के लिए t-कोपुला)
  • वाइन कोपुला विघटन के माध्यम से उच्च-आयामी स्केलेबिलिटी, जहां एसेट की प्रत्येक जोड़ी को अपना स्वयं का द्विचर कोपुला मिलता है
  • सटीक VaR/CVaR अनुमान जो गैर-रैखिक, असममित निर्भरता को ध्यान में रखता है — एक बाज़ार में जोखिम प्रबंधन के लिए महत्वपूर्ण जहां "सब कुछ एक साथ क्रैश होता है" आदर्श है, अपवाद नहीं

GARCH-EVT-कोपुला पाइपलाइन अब क्वांटिटेटिव हेज फंड और क्रिप्टो-केंद्रित जोखिम डेस्क पर मानक दृष्टिकोण है। pyvinecopulib जैसी लाइब्रेरी के साथ, कार्यान्वयन बाधा इतनी कम है कि कोई भी व्यवस्थित ट्रेडर कोपुला-आधारित जोखिम मॉडलिंग को अपने पोर्टफोलियो प्रबंधन वर्कफ़्लो में एकीकृत कर सकता है।

इस लेख में दिया गया कोड एक कार्यशील प्रारंभिक बिंदु प्रदान करता है। उत्पादन उपयोग के लिए, आप GARCH ऑर्डर चयन के लिए उचित क्रॉस-वैलिडेशन, अधिक परिष्कृत मार्जिनल मॉडल (जैसे लीवरेज प्रभावों के साथ EGARCH, या इंट्राडे डेटा का उपयोग करके रियलाइज्ड वोलैटिलिटी माप), और ऐतिहासिक संकट प्रकरणों पर कैलिब्रेटेड काल्पनिक कोपुला पैरामीटर के तहत स्ट्रेस टेस्टिंग जोड़ेंगे।


संदर्भ

  • 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.