copula是将多变量分布函数与其边际分布函数耦合的函数,通常称为边缘或简单的边缘。Copula是建模和模拟相关随机变量的绝佳工具。
Copula的主要吸引力在于,通过使用它们,您可以分别对相关结构和边缘(即每个随机变量的分布)进行建模。这可能是一个优点,因为对于某些边缘组合,没有内置函数来生成所需的多变量分布。例如,在R中,很容易从多元正态分布中生成随机样本,但是对于分别其边缘分别为Beta,Gamma和Student的分布来说,这样做并不容易。
此外,正如您可以通过谷歌搜索copula看到的那样,有各种各样的模型提供了一组非常不同且可定制的相关结构,可以很容易地适应观察到的数据并用于模拟。这种多样的选择是我最喜欢copulas的事情之一。
在这篇文章中,我们将展示如何使用copula包在R中使用copula,然后我们尝试提供一个简单的应用示例。
copulas如何工作
但首先,让我们试着了解copula的实际工作方式。
我们使用包n
给出协方差矩阵,从3个随机变量的多元正态分布中生成样本。sigma
MASS
图书馆(MASS)
set.seed(100)
m < - 3
n < - 2000
西格玛< - 矩阵(c(1,0.4,0.2,
0.4,1,-0.8,
0.2,-0.8,1),
nrow = 3)
z < - mvrnorm(n,mu = rep(0,m),Sigma = sigma,empirical = T)
现在我们使用cor()
和配对图检查样本相关性。
我们将设置method='spearman'
为使用 而不是函数中的'pearson'
方法cor()
(这在我们的例子中并不是绝对必要的,因为我们将使用椭圆形copula,如果你使用非椭圆形copula,你可能想要使用Spearman的Rho或Kendall的Tau)。
库(斗志)
心病(Z,方法= '斯皮尔曼')
pairs.panels(Z)
[,1] [,2] [,3]
[1,] 1.0000000 0.3812244 0.1937548
[2,] 0.3812244 1.0000000 -0.7890814
[3,] 0.1937548 -0.7890814 1.0000000
输出和配对图显示我们的样本确实具有完全预期的相关结构。
你< - pnorm(z)
pairs.panels(U)
这是包含在中的新随机变量的配对图u
。请注意,每个分布在[0,1]区间内是均匀的。还要注意,相关性相同,实际上,我们应用的变换并没有改变随机变量之间的相关结构。基本上我们只留下通常被称为依赖结构的东西。
库(RGL)
PLOT3D格式(U [1]中,u [2],U [1,3],PCH = 20,列= 'navyblue')
x1 < - qgamma(u [,1],shape = 2,scale = 1)
x2 < - qbeta(u [,2],2,2)
x3 < - qt(u [,3],df = 5)
PLOT3D格式(X1,X2,X3,PCH = 20,列= '蓝')
下面是我们模拟数据的3D图。花几秒钟检查一下。可以肯定的是,这是一个非常简单的依赖结构,它以非常简单的方式生成并且步骤非常少。
df < - cbind(x1,x2,x3)
pairs.panels(DF)
心病(DF,甲基= '斯皮尔曼')
x1 x2 x3
x1 1.0000000 0.3812244 0.1937548
x2 0.3812244 1.0000000 -0.7890814
x3 0.1937548 -0.7890814 1.0000000
这是随机变量的配对图:
使用copula包
上面执行的整个过程可以更有效,简洁地完成,并且完全由copula
包装进行一些额外的关注。让我们使用copula复制上面的过程。
库(系动词)
set.seed(100)
myCop < - normalCopula(param = c(0.4,0.2,-0.8),dim = 3,dispstr =“un”)
myMvd < - mvdc(copula = myCop,margin = c(“gamma”,“beta”,“t”),
paramMargins = list(list(shape = 2,scale = 1),
列表(shape1 = 2,shape2 = 2),
列表(df = 5)))
现在我们已经通过copula(普通copula)指定了依赖结构并设置了边缘,该mvdc()
函数生成了所需的分布。然后我们可以使用该rmvdc()
函数生成随机样本。
Z2 < - rmvdc(myMvd,2000)
colnames(Z2)< - c(“x1”,“x2”,“x3”)
pairs.panels(Z2)
模拟数据当然非常接近之前模拟的数据,并显示在下面的配对图中:
一个简单的应用示例
现在为现实世界的例子。我们将拟合两个股票的回报,并尝试使用copula模拟回报。我已经清理了两只股票的数据并计算了回报,你可以下载.csv格式的数据 。请注意,数据可能不是您在Google财经上可以找到的数据,因为我做了一些数据清理并删除了一些异常值而没有多想,主要是因为这是另一个应用程序的玩具示例。
让我们在R中加载回报
cree < - read.csv('cree_r.csv',header = F)$ V2
yahoo < - read.csv('yahoo_r.csv',header = F)$ V2
在直接进入copula拟合过程之前,让我们检查两个股票收益之间的相关性并绘制回归线:
情节(CREE,雅虎,PCH = '')
abline(LM(雅虎〜CREE),山口= '红',LWD = 1)
心病(CREE,雅虎,方法= '斯皮尔曼')
[1] 0.4023584
我们可以看到一个非常温和的正相关 :
在上面的第一个例子中,我选择了一个普通的copula模型而没有太多思考,但是,当将这些模型应用于实际数据时,应该仔细考虑哪些更适合数据。例如,许多copula更适合建模非对称相关,其他强调尾部相关性等等。我对股票回报的猜测是,t-copula应该没问题,但是猜测肯定是不够的。幸运的是,该VineCopula
软件包提供了一个很好的功能,告诉我们应该使用什么copula。本质上,VineCopula
库允许我们通过函数使用BIC和AIC执行copula选择BiCopSelect()
库(VineCopula)
你< - pobs(as.matrix(cbind(cree,yahoo)))[,1]
v < - pobs(as.matrix(cbind(cree,yahoo)))[,2]
selectedCopula < - BiCopSelect(u,v,familyset = NA)
selectedCopula
$家庭
[1] 2
$ PAR
[1] 0.4356302
$ PAR2
[1] 3.844534
请注意,我使用pobs()
函数将伪观察结果输入到选择算法中。伪观测值是[0,1]区间内的观测值。
拟合算法确实选择了t-copula(在$family
参考中编码为2 )并为我们估计了参数。通过键入,?BiCopSelect()
您实际上可以看到每个copula的编码。
让我们尝试使用copula
包装拟合建议的模型,并仔细检查参数拟合。
t.cop < - tCopula(dim = 2)
set.seed(500)
m < - pobs(as.matrix(cbind(cree,yahoo)))
适合< - fitCopula(t.cop,m,method ='ml')
COEF(FIT)
rho.1 df
0.43563 3.84453
很高兴看到拟合的copula的参数与函数建议的参数相同BiCopSelect()
。我们来看看我们刚估计的copula的密度
rho < - coef(fit)[1]
df < - coef(fit)[2]
persp(tCopula(暗= 2,ρ-,DF = DF),dCopula)
你< - rCopula(3965,tCopula(dim = 2,rho,df = df))
情节(U [1]中,u [2],PCH = ' 'COL =' 蓝')
心病(U,方法= '斯皮尔曼')
[,1] [,2]
[1,] 1.0000000 0.3972454
[2,] 0.3972454 1.0000000
这是载体中包含的样本的图u
:
来自copula的随机样本看起来有点接近独立情况,但这很好,因为回报之间的相关性很低。请注意,生成的样本与数据具有相同的相关性。
t-copula强调极端结果:它通常适用于在极值(分布的尾部)中存在高度相关性的建模现象。
还要注意它是对称的,这可能是我们的应用程序的问题,但是我们将忽略这一点。
现在我们正面临着困难:对边缘进行建模。为简单起见,我们将假设正态分布的回报,尽管众所周知它远非合理的假设。因此,我们估计边际的参数
cree_mu < - mean(cree)
cree_sd < - sd(cree)
yahoo_mu < - 意味着(雅虎)
yahoo_sd < - sd(雅虎)
让我们根据直方图绘制配件,以便直观地了解我们正在做的事情:
hist(cree,breaks = 80,main ='Cree returns',freq = F,density = 30,col ='cyan',ylim = c(0,20),xlim = c(-0.2,0.3))
线(SEQ(-0.5,0.5,0.01),dnorm(SEQ(-0.5,0.5,0.01),cree_mu,cree_sd),山口= '红',LWD = 2)
传奇('topright',c('Fitted normal'),col = c('red'),lwd = 2)
hist(yahoo,breaks = 80,main ='Yahoo returns',density = 30,col ='cyan',freq = F,ylim = c(0,20),xlim = c(-0.2,0.2))
线(SEQ(-0.5,0.5,0.01),dnorm(SEQ(-0.5,0.5,0.01),yahoo_mu,yahoo_sd),山口= '红',LWD = 2)
传奇('topright',c('Fitted normal'),col = c('red'),lwd = 2)
两个直方图显示如下
现在我们在函数中应用copula,mvdc()
然后用于rmvdc()
从生成的多变量分布中获取模拟观测值。最后,我们将模拟结果与原始数据进行比较。
copula_dist < - mvdc(copula = tCopula(rho,dim = 2,df = df),margin = c(“norm”,“norm”),
paramMargins = list(list(mean = cree_mu,sd = cree_sd),
list(mean = yahoo_mu,sd = yahoo_sd)))
sim < - rmvdc(copula_dist,3965)
好,现在我们有模拟数据,让我们进行视觉比较
情节(CREE,雅虎,主要= '返回')
点(SIM [1],SIM [2],COL = '红')
图例( 'bottomright',C( '观察', '模拟'),列= C( '黑', '红'),PCH = 21)
这是在假设正常边缘和依赖结构的t-copula的情况下数据的最终散点图:
由于此示例的目的仅仅是为了展示如何使用真实数据拟合copula并生成随机观察,我们将在此处停止。
正如好奇心让我向您展示如何通过调整df
t-copula中的参数来改变copula中的模拟值。
让我们尝试df=1
和df=8
set.seed(4258)
copula_dist < - mvdc(copula = tCopula(rho,dim = 2,df = 1),margin = c(“norm”,“norm”),
paramMargins = list(list(mean = cree_mu,sd = cree_sd),
list(mean = yahoo_mu,sd = yahoo_sd)))
sim < - rmvdc(copula_dist,3965)
情节(CREE,雅虎,主要= '返回')
点(SIM [1],SIM [2],COL = '红')
legend('bottomright',c('Observed','Simulated df = 1'),col = c('black','red'),pch = 21)
心病(SIM [1],SIM [2],方法= '斯皮尔曼')
copula_dist < - mvdc(copula = tCopula(rho,dim = 2,df = 8),margin = c(“norm”,“norm”),
paramMargins = list(list(mean = cree_mu,sd = cree_sd),
list(mean = yahoo_mu,sd = yahoo_sd)))
sim < - rmvdc(copula_dist,3965)
情节(CREE,雅虎,主要= '返回')
点(SIM [1],SIM [2],COL = '红')
legend('bottomright',c('Observed','Simulated df = 8'),col = c('black','red'),pch = 21)
心病(SIM [1],SIM [2],方法= '斯皮尔曼')
[1] 0.3929509
[1] 0.3911127
注意虽然Spearman的Rho类似,但我们获得的依赖结构有多么不同。
显然,该参数df
对于确定分布的形状非常重要。随着df
增加,t-copula倾向于高斯copula。
有问题吗?联系我们!
大数据部落 -中国专业的第三方数据服务提供商,提供定制化的一站式数据挖掘和统计分析咨询服务
统计分析和数据挖掘咨询服务:y0.cn/teradat(咨询服务请联系官网客服)
【服务场景】
科研项目; 公司项目外包;线上线下一对一培训;数据采集;学术研究;报告撰写;市场调查。
【大数据部落】提供定制化的一站式数据挖掘和统计分析咨询服务