@fanxy
2020-05-10T19:23:38.000000Z
字数 11589
阅读 5986
樊潇彦
复旦大学经济学院
金融数据
下载: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.9927
log(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+2001
par(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+2009
H=c(1,seq(5,40,by=5)) # h=1,5,10...40
t_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-3
xlab="",ylab="",main="CSCO波动率期限结构")
matplot(x=tdx,FCmat_cat,type="l", # P194,图5-4
xlab="",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+1986
plot(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.245
alpha0=1.5e-5; alpha1=0.19; beta1=0.72; theta=0.007; lambda=0
for (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.563
print(data.frame(fixsigma,Asiacall,Asiacall_check)) # 比较亚式期权结果
}
r=rsp # 用sp100收益率
for (withlambda in c(0,1)){
if (withlambda==0){ # 没有lambda
para0=c(alpha0=1.5e-5,alpha1=0.13,beta1=0.7,theta=0.8)*1.1
}else{ # 有lambda
para0=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.1
report(para0)
如果根据定义,用两种资产的收益率直接计算协方差和相关系数,则得到的 是不随时间变化的,但是在实际运用中,我们希望得到任意两种资产随时间变化的相关系数。根据统计理论,有:
# P198:
xp=csco+cat
xm=csco-cat
m1=garchFit(~1+garch(1,1),data=csco,trace=F)
vcsco=m1@sigma.t
m2=garchFit(~1+garch(1,1),data=cat,trace=F)
vcat=m2@sigma.t
m3=garchFit(~1+garch(1,1),data=xp,trace=F) # 收益率之和的模型
summary(m3)
vxp=m3@sigma.t
m4=garchFit(~1+garch(1,1),data=xm,trace=F) # 收益率之差的模型
summary(m4)
vxm=m4@sigma.t
COV=(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+2001
par(mfcol=c(2,1))
range(COR,cor_ewma,cor_ewma2) # 查看纵轴取值范围,设定 ylim,作图5-5
plot(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+sp5
xm=cat-sp5
m1=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.t
vsp5=m3@sigma.t
beta=(vxp^2-vxm^2)/(4*vsp5^2) # 计算可变的beta
par(mfcol=c(1,1))
tdx=c(1:2515)/252+2001
coef(lm(cat~sp5))
plot(tdx,beta,xlab='year',ylab='beta',type='l') # 作图
abline(h=c(1.146)) # 标记不变的beta
index(cat)[which(beta==max(beta))] # 显示风险最大的一天
记 种资产的协方差矩阵 ,权重 和收益率 分别为 维列向量, 为单位列向量。允许做空、目标收益率为 的最小方差投资组合问题可以描述为:
如果不考虑目标收益率,问题的解简化为:
rtn=rtn5 # 5支股票
colnames(rtn)=stocklist=c("BA","CAT","IBM","MSFT","PG")
# 计算最小方差组合权重和波动率,绘制表5-2
One=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) %*% One
w=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)=stocklist
Vol=round(t(Vol)*100,2)
rownames(Vol)=c(stocklist,"Portfolio")
Wgt
Vol
# 用fPortfolio包中的命令复制表5-2
library(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$weights
range(wgt)
prtn=M2$returns
mean(prtn)
sqrt(var(prtn))
Mean=apply(rtn[2012:2515,],2,mean)
Mean
v1=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+2009
par(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模型提高对金融数据的预测力。具体步骤为:
# P212
da=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-13
m4=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)预测