Copula函数思想
Copula函数能够把随机变量之间的相关关系与变量的边际分布分开进行研究,这种思想方法在多元统计分析中非常重要。直观来看,可以将任意维的联合分布H(x1,...,xn)=P(X1<=x1,...,Xn<=xn)分成两步来处理。第一步是,对所有的单随机变量Xi通过累积分布函数Fi,我们可以得到Ui=Fi(Xi),这是一个均匀随机变量;第二步是,随机变量间的关联可以通过直接连接这些均匀变量的n元Copula函数C(u1,...,un)来描述。
Copula函数是定义域为[0,1]均匀分布的多维联合分布函数,其核心概念是以Copula函数将多个随机变量的边缘分布耦合起来。Copula函数的基本思想就是,通过把边缘变量转化为均匀分布变量而不需要考察很多不同的边缘分布以简化问题,然后再把相关性定义为一个在均匀分布上的联合分布。
Copula函数种类
常用的Copula函数有高斯Copula函数,Gumbel Copula函数, Clayton Copula函数, Frank Copula函数。
在风险管理中,我们常常用Copula函数来估计VAR,其过程如下:
选择Copula函数,估计参数(详情可参照Copula理论及其在金融分析中的应用)
第一步:分别选择能够较好地描述资产收益边缘分布Fi和相关结构的Copula函数;
第二步:根据所有的边缘分布函数F和Copula函数,最大化对数似然函数估计边缘分布函数Fi和Copula函数的相应参数;
蒙特卡洛模拟估计VAR
第一步:生成两个独立的服从(0,1)均匀分布的随机数u和w,u即为要模拟的第一个伪随机数,令Cu(v)=w,通过Cu(v)的逆函数可以计算得到另一个伪随机数v=Cu^{-1}(w),从而得到符合Copula函数的随机数对(u, v);
第二步:通过随机数(u, v)和边缘分布函数累计概率函数的逆函数得到各资产收益率的模拟序列;
第三步:根据各资产权重得到组合收益序列,取q分位数作为VAR的估计值。
Copula函数计算Var的Python实现
在这里我们使用Python的pycopula包来实现
import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib import cm from pycopula.copula import ArchimedeanCopula from pycopula.visualization import pdf_2d, cdf_2d from scipy import stats # 读取facebook、apple公司14-19年收盘数据,计算日收益率 data_fb = pd.read_csv('FB.csv', header=0, index_col=0, engine='python') data_apl = pd.read_csv('AAPL.csv', header=0, index_col=0, engine='python') data = np.array([data_fb['close'].pct_change().dropna(), data_apl['close'].pct_change().dropna()]).T # 使用t分布拟合其分布 t = stats.t dt1 = t.fit(data[:, 0]) dt2 = t.fit(data[:, 1])
分布如下图所示
# 拟合Copula函数clayton,由于全部拟合边缘t分布参数不理想,这里直接采用t分布之前拟合的自由度参数,只优化loc和scale以及clayton函数的theta paramX1 = {'df': 3.34, 'loc': None, 'scale': None} paramX2 = {'df': 3.32, 'loc': None, 'scale': None} hyperParams = [paramX1, paramX2] param = clayton.fit(data, method='mle', marginals=[t, t], hyper_param=hyperParams, hyper_param_bounds=[[-1, 1], [0, 1], [-1, 1], [0, 1]]) # 蒙特卡洛模拟 # 首先生成服从[0, 1]均匀分布的两组随机数(u, w) u = np.random.uniform(0, 1, size=10000) w = np.random.uniform(0, 1, size=10000) # w = C_u(v), 其中C_u(v)为C(u, v)对u求偏导结果, # v = C_u^{-1}(w)通过反函数法得到服从C(u, v)的(u, v) # C(u, v) = (u^{-theta} + v^{-theta} - 1)^{-1/theta} # C_u(v) = (u^{-theta} + v^{-theta} - 1)^{-(1+theta)/theta} * u^{-theta-1} # C_u^{-1}(w) = [(w^{-theta/(1+theta)}-1)*u^{-theta}+1]^{-theta} theta = param[0] v = ((w**(-theta/(1+theta))-1)*u**(-theta)+1)**(-theta) # 利用u,v对应边缘分布函数的累计概率函数的逆函数 x = t.ppf(u, df=param[1][0]['df'], loc=param[1][0]['loc'], scale=param[1][0]['scale']) y = t.ppf(v, df=param[1][1]['df'], loc=param[1][1]['loc'], scale=param[1][1]['scale'])
# 假设两个公司资金投资权重分别为0.3和0.7,得到对应1分位、5分位、10分位的损失 z = 0.3 * x + 0.7 * y
p = np.percentile(z, (1, 5, 10), interpolation='midpoint')
# 最后查看拟合得到的Copula函数的CDF和PDF分布图 u, v, C = cdf_2d(clayton) u, v, c = pdf_2d(clayton) fig = plt.figure() ax = fig.add_subplot(121, projection='3d', title="Clayton copula CDF") X, Y = np.meshgrid(u, v) ax.set_zlim(0, 1) ax.plot_surface(X, Y, C, cmap=cm.Blues) ax.plot_wireframe(X, Y, C, color='black', alpha=0.3) ax = fig.add_subplot(122, projection='3d', title="Clayton copula PDF") ax.set_zlim(0, 5) ax.plot_surface(X, Y, c, cmap=cm.Blues) ax.plot_wireframe(X, Y, c, color='black', alpha=0.3) plt.show()