python做var模型_【Python金融量化】VaR系列(五):Copula模型估计组合VaR-阿里云开发者社区...
1. 資產組合VaR建模方法回顧
文章中總結了通過DCC模型估計組合向前一日VaR的方法,整體思路如下:
●??通過Garch族模型估計各資產的波動率
●??通過DCC模型估計各資產間的相關系數,結合1得到資產組合的協方差矩陣
●??在各資產正態性假設的前提下,可以知道資產組合也服從正態分布,并且均值與協方差陣已在1,2中計算得到
●??在已知組合中各但資產權重w的情況下,根據下式計算組合VaR
文章中總結了通過蒙特卡洛方法估計組合向前K日VaR的方法,也可以僅計算組合向前一日VaR(本文只考慮向前1日的情況),文章中也對比了蒙特卡洛方法與DCC方法得到的結果,差異并不大。蒙特卡洛方法的思路如下:
●??根據Garch族模型估計資產的波動率
●??根據DCC模型估計組合的相關系數
●??在1,2的基礎上,在正態性假設前提下,得到組合的分布函數,對組合收益率進行模擬,在給定各資產權重w的情況下,可以得到組合的總收益
●??重復1-3若干次,可以得到組合總收益的模擬序列,類似HS方法,取p分位數即可
可以看出不論是DCC模型還是蒙特卡洛方法,都是在正態性假設的前提下,得到組合的分布函數再進行求解。事實上,也可以類比多元正態的概念構建多元t分布和多元漸進t分布,假設組合服從這樣的分布,求出分布的參數后,再用蒙特卡洛方法進行模擬,這些理論依據已經很成熟,推導過程見文獻[1],這里不再贅述。
但需要說明的是,多元t分布和多元漸近t分布都沒有邊際分布和線性組合依然多元t或者多元漸近t的性質。回憶多元正態的情況下,為了生成多元正態隨機數,實際上是先產生不相關的n組一元正態隨機數向量,然后通過cholesky分解轉換為符合給定相關系數矩陣的組合收益率模擬序列。如果組合的分布不具有類似多元正態的性質,要根據分布函數模擬組合收益就比較困難,必須直接通過多元分布函數產生隨機數,不能分解成單個資產去做,雖然也有相關的方法可以生成給定分布函數下隨機數,但都比較麻煩,這是之前方法的一個局限性。
此外,多元正態假設所有的單個資產都是正態分布,多元t分布和多元漸近t分布的邊際分布并非t分布或者漸近t分布,而不同的資產可能服從不同的分布,需要用不同方法去建模,已有的多元分布都不能滿足這一條件,這是之前方法的另一局限性。
比較理想的狀態是,我們可以用不同的方法對不同的單資產進行建模,最終n各資產具有不同的分布函數
這種情況下,如果可以找到一個連接函數G,通過這n個邊際分布得到組合的分布F,就可以解決上面所說的兩種局限。
這也正是本文總結的Copula模型的邏輯。
2.Copula模型
Sklar定理
Copula模型整體來說比較復雜,這里只對關鍵的部分加以說明,模型中最重要的定理是Sklar定理,也就是上面所說的理想情況,具體敘述如下
G稱為copula CDF,在sklar定義的假設下,如果我們已經通過一些單變量模型得到了單資產的分布函數,只需要確定出copula函數G,就相當于知道了組合的分布函數,從而把估計組合分布函數的問題轉化為估計copula函數的問題。當然copula函數也不是靠猜,有一些常用的copula函數可以選擇,在確定了copula函數之后,可以通過MLE等方法估計參數。
參數估計(MLE)
這里的C就是上文的G,見參考文獻[2],二元情況下,可以細分為
其中,序號1稱為Gumbel Copula函數,序號2稱為Clayton Copula函數,序號3稱為Frank Copula函數,之所以說明這三個,是因為這三個實際應用中比較多,python的copulalib包中也只提供這三種方法,不過本文并未嘗試這幾種方法,有興趣的可以自己嘗試下。
VaR估計思路
從之前的敘述中可以看出,通過copula函數得到的組合分布函數沒有非常好的解析表達式,所以直接通過定義計算VaR的方法行不通,一般采取與蒙特卡洛方法相結合的方式,生成給定copula函數下的隨機數,模擬資產組合的收益序列,再根據組合權重得到組合總收益,重復若干次,取p分位數。
隨機數構造
使用蒙特卡洛方法的難點在于生成給定copula函數下的隨機數,需要用到Nelsen定理,詳見參考文獻[2]
用Nelson定理構造隨機數的方法如下
看了下copulib的源碼,就是用這種方法構造的。而如果是多元正態copula或者多元t-copula的話, 有更簡便的方法。以二元為例,可以往更高維推廣
服從二元正態,可以直接模擬,然后再用標準正態分布函數作用,就可以得到符合給定多元正態copula的隨機數,多元t-copula分布類似。
在得到符合給定copula分布的隨機數u后,根據單個資產的分布F,可以得到單資產對應的隨機數z
隨后可以根據權重計算組合收益進而估計VaR。
綜上,可以將Copula函數估計VaR的過程總結如下
選擇copula函數,估計參數
第一步:根據單變量模型對所有單資產進行建模,估計分布函數F;
第二步:根據所有的分布函數F和給定copula函數,最大化對數似然函數估計參數;
蒙特卡洛模擬估計VaR
第一步:生成符合copula函數的隨機數;
第二步:通過隨機數得到各資產收益的模擬序列;
第三步:根據各資產權重得到組合收益序列,取p分位數作為VaR估計值
3.實證分析
數據:S&P500、US 10yr T-Note Fixed Term(同上一篇)
區間:2001-2010
蒙特卡洛模擬次數:10000次
數據和代碼在后臺回復“VaR5”獲取
僅估計最后一天的VaR。代碼中未給出太多注釋,可以參見文獻[1]第九章習題。
前兩道題首先通過threshold correlation說明正態性假設并不符合實際,threshold correlation定義如下,r(p)表示r的p分位數
結果如下
藍色線為真實收益序列的threshold correlation,紅色為標準正態的,如果將真實收益序列轉化為標準收益,結果如下
可以看出,二者相差很大,說明用多元正態進行建模并不符合實際。
1def getThre_cor(data,column1,column2,p):
2cor = pd.DataFrame(p,columns = ['p'])
3cor['thre_cor'] =0
4foriinrange(cor.shape[0]):
5ifp[i] <=0.5:
6condition1 = (data[column1] <= np.percentile(data[column1],p[i]*100))
7condition2 = (data[column2] <= np.percentile(data[column2],p[i]*100))
8else:
9condition1 = (data[column1] > np.percentile(data[column1],p[i]*100))
10condition2 = (data[column2] > np.percentile(data[column2],p[i]*100))
11datas = data.loc[condition1 & condition2,:]
12cor.loc[i,'thre_cor'] = np.corrcoef(datas[column1],datas[column2])[0,1]
13returncor
14
15def Thre_cor_norm(num,rou):
16np.random.seed(52)
17data = pd.DataFrame(index = range(num))
18data['r1'] = np.random.normal(size=(num,1))
19data['r2'] = np.random.normal(size=(num,1))
20
21data['r1_c'] = data['r1']
22data['r2_c'] = data.r1*rou + data.r2*(1- rou**2)**0.5
23returndata
24
25p = np.arange(0.15,0.90,0.05)
26rou = np.corrcoef(data1.Log_Return_SP,data1.Log_Return_US)[0,1]
27data_norm = Thre_cor_norm(30000,rou)
28cor_norm = getThre_cor(data_norm,'r1_c','r2_c',p)
29
30p = np.arange(0.15,0.86,0.01)
31cor = getThre_cor(data1,'Log_Return_SP','Log_Return_US',p)
32ax = plt.figure(figsize=(10,5))
33plt.plot(cor.p,cor.thre_cor,linewidth =2)
34plt.plot(cor_norm.p,cor_norm.thre_cor,linewidth =2,color ='red')
35plt.grid()
36plt.show()
第三道題為用t-garch分別對兩個單資產進行建模,估計參數d,不再說明;
第四道題為用第三問的結果建立二元正態copula模型,估計組合VaR,過程前面已經說明,代碼如下
估計copula函數的參數
1def getNegativeLoglikelihood_copula(rou,r):
2LogLikeLihood = -r.shape[0]*np.log(1- rou**2)/2- ((r.norm1**2+r.norm2**2-2*rou*r.norm1*r.norm2)/(2*(1- rou**2)) -
30.5*(r.norm1**2+ r.norm2**2)).sum()
4return-LogLikeLihood
5
6rou_best = optimize.fmin(getNegativeLoglikelihood_copula,rou0, \
7args=(copula_data,),ftol =0.000000001)
8print('估計結果為:',rou_best)
模擬
1data4['u1c'] = data4['u1']
2data4['u2c'] = data4.u1*rou + data4.u2*(1- rou**2)**0.5
3data4['F1'] = norm(0,1).cdf(data4['u1c'])
4data4['F2'] = norm(0,1).cdf(data4['u2c'])
5data4['z1'] = t(d_SP).ppf(data4.F1)*((d_SP-2)/d_SP)**0.5
6data4['z2'] = t(d_US).ppf(data4.F2)*((d_US-2)/d_US)**0.5
7data4['R1'] = data4.z1*sigma_SP**0.5
8data4['R2'] = data4.z2*sigma_US**0.5
9data4['R'] =0.5*data4.R1 +0.5* data4.R2
10VaR = -np.percentile(data4.R,1)
最終估計結果為VaR = 0.0101,可以與上篇文章最后一日的結果相對比,基本上是一致的。
原文發布時間為:2018-10-1
本文作者:量化小白H
本文來自云棲社區合作伙伴“Python愛好者社區”,了解相關信息可以關注“Python愛好者社區”。
總結
以上是生活随笔為你收集整理的python做var模型_【Python金融量化】VaR系列(五):Copula模型估计组合VaR-阿里云开发者社区...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实验报告总结_小学四年级数学下册全册知识
- 下一篇: python中的str方法和repr方法