@fanxy
2020-05-10T11:23:38.000000Z
字数 11589
阅读 6338
樊潇彦 复旦大学经济学院 金融数据
下载:Ch12.rar
setwd("D:\\...\\Ch12")install.packages("fPortfolio","RQuantLib","qcc")## 调用library(fPortfolio)library(RQuantLib)library(qcc)library(rugarch)library(fGarch)library(zoo)library(tseries)library(forecast)library(timeSeries)library(tidyverse)library(readxl)library(ggplot2)load("Ch12_data.Rdata") # 加载数据
对于标准GARCH(1,1)模型:
m1=garchFit(~1+garch(1,1),data=csco,trace=F)coef(m1) # 表5-1第二行:alpha1 + beta1 = 0.9770# 注:用rugarch包做,结果不同garch.sec= ugarchspec(variance.model = list(model="sGARCH",garchOrder=c(1,1)),mean.model = list(armaOrder=c(0,0),include.mean=T))garch_csco=ugarchfit(spec=garch.sec, data=csco)coef(garch_csco) # alpha1 + beta1 = 0.9927log(0.5)/log(coef(m1)[3]+coef(m1)[4]) # csco波动率冲击的半衰期m2=garchFit(~1+garch(1,1),data=cat,trace=F)log(0.5)/log(coef(m2)[3]+coef(m2)[4]) # cat波动率冲击的半衰期# 用rugarch包为cat建GARCH模型,sigma的拟合与预测garch_cat=ugarchfit(spec=garch.sec, data=cat)tdx=c(1:2515)/252+2001par(mfcol=c(2,1))plot(x=tdx,garch_cat@fit$sigma,type="l",xlab="",ylab="sigma",main="CAT波动率拟合值")fc_cat=ugarchforecast(garch_cat,n.ahead=30,data=cat) # 预测30期plot(fc_cat,which=3) # 作sigma的预测图,可以看到均值回转
距离 时刻 期的某资产的对数收益率为:
par(mfcol=c(1,1))tdx=c(1:507)/252+2009H=c(1,seq(5,40,by=5)) # h=1,5,10...40t_start=which(index(csco)=="2008-12-29")# 计算时间较长,可跳过以下三行,直接加载数据作图:#source("FCmat.R") # 调用函数#FCmat_csco=FCmat(H, var=csco, t_start,t_end=length(csco))#FCmat_cat =FCmat(H, var=cat, t_start,t_end=length(cat))load("FCmat.RData")matplot(x=tdx,FCmat_csco,type="l", # P193,图5-3xlab="",ylab="",main="CSCO波动率期限结构")matplot(x=tdx,FCmat_cat,type="l", # P194,图5-4xlab="",ylab="",main="CAT波动率期限结构")
假定股票对数价格服从如下随机过程:
在实际应用中,波动率是随时间变化的,Duan(1995)提出估计下述方程中的参数 :
# 读取 Duan(1995) S&P100 数据sp100=read.csv("sp100.csv",header=T)head(sp100)rsp=diff(log(sp100$Adj.Close))rsp=c(0,rsp)tdx=(1:nrow(sp100))/252+1986plot(tdx,rsp,type="l")abline(v=tdx[which(sp100$Date=="1987/10/19")],col="red") # 黑色星期一P0=100; rf=0; K=90; # 设定期权参数source("myfun_ch12.R") # 调用程序
sigma_a=0.245 # 年化收益率标准差sigma=sigma_a/sqrt(360) # 相应的日收益率标准差# 或者遵循 Duan(1995) 的方程设定,相应的年化收益率标准差也为0.245alpha0=1.5e-5; alpha1=0.19; beta1=0.72; theta=0.007; lambda=0for (fixsigma in c(1,0)){# 模拟数据P_simu=Psimu(S=1000, T=180, fixsigma)matplot(P_simu[,1:30],type="l",main=paste("价格模拟(fixsigma= ",fixsigma,")",sep=""),xlab="",ylab="")P_simu_est=Psimu(S=30, T=1000, fixsigma)# 计算期权价格max_PT_0=as.numeric(P_simu[T,]-K)*as.numeric(P_simu[T,]>K)Eurocall=exp(-rf*T)*mean(max_PT_0)Eurocall_check=EuropeanOption(type="call", underlying=100, strike=90,dividendYield = 0, riskFreeRate=0, maturity=0.5,volatility=sigma_a)$value # 用RQuantLib中命令计算print(data.frame(fixsigma,Eurocall,Eurocall_check)) # 比较欧式期权结果mnPs=apply(as.matrix(P_simu),2,mean)max_mnPs_0=as.matrix(mnPs-K)*as.numeric(mnPs>K)Asiacall=exp(-rf*T)*mean(max_mnPs_0)# AsianOption(averageType="arithmetic", type="call", underlying=100,# strike=90, div=0, riskFree=0, maturity=0.5,vol=sigma)# 亚式看涨期权计算时间较长,结果为:Asiacall_check=11.563print(data.frame(fixsigma,Asiacall,Asiacall_check)) # 比较亚式期权结果}
r=rsp # 用sp100收益率for (withlambda in c(0,1)){if (withlambda==0){ # 没有lambdapara0=c(alpha0=1.5e-5,alpha1=0.13,beta1=0.7,theta=0.8)*1.1}else{ # 有lambdapara0=c(alpha0=1.5e-5,alpha1=0.13,beta1=0.7,theta=0.8,lambda=0.05)*1.1}report(para0)}# 或者用模拟数据估计(模拟数据没有lambda)s=floor(runif(1,min=1,max=30))r=c(0,diff(log(P_simu_est[,s])))para0=c(alpha0=1.5e-5,alpha1=0.19,beta1=0.72,theta=0.007)*1.1report(para0)
如果根据定义,用两种资产的收益率直接计算协方差和相关系数,则得到的 是不随时间变化的,但是在实际运用中,我们希望得到任意两种资产随时间变化的相关系数。根据统计理论,有:
# P198:xp=csco+catxm=csco-catm1=garchFit(~1+garch(1,1),data=csco,trace=F)vcsco=m1@sigma.tm2=garchFit(~1+garch(1,1),data=cat,trace=F)vcat=m2@sigma.tm3=garchFit(~1+garch(1,1),data=xp,trace=F) # 收益率之和的模型summary(m3)vxp=m3@sigma.tm4=garchFit(~1+garch(1,1),data=xm,trace=F) # 收益率之差的模型summary(m4)vxm=m4@sigma.tCOV=(vxp^2-vxm^2)/4 # (5-5)式协方差COR=COV/(vcat*vcsco) # (5-6)式相关系数
此外,还可以基于指数加权移动平均方法(Exponentially Weighted Moving Average, EWMA)来计算方差和协方差。给定权重 ,样本 的EWMA预测值为:
qcc包中的ewma命令方程为:
# P200:source("EWMAvol.R")rtn=data.frame(csco,cat)M1=EWMAvol(rtn,theta=0.94)cor_ewma=M1[,3]/sqrt(M1[,1]*M1[,2])# 以均值为起点,调用qcc包中的ewma命令复制结果dacsco=c(mean(csco^2),(csco^2)[-2515])dacat=c(mean(cat^2),(cat^2)[-2515])dacscocat=c(mean(csco*cat),(csco*cat)[-2515])library(qcc)vcsco <- ewma(dacsco, lambda=0.06, plot=F)vcat <- ewma(dacat, lambda=0.06, plot=F)vcscocat <- ewma(dacscocat, lambda=0.06, plot=F)cor_ewma2=vcscocat$y/sqrt(vcsco$y*vcat$y)tdx=(1:2515)/252+2001par(mfcol=c(2,1))range(COR,cor_ewma,cor_ewma2) # 查看纵轴取值范围,设定 ylim,作图5-5plot(tdx,COR,xlab='year',ylab='cor',ylim=c(-0.35,1),type='l')title(main='(a) GARCH based')plot(tdx,cor_ewma,xlab='year',ylab='cor',ylim=c(-0.35,1),type='l')title(main='(b) EWMA with theta = 0.94')lines(tdx,cor_ewma2,col="red")
回归标准CAPM模型:
xp=cat+sp5xm=cat-sp5m1=garchFit(~1+garch(1,1),data=xp,trace=F) # 分别建GARCH(1,1)模型summary(m1)m2=garchFit(~1+garch(1,1),data=xm,trace=F)summary(m2)m3=garchFit(~1+garch(1,1),data=sp5,trace=F)summary(m3)vxp=m1@sigma.t # 提取标准差vxm=m2@sigma.tvsp5=m3@sigma.tbeta=(vxp^2-vxm^2)/(4*vsp5^2) # 计算可变的betapar(mfcol=c(1,1))tdx=c(1:2515)/252+2001coef(lm(cat~sp5))plot(tdx,beta,xlab='year',ylab='beta',type='l') # 作图abline(h=c(1.146)) # 标记不变的betaindex(cat)[which(beta==max(beta))] # 显示风险最大的一天
记 种资产的协方差矩阵 ,权重 和收益率 分别为 维列向量, 为单位列向量。允许做空、目标收益率为 的最小方差投资组合问题可以描述为:
如果不考虑目标收益率,问题的解简化为:
rtn=rtn5 # 5支股票colnames(rtn)=stocklist=c("BA","CAT","IBM","MSFT","PG")# 计算最小方差组合权重和波动率,绘制表5-2One=matrix(1,5,1)period=list(c(1:756),c(757:1512),c(1513:2515))Wgt=Vol=data.frame()for (p in 1:3){V=cov(rtn[period[[p]],])D=t(One) %*% solve(V) %*% Onew=solve(V) %*% One / as.numeric(D)Wgt=rbind(Wgt,t(w))v=sqrt(diag(V))sd_p=sqrt(t(w)%*%V%*%w)Vol=rbind(Vol,c(v,sd_p=sd_p))}Wgt=round(t(Wgt)*100,2)rownames(Wgt)=stocklistVol=round(t(Vol)*100,2)rownames(Vol)=c(stocklist,"Portfolio")WgtVol# 用fPortfolio包中的命令复制表5-2library(timeSeries)rtn=timeSeries(rtn[1:756,])Spec <- portfolioSpec()setSolver(Spec) <- "solveRshortExact"#setTargetReturn(Spec) <- 0.005 # 设定目标收益率a=efficientPortfolio(rtn, Spec)a@portfolio@portfolio$weights # 查看权重sqrt(diag(a@data@statistics$Cov)) # 资产标准差a@portfolio@portfolio$targetRisk[2] # 组合标准差
rtn=rtn3 # 3只股票colnames(rtn)=c("ABT","IBM","WMT")# 下面的命令运行时间很长(约13分钟),建议跳过#timestart<-Sys.time()#source("GMVPnew.R")#M2=GMVP(rtn,start=2011)#timeend<-Sys.time()#runningtime<-timeend-timestart#print(runningtime)# 直接加载结果load("M2_Portfolio.RData")names(M2)wgt=M2$weightsrange(wgt)prtn=M2$returnsmean(prtn)sqrt(var(prtn))Mean=apply(rtn[2012:2515,],2,mean)Meanv1=sqrt(apply(rtn[2012:2515,],2,var))print(v1)minV=sqrt(M2$minVariance)Vol=sqrt(M2$variances)range(minV,Vol)tdx=c(1:505)/505+2009par(mfcol=c(2,1))plot(tdx,wgt[1,],xlab='year',ylab='weights',type='l',ylim=c(-.75,1.5))lines(tdx,wgt[2,],lty=2,col="blue")lines(tdx,wgt[3,],lty=3,col="green")plot(tdx,Vol[,1],xlab='year',ylab='vol',type='l',ylim=c(0,0.04))lines(tdx,Vol[,2],lty=2,col="blue")lines(tdx,Vol[,3],lty=3,col="green")lines(tdx,minV,lty=4,col="red")
Tsay(2015)以美国1997-2010年每周的原油价格为例,介绍如何利用ARMA-GARCH模型提高对金融数据的预测力。具体步骤为:
# P212da=read.table("w-petroprice.txt",header=T)head(da)price=ts(da$US,frequency=52,start=c(1997,1))dp=ts(diff(price),frequency=52,start=c(1997,2))cprice=diff(price)arima(cprice,order=c(3,0,0),seasonal=list(order=c(2,0,0),period=5)) # (5-9)式,截距项不显著arima(cprice,order=c(3,0,0),seasonal=list(order=c(2,0,0),period=5),include.mean=F) # (5-9)式,去掉截距项m2=arima(cprice,seasonal=list(order=c(2,0,0),period=5), # 季节模型include.mean=F)c_star=cprice[11:716]-coef(m2)[1]-coef(m2)[2]*cprice[1:706] # 根据季节模型进行调整
m3=garchFit(~arma(3,0)+garch(1,1),data=c_star,trace=F,include.mean=F)summary(m3)par(mfcol=c(2,1))plot(m3,which=c(3,13)) # 图5-13m4=garchFit(~arma(3,0)+garch(1,1),data=c_star,trace=F,include.mean=F,cond.dist="std")summary(m4)plot(m4,which=13) # 图5-14(a)m5=garchFit(~arma(1,0)+garch(1,1),data=c_star,trace=F,include.mean=F,cond.dist="sstd")summary(m5)plot(m5,which=13) # 图5-14(b)plot(m5,which=c(3,7)) # 图5-15
M3=arima(c_star,order=c(3,0,0),include.mean=F)source("backtest.R")M3F=backtest(M3,c_star,650,2,inc.mean=F) # AR(3)预测source("backtestGarch.R")M4F=backtestGarch(c_star,650,2,inc.mean=F,cdist="sstd") # AR(1)-GARCH(1,1)预测