DCC-GARCH: पेयर्स ट्रेडिंग और पोर्टफोलियो रिस्क के लिए डायनामिक कोरिलेशन
अधिकतर क्रिप्टो डेस्क से BTC और ETH के बीच कोरिलेशन पूछिए, और आपको एक ही संख्या मिलेगी — 0.8, शायद 0.75 — जो किसी ऐसी विंडो पर निकाली गई है जिसे चुनने का कारण किसी को याद नहीं। यह संख्या झूठ है, या कम से कम एक खतरनाक सरलीकरण। सैंपल कोरिलेशन उस अवधि का औसत होता है जिसमें वास्तविक निर्भरता संरचना लगातार बदल रही थी। शांत बाजारों में BTC और ETH इतने अलग हो जाते हैं कि एक मार्केट-न्यूट्रल पेयर आकर्षक दिखने लगता है। लिक्विडेशन कैस्केड में वे एक-दूसरे और बाकी सबसे जुड़ जाते हैं, और जो डाइवर्सिफिकेशन आपने खरीदा था वह ठीक उसी क्षण गायब हो जाता है जब आपको उसकी सबसे ज्यादा जरूरत होती है।
यह कोई सूक्ष्म प्रभाव नहीं है। 2022 का कोई भी ड्रॉडाउन उठा लीजिए — मई में LUNA का पतन, जून में 3AC का अनवाइंड, नवंबर में FTX का इम्प्लोजन — और आप देखेंगे कि टॉप 20 टोकन में औसत पेयरवाइज कोरिलेशन कुछ ही दिनों में 0.4-0.6 की रेंज से 0.9+ की ओर बढ़ जाता है। कोरिलेशन कोई स्थिरांक नहीं है जिसका कभी-कभार गलत अनुमान लग जाता है; यह अपनी खुद की गतिशीलता, अपने खुद के क्लस्टरिंग, और अपने खुद के रीजीम वाली एक टाइम सीरीज है। इसे स्केलर मानना, स्थिर वोलैटिलिटी मान लेने के मल्टीवैरिएट समकक्ष है — एक गलती जिसे हम पहले ही इस सीरीज के भाग 1 में एक ही असेट के लिए तोड़ चुके हैं।
यह लेख चार-भाग वाली वोलैटिलिटी सीरीज का भाग 3 है। भाग 1 ने arch लाइब्रेरी के साथ यूनिवैरिएट GARCH(1,1) बनाया और दिखाया कि वोलैटिलिटी कैसे क्लस्टर होती है और मीन-रिवर्ट करती है। भाग 2 ने असममिति (GJR-GARCH, EGARCH) और स्टूडेंट-t इनोवेशन जोड़े ताकि लीवरेज इफेक्ट और फैट टेल्स को पकड़ा जा सके। यहां हम मल्टीवैरिएट जाते हैं: हम पूरे कंडीशनल कोवेरियंस मैट्रिक्स को उसके विकास के साथ मॉडल करते हैं, एंगल के डायनामिक कंडीशनल कोरिलेशन (DCC) मॉडल का उपयोग करके। इससे हमें वो दो चीजें मिलती हैं जो एक स्केलर कोरिलेशन कभी नहीं दे सकता — पेयर्स ट्रेडिंग के लिए एक डायनामिक हेज रेशियो, और रिस्क-आधारित एलोकेशन के लिए एक ईमानदार, समय-परिवर्तनशील पोर्टफोलियो वेरियंस। भाग 4 सीरीज को एक वोलैटिलिटी-टारगेटेड बैकटेस्ट के साथ समाप्त करता है जो यूनिवैरिएट और मल्टीवैरिएट फोरकास्ट को एक पोजीशन-साइजिंग नियम में जोड़ता है।
हम मानते हैं कि आपने भाग 1 और 2 पढ़ लिए हैं, इसलिए हम यूनिवैरिएट GARCH को दोबारा नहीं समझाएंगे। यदि आपको संयुक्त टेल व्यवहार चाहिए — यह संभावना कि दो असेट एक साथ अपने 1% क्वांटाइल को तोड़ें — वह एक कोप्युला प्रश्न है, और हम इसे Copula Models for Joint Risk में कवर करते हैं। DCC और कोप्युला परस्पर पूरक हैं: कोप्युला आपको एक स्थिर-लेकिन-लचीली टेल-डिपेंडेंस संरचना देता है, जबकि DCC आपको पूरे कोरिलेशन मैट्रिक्स की एक ट्रैक्टेबल टाइम सीरीज देता है। यह लेख दूसरे के बारे में है।
क्रिप्टो में स्थिर कोरिलेशन क्यों टूटता है
तंत्र में जाने से पहले, स्पष्ट रूप से समझें कि क्या विफल होता है। एक विंडो पर एक ही सैंपल कोरिलेशन इसका अनुमान लगाता है
इसमें तीन अंतर्निहित मान्यताएं हैं, जो सभी क्रिप्टो के लिए गलत हैं:
- निर्भरता की स्थिरता। विंडो में एक ही सच्चा होता है। वास्तव में निर्भरता के रीजीम होते हैं — 0.5 के आसपास एक शांत-बाजार रीजीम और 0.95 के आसपास एक स्ट्रेस रीजीम — और इन्हें एक निरर्थक बीच के मान में मिला देता है।
- स्थिर मार्जिनल वोलैटिलिटी। पियर्सन कोरिलेशन एक नॉर्मलाइज्ड कोवेरियंस है। यदि और स्वयं बदल रहे हैं (जो वे हैं — यही भाग 1 और 2 की पूरी बुनियाद है), तो एक स्थिर कोवेरियंस भी एक समय-परिवर्तनशील कोरिलेशन पैदा करती है, और इसका उल्टा भी सच है। नीचे किसी वोलैटिलिटी मॉडल के बिना आप इन दोनों को अलग नहीं कर सकते।
- बाजार दिशा में असममिति। रैलियों की तुलना में ड्रॉडाउन में कोरिलेशन ज्यादा बढ़ता है। यह लीवरेज इफेक्ट का मल्टीवैरिएट चचेरा भाई है। एक रोलिंग विंडो इसे तब तक व्यक्त नहीं कर सकती जब तक वह इतनी छोटी न हो जाए कि शुद्ध शोर बन जाए।
रोलिंग-विंडो समाधान — पिछले 30 या 60 दिनों पर को दोबारा निकालना — एक समस्या को दूसरी से बदल देता है। छोटी विंडो प्रतिक्रियाशील लेकिन शोरगुल वाली होती हैं और वास्तविक ब्रेक से पिछड़ जाती हैं; लंबी विंडो स्थिर लेकिन पुरानी होती हैं। इससे भी बुरा, असेट पर एक रोलिंग कोरिलेशन मैट्रिक्स के पॉजिटिव सेमी-डेफिनिट बने रहने की कोई गारंटी नहीं है, एक बार जब आप उसे श्रिंक या पैच करना शुरू करते हैं, जिससे हर डाउनस्ट्रीम ऑप्टिमाइज़र टूट जाता है। हमें एक ऐसा मॉडल चाहिए जो (a) प्रति असेट एक उचित वोलैटिलिटी प्रोसेस से संचालित हो, (b) हर स्टेप पर संरचना से एक वैध कोरिलेशन मैट्रिक्स प्रदान करे, और (c) जिसके पैरामीटर हम मैक्सिमम लाइकलिहुड द्वारा अनुमानित कर सकें बजाय किसी टोपी से विंडो लंबाई चुनने के। वह मॉडल है DCC-GARCH।
मल्टीवैरिएट समस्या: कंडीशनल कोवेरियंस मैट्रिक्स
मान लीजिए समय पर असेट के रिटर्न का वेक्टर है, जिसका कंडीशनल मीन है (अक्सर सिर्फ एक स्थिरांक या एक छोटा AR टर्म) और रेजिड्युअल । हम मानते हैं
जहां इंफॉर्मेशन सेट के दिए जाने पर कंडीशनल कोवेरियंस मैट्रिक्स है, और कोई कंडीशनल डिस्ट्रीब्यूशन है (गॉसियन या, क्रिप्टो के लिए बेहतर, मल्टीवैरिएट स्टूडेंट-t)। मल्टीवैरिएट वोलैटिलिटी मॉडलिंग में हर चीज एक ही सवाल का अलग जवाब है: आप की गतिशीलता को इस तरह कैसे पैरामीटराइज करें कि वह हर स्टेप पर सिमेट्रिक पॉजिटिव डेफिनिट बना रहे, बिना पैरामीटरों के विस्फोट के?
दो शास्त्रीय जवाब दिखाते हैं कि यह समस्या कितनी कठिन है।
VECH
VECH मॉडल (Bollerslev, Engle, Wooldridge 1988) के हाफ-वेक्टराइजेशन को अतीत के स्क्वेयर्ड रेजिड्युअल और अतीत के कोवेरियंस के रैखिक फंक्शन के रूप में लिखता है:
जहां एक सिमेट्रिक मैट्रिक्स की निचली त्रिकोण को लंबाई के वेक्टर में जमा करता है। यह अधिकतम सामान्य है — हर वेरियंस और कोवेरियंस हर पिछले वेरियंस और कोवेरियंस पर निर्भर करता है — और के बाद अधिकतम बेकार है। असेट के लिए, और में से हर एक है। पर वह दो मैट्रिक्स हैं, लगभग 450 पैरामीटर, प्लस पॉजिटिव-डेफिनिटनेस बाधाएं जिन्हें व्यक्त करना भी कष्टकारी है। लाइकलिहुड सरफेस एक दलदल है।
BEKK
BEKK मॉडल (Engle & Kroner 1995) एक क्वाड्रेटिक फॉर्म का उपयोग करके संरचना से पॉजिटिव डेफिनिटनेस की गारंटी देता है:
जहां ऊपरी त्रिकोणीय है। क्योंकि हर टर्म एक क्वाड्रेटिक फॉर्म है, अपने आप होता है जब तक । BEKK, VECH से अधिक पारदर्शी है लेकिन फिर भी पैरामीटर के रूप में स्केल करता है — और मैट्रिक्स प्रत्येक हैं। के लिए आप MLE द्वारा शोरगुल वाले डेली क्रिप्टो डेटा पर संयुक्त रूप से 200+ पैरामीटर के क्रम में अनुमान लगा रहे हैं, बिना किसी गारंटी के कि ऑप्टिमाइज़र किसी सार्थक चीज पर कन्वर्ज करेगा। व्यवहार में पूरा BEKK तक सीमित रहता है, और तब भी लोग "डायगोनल" या "स्केलर" प्रतिबंधों का उपयोग करते हैं जो अधिकतर क्रॉस डायनामिक्स को फेंक देते हैं।
यह मल्टीवैरिएट GARCH के लिए डाइमेंशनैलिटी का अभिशाप है: पैरामीटरों की संख्या क्वाड्रेटिकली बढ़ती है, लेकिन डेटा में जानकारी की मात्रा नहीं बढ़ती। आप उन असेट से बहुत पहले फ्रीडम की डिग्री से बाहर हो जाते हैं जिनकी आपको परवाह है। 10-30 टोकन वाली कोई भी क्रिप्टो बुक VECH या BEKK की पहुंच से पूरी तरह बाहर है।
एंगल के कारण निकास मार्ग यह है कि को सीधे मॉडल करने की कोशिश छोड़ दी जाए और इसके बजाय उसे उन टुकड़ों में फैक्टर किया जाए जिन्हें हम पहले से सस्ते में अनुमानित करना जानते हैं।
एंगल का DCC (2002): टू-स्टेप डिकम्पोजिशन
Bollerslev का कॉन्स्टेंट कंडीशनल कोरिलेशन (CCC) मॉडल (1990) पहला पारदर्शी फैक्टराइजेशन था। यह लिखता है
जहां कंडीशनल स्टैंडर्ड डेविएशन का डायगोनल मैट्रिक्स है — प्रति असेट एक यूनिवैरिएट GARCH — और एक स्थिर कोरिलेशन मैट्रिक्स है। यह एक बड़ा सरलीकरण है: आप स्वतंत्र यूनिवैरिएट GARCH मॉडल फिट करते हैं, फिर स्टैंडर्डाइज्ड रेजिड्युअल का एक ही सैंपल कोरिलेशन मैट्रिक्स अनुमानित करते हैं। पॉजिटिव डेफिनिटनेस अपने आप होती है जब तक एक वैध कोरिलेशन मैट्रिक्स है और सभी हैं।
CCC की समस्या नाम में ही है — कोरिलेशन स्थिर है, जो ठीक वही मान्यता है जिसे हमने इस लेख की शुरुआत में खारिज किया था। एंगल का डायनामिक कंडीशनल कोरिलेशन (2002) CCC के सुंदर फैक्टराइजेशन को बनाए रखता है लेकिन कोरिलेशन मैट्रिक्स को सांस लेने देता है:
अब समय-परिवर्तनशील है। जीनियस बात यह है कि वोलैटिलिटी और कोरिलेशन को दो अलग स्टेप में अनुमानित किया जाता है, इसलिए हमें कभी पूरे संयुक्त ऑप्टिमाइजेशन का सामना नहीं करना पड़ता।
स्टेप 1: प्रति असेट यूनिवैरिएट GARCH
प्रत्येक असेट के लिए, ठीक भाग 1 और 2 की तरह एक यूनिवैरिएट GARCH मॉडल फिट करें — GARCH(1,1), GJR-GARCH, या EGARCH स्टूडेंट-t इनोवेशन के साथ, जो भी उस सीरीज के लिए सबसे अच्छा फिट हो। इससे कंडीशनल वेरियंस मिलता है और इसलिए ।
फिट किए गए मॉडलों से हम स्टैंडर्डाइज्ड रेजिड्युअल निकालते हैं:
संरचना से प्रत्येक का (लगभग) यूनिट कंडीशनल वेरियंस होता है। उन्हें एक वेक्टर में जमा करें। ये स्टैंडर्डाइज्ड रेजिड्युअल कोरिलेशन स्टेप के लिए कच्चा माल हैं — इनकी व्यक्तिगत वोलैटिलिटी गतिशीलता निकाल दी गई है, इसलिए जो भी को-मूवमेंट बचता है वह शुद्ध निर्भरता है, न कि वोलैटिलिटी का आर्टिफैक्ट। (यह वही PIT-शैली का तर्क है जिसका उपयोग कोप्युला लेख मार्जिन फिट करने से पहले करता है; यहां हम यूनिफॉर्म तक जाने के बजाय स्टैंडर्डाइजेशन पर रुक जाते हैं।)
स्टेप 2: DCC कोरिलेशन रिकर्शन
हम एक सहायक प्रोसेस मॉडल करते हैं, एक सिमेट्रिक पॉजिटिव-डेफिनिट मैट्रिक्स, जिसमें स्टैंडर्डाइज्ड रेजिड्युअल के आउटर प्रोडक्ट से संचालित एक GARCH-जैसा रिकर्शन है:
जहां:
- स्टैंडर्डाइज्ड रेजिड्युअल का अनकंडीशनल कोरिलेशन मैट्रिक्स है (यह कोरिलेशन टारगेटिंग है — नीचे और अधिक जानकारी),
- यह नियंत्रित करता है कि आज का शॉक कोरिलेशन को कितनी मजबूती से खींचता है,
- पर्सिस्टेंस को नियंत्रित करता है — कल का कितना आगे बढ़ता है,
- और मीन-रिवर्जन बाधा है (जिसमें ), जो सीधे यूनिवैरिएट GARCH में के समान है।
ध्यान दें कि संरचना एक स्केलर GARCH(1,1) रिकर्शन के समान ही है, लेकिन मैट्रिक्स पर: एक दीर्घकालिक एंकर , एक शॉक टर्म, और एक पर्सिस्टेंस टर्म। क्योंकि यह पॉजिटिव-सेमी-डेफिनिट मैट्रिक्स का एक कॉन्वेक्स कॉम्बिनेशन है (, रैंक-1 आउटर प्रोडक्ट, और पिछला ), पॉजिटिव डेफिनिट बना रहता है जब तक है और वेट नॉन-नेगेटिव हैं। यही हमें मुफ्त में गारंटीशुदा वैध कोवेरियंस मैट्रिक्स दिलाता है।
लगभग एक कोरिलेशन मैट्रिक्स है लेकिन बिल्कुल नहीं — इसका डायगोनल ठीक 1 नहीं है। इसलिए हम इसे नॉर्मलाइज करते हैं:
एलिमेंटवाइज, असेट और के बीच कंडीशनल कोरिलेशन है
यह हर एक टाइम स्टेप पर, संरचना से, एक उचित कोरिलेशन मैट्रिक्स है — यूनिट डायगोनल, ऑफ-डायगोनल में, पॉजिटिव डेफिनिट। पूरा कंडीशनल कोवेरियंस दोबारा जोड़ें:
वह अंतिम एलिमेंटवाइज फॉर्म वह है जिसका आप लगातार उपयोग करेंगे: दो असेट का कंडीशनल कोवेरियंस उनके डायनामिक कोरिलेशन गुणा उनकी प्रत्येक की डायनामिक वोलैटिलिटी है। दाईं ओर हर सामग्री समय-परिवर्तनशील है और एक ऐसे मॉडल से आती है जिसे आप अनुमानित कर सकते हैं।
पूरे मॉडल में सिर्फ दो कोरिलेशन पैरामीटर हैं, और , चाहे हो या । वोलैटिलिटी वाला हिस्सा रैखिक रूप से स्केल करता है (प्रति असेट एक यूनिवैरिएट GARCH, प्रत्येक में ~4-5 पैरामीटर, सभी स्वतंत्र रूप से और शर्मनाक रूप से समानांतर फिट किए गए)। यही कारण है कि DCC वहां स्केल करता है जहां BEKK और VECH नहीं कर सकते: डाइमेंशनैलिटी का अभिशाप तक सीमित है, जो ऑप्टिमाइज्ड होने के बजाय टारगेटेड है (सैंपल एस्टिमेट के रूप में प्लग किया गया)।
स्केलर प्रतिबंध और उसकी कीमत
स्केलर का मतलब है कि हर असेट पेयर एक ही कोरिलेशन गतिशीलता साझा करता है — समायोजन की वही गति और वही पर्सिस्टेंस। BTC-ETH कोरिलेशन और DOGE-SHIB कोरिलेशन एक ही लय में चलते हैं, भले ही उनकी अर्थव्यवस्था अलग हो। यह ट्रैक्टेबिलिटी की कीमत है, और यह आमतौर पर एक स्वीकार्य कीमत है। जनरलाइजेशन (मैट्रिक्स के साथ जनरलाइज्ड DCC; कैप्पिएलो-एंगल-शेपर्ड असममित DCC) इसे पैरामीटर और अनुमान स्थिरता की कीमत पर ढीला करते हैं। हम नीचे aDCC का उल्लेख करते हैं।
DCC क्वासि-लॉग-लाइकलिहुड
और अनुमानित करने के लिए हमें लाइकलिहुड चाहिए। एंगल का मुख्य परिणाम यह है कि गॉसियन लॉग-लाइकलिहुड एक वोलैटिलिटी भाग और एक कोरिलेशन भाग में अलग हो जाता है, जो टू-स्टेप एस्टिमेटर को न्यायसंगत बनाता है। यह मानते हुए कि , समय पर लॉग-लाइकलिहुड योगदान है
को प्रतिस्थापित करें। फिर और , और का उपयोग करते हुए:
अब जोड़कर और घटाकर इसे विभाजित करें:
वोलैटिलिटी भाग केवल यूनिवैरिएट GARCH पैरामीटर पर निर्भर करता है ( के माध्यम से) — इसे मैक्सिमाइज करना ठीक उतना ही है जितना स्वतंत्र यूनिवैरिएट GARCH मॉडल फिट करना, जो हमने स्टेप 1 में किया। कोरिलेशन भाग , स्टेप 1 के स्टैंडर्डाइज्ड रेजिड्युअल दिए जाने पर, और पर निर्भर करता है ( के माध्यम से)। इसलिए स्टेप 2 में हम केवल यह मैक्सिमाइज करते हैं
( टर्म पर निर्भर नहीं करता, इसलिए हम इसे हटा देते हैं)। यह चाहे कितने भी असेट हों, एक दो-पैरामीटर ऑप्टिमाइजेशन है — यही पूरी बात है। इसे क्वासि-लाइकलिहुड कहा जाता है क्योंकि टू-स्टेप एस्टिमेटर कंसिस्टेंट है लेकिन पूरी तरह एफिशिएंट नहीं है; स्टैंडर्ड एरर को सुधार की जरूरत है (Engle & Sheppard 2001), लेकिन सिग्नल जनरेशन के लिए पॉइंट एस्टिमेट ही मायने रखते हैं।
क्रिप्टो के लिए, गॉसियन इनोवेशन टेल रिस्क को कम करके आंकते हैं। मल्टीवैरिएट स्टूडेंट-t लाइकलिहुड को स्वैप करना में एक ड्रॉप-इन बदलाव है (गॉसियन कर्नेल को मल्टीवैरिएट- डेंसिटी से बदलें और एक डिग्री-ऑफ-फ्रीडम पैरामीटर जोड़ें)। हम स्पष्टता के लिए नीचे दिए गए एस्टिमेटर में गॉसियन क्वासि-लाइकलिहुड बनाए रखते हैं और नोट करते हैं कि कहां प्रवेश करता है — भाग 1-2 के स्टैंडर्डाइजेशन ने मार्जिन पर पहले से t-इनोवेशन का उपयोग किया, जो अधिकतर टेल लाभ को पकड़ लेता है।
पायथन इम्प्लीमेंटेशन
एक स्पष्ट लेकिन महत्वपूर्ण तथ्य: arch लाइब्रेरी मल्टीवैरिएट GARCH या DCC नहीं करती। arch एक शानदार यूनिवैरिएट इंजन है (हम इसी के लिए इस पर भरोसा करते हैं), लेकिन इसमें कोई dcc_model नहीं है। आपके व्यावहारिक विकल्प हैं:
archके ऊपर अपना खुद का DCC बनाएं —archसे यूनिवैरिएट मॉडल फिट करें, स्टैंडर्डाइज्ड रेजिड्युअल निकालें, NumPy/SciPy में -रिकर्शन और कोरिलेशन क्वासि-लाइकलिहुड इम्प्लीमेंट करें, और दो स्केलर ऑप्टिमाइज करें। यह वही है जो हम नीचे करते हैं। यह लगभग 60 लाइनें हैं और पूरी तरह पारदर्शी है।mgarchPyPI पैकेज — एक हल्का शुद्ध-पायथन DCC-GARCH इम्प्लीमेंटेशन। त्वरित फिट के लिए सुविधाजनक, कम लचीला यदि आप GJR मार्जिन या t-इनोवेशन को सटीक रूप से वायर करना चाहते हैं।- R का
rmgarch(Alexios Galanos) — संदर्भ इम्प्लीमेंटेशन।dccspec/dccfitDCC, aDCC, GARCH-कोप्युला, स्टूडेंट-t, और उचित स्टैंडर्ड एरर को सपोर्ट करते हैं। यदि आप गंभीर मल्टीवैरिएट वोलैटिलिटी रिसर्च कर रहे हैं, तोrmgarch(यदि जरूरी हो तोrpy2के माध्यम से पायथन से कॉल किया गया) गोल्ड स्टैंडर्ड है।
हम विकल्प 1 बनाते हैं क्योंकि यह हर चलने वाले हिस्से को स्पष्ट बनाता है और भाग 1-2 के यूनिवैरिएट स्किल्स का पुन: उपयोग करता है।
स्टेप 1: arch के साथ यूनिवैरिएट GARCH मार्जिन फिट करें
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())
स्टैंडर्डाइज्ड रेजिड्युअल पर एक त्वरित सैनिटी चेक मायने रखता है। यदि किसी कॉलम का स्टैंडर्ड डेविएशन 1 से बहुत दूर है, या उसके स्क्वायर में भारी बचा हुआ ऑटोकोरिलेशन है ( पर Ljung-Box), तो यूनिवैरिएट मार्जिन गलत तरीके से निर्दिष्ट है और DCC स्टेप उस त्रुटि को विरासत में लेगा। पहले मार्जिन को ठीक करें — यही भाग 2 के लिए था।
स्टेप 2: DCC रिकर्शन और क्वासि-लॉग-लाइकलिहुड
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)
कुछ वर्षों के डेली डेटा पर एक BTC/ETH/SOL/BNB बुक पर इसे चलाने से इस आकार का आउटपुट मिलता है (नीचे दी गई संख्याएं उदाहरणात्मक हैं, किसी विशिष्ट दिनांकित प्रयोग से नहीं — इसे अपने खुद के डेटा पर चलाएं):
DCC estimates: a = 0.0287, b = 0.9401, a+b = 0.9688
log-likelihood: -3812.44
इसे कैसे पढ़ें:
- छोटा है — कोरिलेशन मैट्रिक्स एक ही दिन के शॉक पर नहीं उछलता। हर दिन को आउटर प्रोडक्ट की ओर सिर्फ ~3% धकेलता है।
- बड़ा है — कोरिलेशन अत्यधिक पर्सिस्टेंट हैं। एक बार जब बुक एक स्ट्रेस इवेंट में जुड़ जाती है, तो वह कुछ समय तक जुड़ी रहती है, धीरे-धीरे की ओर वापस डिके होती है। यह क्रिप्टो ड्रॉडाउन के वास्तविक अनुभव से मेल खाता है: कीमत स्थिर होते ही कोरिलेशन तुरंत वापस नहीं आते।
- मीन-रिवर्जन की पुष्टि करता है। कोरिलेशन प्रोसेस का एक स्टेशनरी दीर्घकालिक स्तर () है जिस पर वह लौटता है, जिसका हाफ-लाइफ लगभग दिन है। यदि आप कभी का अनुमान अनिवार्य रूप से 1 के बराबर लगाते हैं, तो कोरिलेशन प्रोसेस इंटीग्रेटेड है — इसका कोई दीर्घकालिक एंकर नहीं है, आमतौर पर आपके सैंपल के अंदर एक स्ट्रक्चरल ब्रेक का लक्षण जिसे मॉडल अनंत पर्सिस्टेंस के रूप में अवशोषित कर रहा है।
लगभग-यूनिट पर्सिस्टेंस और छोटा शॉक लोडिंग असेट क्लासों में DCC का विशिष्ट फिंगरप्रिंट है, और क्रिप्टो कोई अपवाद नहीं है। यही कारण है कि 30-दिन रोलिंग कोरिलेशन एक इतना खराब विकल्प है: एक रोलिंग विंडो अंतर्निहित रूप से ऐसे और मान लेती है जो इस डिके संरचना से बिल्कुल मेल नहीं खाते।
कुछ इम्प्लीमेंटेशन नोट्स जो वास्तविक डिबगिंग समय बचाते हैं:
- इनिशियलाइजेशन।
[0.03, 0.94]पर शुरू करना विशिष्ट क्रिप्टो अनुमान को दर्शाता है: छोटा (कोरिलेशन शॉक पर प्रतिक्रिया करते हैं लेकिन हिंसक रूप से नहीं), बड़ा (कोरिलेशन पर्सिस्टेंट हैं)। यदि आपका ऑप्टिमाइज़र की ओर भटकता है, तो कोरिलेशन प्रोसेस इंटीग्रेटेड है — आमतौर पर सैंपल में एक स्ट्रक्चरल ब्रेक का संकेत (एक रीजीम परिवर्तन जिसे मॉडल पर्सिस्टेंस के रूप में फिट करने के लिए संघर्ष कर रहा है)। - टाइमिंग कन्वेंशन। लूप के अंदर हम को के विरुद्ध स्कोर करते हैं और फिर अगले स्टेप के लिए के साथ अपडेट करते हैं। यह को केवल तक की जानकारी का फंक्शन बनाए रखता है — कोई लुक-अहेड नहीं। यह ऑफ-बाय-वन गलत होना सबसे आम DCC बग है, और यह चुपचाप इन-सैंपल फिट को बढ़ा देता है।
- कोरिलेशन टारगेटिंग। हम को अनुमानित करने के बजाय सैंपल कोरिलेशन के रूप में प्लग करते हैं। यही ऑप्टिमाइजेशन को दो-आयामी बनाता है। कीमत यह है कि पूरे सैंपल का उपयोग करता है, इसलिए एक सख्त वॉक-फॉरवर्ड में आपको इसे केवल ट्रेनिंग विंडो पर दोबारा अनुमानित करना होगा (नीचे देखें)।
स्टेप 3: कोरिलेशन और कोवेरियंस पथ पुनर्निर्मित करें
एक बार तय हो जाने पर, रिकर्शन को एक बार फिर चलाएं, इस बार पूरे (और ) पथ को स्टोर करते हुए ताकि डाउनस्ट्रीम रणनीतियां इसका उपयोग कर सकें।
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))
rho_btc_eth सीरीज पूरी कवायद का प्रतिफल है: एक संख्या के बजाय, अब आपके पास एक डेली कोरिलेशन है जिसे आप प्लॉट, थ्रेशोल्ड, या किसी रणनीति में फीड कर सकते हैं। वास्तविक क्रिप्टो डेटा पर आप आमतौर पर इसे शांत अवधियों में लगभग 0.5 से लेकर स्ट्रेस के दौरान 0.9 से ऊपर तक की रेंज में देखेंगे — ठीक वही फैलाव जिसे एक सैंपल कोरिलेशन औसत निकाल देता है।
वन-स्टेप-अहेड फोरकास्ट
लाइव ट्रेडिंग के लिए आपको अभी उपलब्ध जानकारी से अगले-पीरियड चाहिए। वोलैटिलिटी वाला हिस्सा प्रत्येक arch मॉडल के वन-स्टेप फोरकास्ट से आता है; कोरिलेशन वाला हिस्सा रिकर्शन का एक और मोड़ है:
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)
याद रखें सब कुछ स्केल्ड (×100) यूनिट में है क्योंकि हमने arch को series * 100 पर फिट किया। किसी रणनीति में फीड करने से पहले वोलैटिलिटी को 100 से (और कोवेरियंस को से) विभाजित करके कच्ची-रिटर्न यूनिट में वापस लाएं। स्केलिंग को सीधा रखना थकाऊ है लेकिन साइलेंट बग का एक आम स्रोत है।
एप्लिकेशन 1: पेयर्स ट्रेडिंग के लिए एक डायनामिक हेज रेशियो
क्लासिक मार्केट-न्यूट्रल पेयर — एक असेट में लॉन्ग, दूसरे में बीटा-भारित शॉर्ट — हेज रेशियो पर जीता-मरता है। इसे एक ट्रेनिंग विंडो पर स्टैटिक OLS द्वारा अनुमानित करें और आप ठीक उसी पुरानी-कोरिलेशन समस्या को विरासत में लेते हैं जिसके बारे में यह पूरा लेख है: जो हेज पिछली तिमाही में मार्केट एक्सपोजर को न्यूट्रलाइज करता था, वह इस तिमाही में गलत है।
DCC आपको हेज रेशियो एक टाइम सीरीज के रूप में देता है। BTC का उपयोग करके ETH एक्सपोजर का मिनिमम-वेरियंस हेज कंडीशनल रिग्रेशन गुणांक है
दाईं ओर हर टर्म एक DCC आउटपुट है। हेज रेशियो दो अलग-अलग कारणों से चलता है, और DCC उन्हें साफ-साफ अलग करता है: कोरिलेशन बदलता है (असेट जुड़ते या अलग होते हैं), और वोलैटिलिटी अनुपात बदलता है (एक असेट अपेक्षाकृत अधिक वोलेटाइल हो जाता है)। एक रोलिंग-OLS बीटा दोनों प्रभावों को एक लैग के साथ आपस में मिला देता है; DCC उन्हें अलग-अलग बताता है।
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()
spread को आप जो भी पेयर्स इंजन चलाते हैं उसमें फीड करें। डायनामिक हेज खुद से कोई एज नहीं बनाता — यह उस स्प्रेड को जिसे आप ट्रेड करते हैं समय के साथ वास्तव में मार्केट-न्यूट्रल बनाता है, ताकि आपका मीन-रिवर्जन सिग्नल बहती हुई दिशात्मक एक्सपोजर से दूषित न हो। यदि आप पेयर्स रणनीतियां बनाते हैं, तो यह सीधे Statistical Arbitrage & Pairs Trading in Crypto और distance approach to pairs के फ्रेमवर्क में फिट बैठता है, उनके निश्चित हेज रेशियो की जगह लेता है। कोरिलेशन सीरीज खुद भी किसी भी रोलिंग विंडो की तुलना में correlation-based pair signal के लिए एक साफ इनपुट है — आपको एक शोरगुल वाले विंडोड एस्टिमेट के बजाय एक स्मूद, मॉडल-कंसिस्टेंट मिलता है।
को लाइव उपयोग करते समय दो सावधानियां विशेष रूप से रखें। पहला, इसे लैग करें — पर ट्रेड करें, कभी भी समकालीन पर नहीं, अन्यथा आप पीक कर रहे हैं। दूसरा, एक हेज रेशियो जो हर दिन इधर-उधर घूमता है वह टर्नओवर और फीस पैदा करता है; क्रिप्टो के 24/7 बाजार में शॉर्ट लेग पर फंडिंग लागत के साथ, एक अति-प्रतिक्रियाशील हेज उससे ज्यादा खून बहा सकता है जितना वह ड्रिफ्ट ठीक करता है। को स्मूद करें (एक EWMA, या हेज को केवल तभी रीबैलेंस करें जब वह एक बैंड से आगे बढ़े) और पूरी चीज को समझदारी से साइज करें — एक शोरगुल वाले सिग्नल से पोजीशन साइजिंग अपना खुद का अनुशासन है, जिसे Kelly criterion sizing में कवर किया गया है।
एप्लिकेशन 2: समय-परिवर्तनशील पोर्टफोलियो वेरियंस
एक वेट वेक्टर वाले पोर्टफोलियो के लिए, कंडीशनल वेरियंस है
एक स्टैटिक कोवेरियंस मैट्रिक्स के साथ — मार्कोविट्ज डिफॉल्ट — यह संख्या एक स्थिरांक है जिसे आपने एक बार निकाला और मान लिया कि यह अभी भी सच है। यह सच नहीं है। पोर्टफोलियो रिस्क बाजार के साथ सांस लेता है, और यह ठीक तब सबसे ज्यादा सांस लेता है जब कोरिलेशन उछलते हैं, क्योंकि ड्रॉडाउन में टर्म और टर्म दोनों एक साथ बढ़ते हैं और गुणा होते हैं। एक पोर्टफोलियो जो शांत बाजारों में 40% वार्षिक वोलैटिलिटी जैसा दिखता था, वह स्ट्रेस वाले सप्ताह में 80%+ चल सकता है, और एक स्टैटिक कोवेरियंस मैट्रिक्स आपको बताएगा कि कुछ नहीं बदला।
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())
यह समय-परिवर्तनशील वह ईमानदार इनपुट है जिसकी रिस्क-आधारित एलोकेशन को जरूरत है। स्टैटिक सैंपल कोवेरियंस के साथ मीन-वेरियंस ऑप्टिमाइजेशन (Markowitz for crypto) एक कल्पना के विरुद्ध ऑप्टिमाइज कर रहा है; इसे (या इसका शॉर्ट-होराइजन फोरकास्ट) फीड करना खुद एफिशिएंट फ्रंटियर को समय-परिवर्तनशील बनाता है और ऑप्टिमाइज़र को बढ़ते-कोरिलेशन रीजीम में डी-रिस्क करने के लिए मजबूर करता है, न कि उनके बाद। रिस्क-पैरिटी और हायरार्किकल दृष्टिकोण — HRP + CVaR pipeline — कोवेरियंस इनपुट के प्रति और भी संवेदनशील हैं, क्योंकि पूरा एलोकेशन रिस्क मैट्रिक्स का फंक्शन है। और यदि आप एलोकेटर्स की सीधे तुलना कर रहे हैं, जैसे portfolio optimization algorithms compared में, तो वे स्टैटिक या डायनामिक कोवेरियंस उपभोग करते हैं या नहीं, यह अक्सर एल्गोरिदम की पसंद से ज्यादा वास्तविक रिस्क का बड़ा चालक होता है।
सीधा एप्लिकेशन पूरे पोर्टफोलियो को वोलैटिलिटी टारगेट करना है: एक टारगेट वार्षिक वोलैटिलिटी चुनें, और हर पीरियड ग्रॉस एक्सपोजर को से स्केल करें ताकि वास्तविक रिस्क संकट में उछलने के बजाय लगभग स्थिर रहे। यह भाग 4 के साथ लूप बंद करता है, जो ठीक इसी नियम को बनाता और बैकटेस्ट करता है।
एप्लिकेशन 3: रीजीम सिग्नल के रूप में कोरिलेशन
हेजिंग और साइजिंग से परे, कोरिलेशन मैट्रिक्स एक मैक्रो सिग्नल रखता है। सबसे उपयोगी स्केलर जिसे आप निकाल सकते हैं वह है औसत पेयरवाइज कोरिलेशन:
जब पूरी बुक में बढ़ता है, तो बाजार एक रिस्क-ऑफ रीजीम में प्रवेश कर रहा है — व्यक्तिगत कहानियां मायने रखना बंद कर देती हैं और सब कुछ एक मैक्रो बीटा के रूप में ट्रेड करता है। यह "संकट में कोरिलेशन 1 की ओर जाते हैं" का मात्रात्मक फिंगरप्रिंट है। यह ड्रॉडाउन का पूर्वानुमान देता है या उनके साथ मेल खाता है, जो इसे एक लैगिंग पोस्टमॉर्टम के बजाय एक उपयोगी रीजीम इंडिकेटर बनाता है।
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)
आप risk_off का उपयोग एक स्टैंडअलोन थ्रॉटल के रूप में कर सकते हैं (ग्रॉस एक्सपोजर काटें, स्टॉप चौड़े करें, उन मीन-रिवर्जन रणनीतियों को रोकें जो तब कुचली जाती हैं जब सब कुछ एक साथ ट्रेंड करता है) या एक अधिक औपचारिक रीजीम मॉडल में एक फीचर के रूप में। यह regime detection with HMMs में छिपे-मार्कोव दृष्टिकोण के साथ स्वाभाविक रूप से जोड़ी बनाता है: औसत DCC कोरिलेशन उन अधिक जानकारीपूर्ण ऑब्जर्वेशन वेरिएबल में से एक है जिसे आप किसी HMM को सौंप सकते हैं, क्योंकि यह सिस्टमिक स्ट्रेस के बारे में उस तरह से आगे-देखने वाला है जो ट्रेलिंग रिटर्न नहीं होते। ईमानदार चेतावनी: बढ़ता कोरिलेशन आपको बताता है कि डाइवर्सिफिकेशन विफल हो रहा है, यह नहीं कि बाजार किस दिशा में जाता है। यह एक रिस्क सिग्नल है, अल्फा सिग्नल नहीं, और इसे उसी तरह साइज किया जाना चाहिए — देखें the asymmetry of losses and profits कि क्यों एक रिस्क रीजीम को दिशात्मक दांव के रूप में मानना बुरी तरह खत्म होता है।
व्यावहारिक विचार
अनुमान स्थिरता और असेट की संख्या
DCC, BEKK की तुलना में कहीं बेहतर स्केल करता है, लेकिन "स्केल करता है" का मतलब "मुफ्त" नहीं है। कोरिलेशन-टारगेटिंग मैट्रिक्स एक सैंपल कोरिलेशन है, और सैंपल कोरिलेशन मैट्रिक्स तब खराब-कंडीशन्ड हो जाते हैं जब ऑब्जर्वेशन की संख्या के करीब पहुंचता है। 4 असेट और 1000 दिनों के साथ आप ठीक हैं। 60 असेट और 400 दिनों के साथ, लगभग सिंगुलर है, लाइकलिहुड में इसका इनवर्स फट जाता है, और न्यूमेरिकल शोर से नॉन-PD की ओर भटक सकता है। समाधान, आमतौर पर जरूरत के क्रम में:
- रिकर्शन चलाने से पहले को एक संरचित टारगेट (Ledoit-Wolf, या आइडेंटिटी / एक कॉन्स्टेंट-कोरिलेशन मैट्रिक्स की ओर) की ओर श्रिंक करें। बड़ी बुक के लिए यह एकल सबसे उच्च-लीवरेज समाधान है।
- असेट को कुछ सेक्टरों (मेजर्स, L1s, DeFi, मीम्स) में समूहित करें, सेक्टर स्तर पर अंदर और आर-पार मॉडल करें, या रॉ असेट के बजाय प्रिंसिपल-कंपोनेंट फैक्टर पर DCC चलाएं।
- अधिक असेट के बजाय अधिक डेटा को प्राथमिकता दें। DCC को एक लंबे, साफ, समकालीन इतिहास की अतृप्त भूख है — जो ठीक वही है जो युवा टोकन के पास नहीं होता।
वास्तविकता में, सीधे DCC को अधिकतम कुछ दर्जन असेट तक ही रखें। एक बड़े यूनिवर्स के लिए, फैक्टर रिटर्न प्लस इडियोसिंक्रेटिक रेजिड्युअल पर DCC मानक वर्कअराउंड है।
कोरिलेशन टारगेटिंग एक कीमत वाला शॉर्टकट है
को टारगेट करना अनुमान को ट्रैक्टेबल बनाता है लेकिन पूरे-सैंपल अनकंडीशनल कोरिलेशन को हर में बेक कर देता है। एक सख्त बैकटेस्ट में यह एक लुक-अहेड लीक है: आपका दिन- कोरिलेशन मैट्रिक्स पूरे सैंपल के औसत कोरिलेशन को "जानता" है, जिसमें भविष्य भी शामिल है। ईमानदार मूल्यांकन के लिए आपको को केवल ट्रेनिंग विंडो पर दोबारा अनुमानित करना होगा और आउट-ऑफ-सैंपल में इसे स्थिर रखना होगा, या इसे आगे रोल करना होगा। यह वही अनुशासन है जिसे पूरा walk-forward optimization फ्रेमवर्क लागू करता है, और पूरे एरे पर एक सुविधाजनक np.cov(Z) के साथ इसे गलती से तोड़ना आसान है — जैसा हमारा ऊपर दिया गया शिक्षण कोड करता है। किसी एकल P&L संख्या पर भरोसा करने से पहले इसे ठीक करें।
रीफिट कैडेंस और लुक-अहेड अनुशासन
आपको हर दिन को दोबारा ऑप्टिमाइज करने की जरूरत नहीं है — वे स्थिर पैरामीटर हैं। एक समझदार प्रोडक्शन कैडेंस:
- और यूनिवैरिएट GARCH पैरामीटर को दोबारा अनुमानित करें साप्ताहिक या मासिक रूप से।
- फिल्टर चलाएं (अपडेट , ) हर पीरियड फ्रीज किए गए पैरामीटर के साथ ताकि ताजा और मिले। फिल्टरिंग सस्ती है; फिटिंग नहीं।
- हमेशा फोरकास्ट करें, कभी स्मूद न करें। तक की जानकारी से बनाया गया का उपयोग पर ट्रेड करने के लिए करें। टू-पास संरचना (एक विंडो पर फिट, फिर आगे फिल्टर) वह है जो आपको ईमानदार रखती है।
DCC बैकटेस्ट और लाइव परफॉरमेंस के बीच का अंतर लगभग हमेशा एक लुक-अहेड लीक है — पूरे-सैंपल , समकालीन , या उस डेटा पर रीफिटिंग जिसमें वह ट्रेड शामिल है जिसका आप मूल्यांकन कर रहे हैं। बैकटेस्ट को लाइव कंडीशन से मिलाने का अनुशासन backtest-live parity में अपना खुद का विषय है, और DCC एक ऐसा मॉडल है जो यहां लापरवाही को अधिकतर से ज्यादा सजा देता है। यदि, साफ वॉक-फॉरवर्ड मूल्यांकन के बाद, आपकी रणनीति के लिए डायनामिक कोरिलेशन एक सामान्य रोलिंग एस्टिमेट पर कुछ नहीं जोड़ता, तो यह एक वास्तविक और प्रकाशन-योग्य नकारात्मक परिणाम है — honest negative results में दी गई मानसिकता सीधे लागू होती है।
असममित DCC (aDCC)
ठीक जैसे यूनिवैरिएट लीवरेज इफेक्ट (भाग 2) का मतलब है कि बुरी खबर अच्छी खबर से ज्यादा वोलैटिलिटी बढ़ाती है, कोरिलेशन संयुक्त नेगेटिव शॉक के बाद संयुक्त पॉजिटिव शॉक की तुलना में ज्यादा बढ़ते हैं। Cappiello, Engle & Sheppard (2006) इसे असममित DCC के साथ पकड़ते हैं, नेगेटिव-पार्ट स्टैंडर्डाइज्ड रेजिड्युअल के आउटर प्रोडक्ट से संचालित एक टर्म जोड़कर:
जहां और संयुक्त डाउनसाइड मूव से अतिरिक्त कोरिलेशन उछाल को मापता है। क्रिप्टो के लिए, जहां क्रैश-कोरिलेशन प्रमुख रिस्क है, असममिति टर्म आमतौर पर महत्वपूर्ण है और एक अतिरिक्त पैरामीटर के लायक है। rmgarch सीधे aDCC फिट करता है (model="aDCC"); हमारे NumPy एस्टिमेटर में टर्म जोड़ना एक सीधा अभ्यास है।
तुलना: DCC बनाम विकल्प
एक क्रिप्टो बुक के लिए कोवेरियंस मैट्रिक्स पाने के तरीकों में DCC कहां बैठता है? ईमानदार सारांश:
| दृष्टिकोण | पैरामीटर | स्केल करता है | समय-परिवर्तनशील ? | PD गारंटीशुदा? | टेल डिपेंडेंस? |
|---|---|---|---|---|---|
| सैंपल / रोलिंग कोवेरियंस | 0 (विंडो लंबाई) | कोई भी | मोटे तौर पर (लैग्ड, शोरगुल) | नहीं (पैचिंग चाहिए) | नहीं |
| EWMA (RiskMetrics) | 1 () | कोई भी | हां (सिंगल डिके) | हां | नहीं |
| CCC-GARCH | मार्जिन + | दर्जनों | नहीं (स्थिर ) | हां | नहीं |
| DCC-GARCH | मार्जिन + 2 | दर्जनों | हां | हां | नहीं |
| aDCC-GARCH | मार्जिन + 3 | दर्जनों | हां, असममित | हां | आंशिक |
| BEKK | हां (समृद्ध) | हां | नहीं | ||
| VECH | हां (सबसे समृद्ध) | कष्टकारी | नहीं | ||
| GARCH-कोप्युला | मार्जिन + कोप्युला | दर्जनों (वाइन्स) | स्थिर कोप्युला | हां | हां |
इस तालिका की कुछ व्याख्याएं:
- EWMA सस्ता बेसलाइन है जिसे DCC मददगार होने का दावा करने से पहले हर किसी को हराना चाहिए। यह भावना में एक-पैरामीटर विशेष मामला है — कोवेरियंस पर सीधे लागू एक एकल एक्सपोनेंशियल डिके — और कई बुक के लिए इसे आउट-ऑफ-सैंपल सुधारना आश्चर्यजनक रूप से कठिन है। यदि DCC साफ वॉक-फॉरवर्ड में EWMA को नहीं हराता, तो EWMA का उपयोग करें।
- CCC बनाम DCC इस पूरे लेख का सार है: वही फैक्टराइजेशन, लेकिन CCC को फ्रीज करता है और DCC इसे हिलने देता है। दो अतिरिक्त पैरामीटर () पूरा अंतर हैं, और क्रिप्टो में वे अपनी कमाई कमाते हैं।
- BEKK/VECH समृद्ध गतिशीलता खरीदते हैं — हर कोवेरियंस हर पिछले शॉक पर प्रतिक्रिया कर सकता है — लेकिन पैरामीटर की कीमत उन्हें छोटी बुक तक सीमित करती है। 4 असेट से आगे के लिए वे कोई वास्तविक विकल्प नहीं हैं।
- GARCH-कोप्युला एकमात्र पंक्ति है जिसमें टेल डिपेंडेंस के तहत "हां" है। वह फिर से पूरकता है: DCC संयुक्त डिस्ट्रीब्यूशन के डायनामिक केंद्र को मॉडल करता है, कोप्युला इसकी स्थिर टेल्स को मॉडल करते हैं। यदि आपका रिस्क प्रश्न है "जब सब कुछ एक साथ टूटता है तो क्या होता है," तो copula pipeline की ओर बढ़ें; यदि यह है "अभी मेरा हेज रेशियो / पोर्टफोलियो वेरियंस क्या है," तो DCC की ओर बढ़ें।
एक सिस्टमैटिक क्रिप्टो डेस्क के लिए व्यावहारिक डिफॉल्ट: मुख्य भाग में हेज रेशियो और डायनामिक कोवेरियंस के लिए DCC (या aDCC), टेल-रिस्क और CVaR के लिए एक कोप्युला ओवरले, और सैनिटी-चेक बेसलाइन के रूप में EWMA जो आपको ईमानदार रखता है कि क्या अतिरिक्त मशीनरी खुद के लिए भुगतान कर रही है।
सीमाएं
- स्केलर गतिशीलता। सभी पेयर के लिए एक और एक एक मजबूत प्रतिबंध है। BTC-ETH और दो अस्पष्ट alts एक ही समायोजन गति साझा करते हैं। जनरलाइज्ड DCC इसे ढीला करता है लेकिन उस पैरामीटर विस्फोट को दोबारा पेश करता है जिसे टालने के लिए DCC डिजाइन किया गया था।
- टू-स्टेप एफिशिएंसी हानि। क्वासि-लाइकलिहुड एस्टिमेटर कंसिस्टेंट है लेकिन पूरी तरह एफिशिएंट नहीं है, और नैव स्टैंडर्ड एरर गलत हैं। यदि आप इन्फरेंस की परवाह करते हैं तो Engle-Sheppard सुधार का उपयोग करें; सिग्नल जनरेशन के लिए पॉइंट एस्टिमेट पर्याप्त हैं।
- डिफॉल्ट रूप से गॉसियन टेल्स। सादा गॉसियन क्वासि-लाइकलिहुड संयुक्त टेल रिस्क को कम करके आंकता है। स्टूडेंट-t इनोवेशन मदद करते हैं; वास्तविक टेल डिपेंडेंस (एक साथ एक्सट्रीम मूव की संभावना) के लिए, DCC गलत टूल है और एक copula model सही है। DCC आपको कोरिलेशन का डायनामिक बॉडी देता है; कोप्युला आपको स्थिर टेल देते हैं। गंभीर डेस्क दोनों का उपयोग करते हैं।
- कोरिलेशन कार्य-कारण नहीं है, और दिशा भी नहीं। बढ़ता चेतावनी देता है कि डाइवर्सिफिकेशन विफल हो रहा है; यह बाजार दिशा के बारे में कुछ नहीं कहता। एक रिस्क सिग्नल को दिशात्मक अपेक्षाओं से ओवरलोड न करें।
- डेटा भूख। ऊपर की हर चीज लंबे, साफ, समकालिक इतिहास मानती है। क्रिप्टो के सबसे नए और सबसे दिलचस्प टोकन इन तीनों का उल्लंघन करते हैं।
सारांश
- स्टैटिक कोरिलेशन क्रिप्टो में एक झूठ है। कोरिलेशन क्लस्टर होते हैं, पर्सिस्ट करते हैं, और ड्रॉडाउन में 1 की ओर उछलते हैं — ठीक तब जब डाइवर्सिफिकेशन को मदद करनी चाहिए। एक सैंपल एक रीजीम-स्विचिंग प्रोसेस को एक निरर्थक बीच के मान में औसत निकाल देता है।
- पूरा मल्टीवैरिएट GARCH (VECH, BEKK) स्केल नहीं करता। पैरामीटर की संख्या के रूप में बढ़ती है; दोनों व्यवहार में कुछ मुट्ठी भर असेट तक सीमित हैं।
- DCC (Engle 2002) समस्या को फैक्टर करता है: , जिसमें स्वतंत्र यूनिवैरिएट GARCH फिट से आता है (भाग 1-2 का पुन: उपयोग) और एक दो-पैरामीटर रिकर्शन से आता है। यह दर्जनों असेट तक स्केल करता है क्योंकि केवल ऑप्टिमाइज्ड होते हैं।
- रिकर्शन , में नॉर्मलाइज्ड, , के साथ हर स्टेप पर एक वैध पॉजिटिव-डेफिनिट कोरिलेशन मैट्रिक्स पैदा करता है।
archDCC नहीं करता।archके साथ मार्जिन फिट करें, फिर यहां दिए गए ~60-लाइन NumPy/SciPy एस्टिमेटर को इम्प्लीमेंट करें, याmgarch(पायथन) याrmgarch(R, संदर्भ) का उपयोग करें।- तीन ठोस प्रतिफल: पेयर्स ट्रेडिंग के लिए एक डायनामिक हेज रेशियो ; रिस्क-आधारित एलोकेशन के लिए एक ईमानदार समय-परिवर्तनशील पोर्टफोलियो वेरियंस ; और रिस्क-ऑफ रीजीम सिग्नल के रूप में औसत पेयरवाइज कोरिलेशन।
- अनुशासन ही सब कुछ है। कोरिलेशन टारगेटिंग पूरे-सैंपल औसत को लीक करती है, इसलिए को केवल ट्रेनिंग डेटा पर दोबारा अनुमानित करें; हर हेज रेशियो को लैग करें; आगे फिल्टर करें, कभी स्मूद न करें। वॉक-फॉरवर्ड मूल्यांकन गैर-परक्राम्य है।
- aDCC एक डाउनसाइड-असममिति टर्म जोड़ता है और क्रिप्टो में आमतौर पर इसके लायक है, जहां क्रैश-कोरिलेशन हावी रहता है।
- भाग 4 इन फोरकास्ट का उपयोग एक वोलैटिलिटी-टारगेटेड रणनीति बनाने और बैकटेस्ट करने के लिए करता है।
संदर्भ:
- 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.
MarketMaker.cc Team
क्वांटिटेटिव रिसर्च और स्ट्रैटेजी