本节书摘来异步社区《量化金融R语言高级教程》一书中的第1章,第1.1节,作者: 【匈牙利】Edina Berlinger(艾迪娜•伯林格) , 等 译者: 高蓉 责编: 胡俊英,更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.1 多元时间序列分析
金融资产价格的运动、技术分析和量化交易的基本问题常常被纳入单变量框架下进行建模。我们能否预测证券价格未来是上升还是下降?这只特定的证券处于向上还是向下的趋势中?我们该买还是该卖?这些问题都需要慎重考虑。此外,投资者常常面对着更复杂的局面,不能仅仅把市场看成不相关的工具与决策问题组成的集合。
如果单独观察这些工具,可以发现正如市场有效假说所示,它们既非自相关又非均值可预测。但是,工具之间的相关性又显而易见。这个特性很可能为交易行为所利用,或者出于投机目的,或者出于对冲目的。以上探讨证实了多变量时间序列技术在数量金融中的应用。在本章中,我们会讨论两个在金融中应用广泛的著名计量经济学概念——协整和向量自回归模型。
1.1.1 协整
现在,我们考虑一个时间序列向量{{y}_{t}},它由元素y_{t}^{left( 1 right)},y_{t}^{left( 2 right)},cdots,y_{t}^{left( n right)}构成,每个元素独立地表示一个时间序列,如不同金融产品价格的变动。我们从协整数据序列的正式定义开始。
如果ntimes 1的时间序列中的每个序列都是d阶单整(特别在大多数的应用中,这些序列是1阶单整,这意味着序列是非平稳的单位根过程或者随机游走过程)。同时,存在一个线性组合{beta }'{{y}_{t}}是d-1阶单整(特别是当阶数为0时,序列是一个平稳过程)。那么,我们称时间序列向量{{y}_{t}}为协整的。
直观地来看,这个定义意味着经济中存在某些潜藏力量。这种力量使n个时间序列看似是相互独立的随机游走过程,但在长期中趋于一致。协整时间序列的一个简单例子是下文这个取自Hamilton(1994)的配对向量。我们通过这个例子研究协整,同时熟悉R中一些基本模拟技术:
标准统计检验可以严格地展示{{y}_{t}}中的单位根。R的tseries包或者urca包都可以实施单位根检验,本文使用后者。下文的R代码模拟了两个长度为1000的序列:
#生成两个长度为1000的时间序列
set.seed(20140623) #固定随机数种子
N <- 1000 #定义模拟的长度
x <- cumsum(rnorm(N)) #模拟一个正态随机游走
gamma <- 0.7 #设置初始的参数值
y <- gamma * x + rnorm(N) #模拟协整序列
plot(x, type='l') #画出两个序列
lines(y,col="red")
下载示例代码
如果你购买了Packt出版社的任何图书,都可以用自己的账号在网站http://www.packtpub.comhttp://www.packtpub.com下载示例的代码文件。如果你通过其他途径购买本书,那么可以访问网站http://www.packtpub.com/support,注册之后文件会直接通过邮件发送给你。
上列代码的输出结果如图1-1所示。
从图形上看,这两个序列看似都是随机游走过程,可以通过urca包实施ADF检验来检验平稳性。此外,R中还有很多其他检验方法。原假设的内容是过程中存在一个单位根(输出已经省略)。如果检验统计量小于临界值,我们就拒绝原假设:
#统计检验
install.packages('urca');library('urca')
#对模拟的单个时间序列做ADF test
summary(ur.df(x,type="none"))
summary(ur.df(y,type="none"))
对于这两个模拟序列,检验统计量大于一般显著性水平(1%、5%和10%)的临界值。因此,我们不能拒绝原假设,并且我们认为这两个序列各自都是单位根过程。
现在,对这两个序列取下文中的线性组合并绘出残差序列:
z = y - gamma*x #取序列的线性组合
plot(z,type='l')
上文代码的输出结果如图1-2所示。
{{z}_{t}} 显而易见是个白噪声过程。但是拒绝单位根还是需要ADF检验的结果判定:
summary(ur.df(z,type="none"))
在实际应用中,显然我们并不知道gamma 的值。我们需要基于原始数据,通过一个序列对另一个序列进行线性回归来估计这个值。这个检验协整的方法称为Engle-Granger方法,实施这个方法需要下文两个步骤。
(1){{y}_{t}}对{{x}_{t}}进行线性回归(简单的最小二乘估计)。
(2)检验残差以确定单位根的存在。
小提示
我们在这里应该注意n个序列的情形,其中独立协整向量的可能个数落在02时,协整关系可能不唯一。我们会在本章后面简要讨论r>1的情况。
简单线性回归可以通过lm函数拟合。残差可以从结果对象获得,如下文例子所示。ADF检验先按常规方式实施,再在所有显著性水平上确认是否拒绝原假设。此外,我们在本章后面讨论一些需要注意的事项:
#估计协整关系
coin <- lm(y ~ x -1) #不带截距项的回归
coin$resid #获取残差
summary(ur.df(coin$resid)) #残差的ADF检验
现在,我们考虑如何将这个理论转化为成功的交易策略。此时,我们需要援引统计套利(statistical arbitrage)或者配对交易(pair trading)的概念。这个概念,在它最早期最简单的形式中,精准地探索这种协整关系。这些方法的主要目的是基于两个时间序列之间的价差来建立交易策略。如果序列是协整的,那么我们可以预期它们的平稳线性组合将会回复到0。因此,我们只要卖出高估证券买入低估证券,然后坐等价差回复,就能赚钱。
小提示
统计套利这个术语,通常用于多种复杂统计和计量经济学技术,目的是在统计意义上探索资产定价的相对偏误,而非在理论均衡模型中进行比较。
这种观点背后的经济原理是什么?潜在的经济力量决定了时间序列的线性组合形成协整关系。这种力量无法在统计模型中得到严格确认,但是有时会作为问题中变量之间的长期关系而存在。比如,我们可以预期相同行业中的相似公司会具有相似的增长,可以预期金融产品的即期价格和远期价格通过无套利原则联系在一起,还可以预期存在某种贸易往来的国家的外汇汇率会共同运动,或者可以预期短期利率和长期利率趋于接近。当交易员推测未来价格相关性的时候,变量偏离了统计上或者理论上的预期联动开启了各种各样的量化交易策略。
协整概念会在随后的章节中更深入讨论。为此,我们首先需要介绍向量自回归模型。
1.1.2 向量自回归模型
显然,向量自回归模型(VAR)可以看成自回归模型(AR)从单变量向多变量的扩展。它们在应用计量经济学中的普及可以追溯到Sims(1980)的开创性论文。VAR模型是最重要的多变量时间序列模型,在计量经济学和金融学中有广泛应用。R包中的vars为R用户提供了一个优秀的框架。如果需要这个包的详细评论,可以参考Pfaff(2013)。如果需要计量经济学理论,可以参考Hamilton(1994)、Lütkepohl(2007)、Tsay(2010)或者Martin et al.(2013)。在本书中,我们仅对该主题提供一个简洁又直观的概述。
在VAR模型中,我们从考虑一个长度为n的时间序列向量{{y}_{t}}开始。VAR模型将每个变量的演进设定为所有其他变量滞后值的线性函数。换句话说,一个p阶的VAR模型如下:
这里,对所有的i=1,2,cdots ,p ,{{A}_{i}}是一个ntimes n的系数矩阵,而{{u}_{t}}是一个协方差矩阵正定的向量白噪声过程。向量白噪声这个术语假设不存在自相关,但允许各成分之间同期相关。换句话说,{{u}_{t}}的协方差矩阵是非对角的。
矩阵记号清楚地解释了VAR模型的一个特殊的特征:所有变量仅仅取决于该变量本身与其他变量的滞后值,这意味着模型没有显式地刻画变量之间的同期相依性。该特征允许我们通过普通最小二乘方法逐个估计方程。这样的模型称为缩减型VAR模型,与之相对的是结构型VAR模型,我们随后介绍。
显然,不存在同期影响的假设存在过度简化的问题。而且,由此推出的脉冲—响应关系结果(某个特定变量发生冲击引起的过程变动)也许会产生误导性,也许没有用。这些问题引发了我们介绍结构型VAR模型,这一类模型显式地刻画了变量间的同期影响:
这里,A_{i}^{*}=A{{A}_{i}} 而且B{{epsilon }_{t}}=A{{u}_{t}},因此,结构形式可以通过简化形式乘上一个恰当的参数矩阵A得到,这个矩阵刻画了变量之间同期的结构关系。
小提示
和往常一样,我们的符号与vars包的技术文档保持一致,它与Lütkepohl(2007)的符号类似。
SVAR建模中既有趣又困难的地方是所谓的识别问题。SVAR模型是不可识别的,换句话说,如果没有额外约束,矩阵A的参数无法被估计。
小提示
我们应该如何理解模型是不可识别的?它的基本含义是指存在着不同的(无限多个)参数矩阵,却有相同的样本分布。因此,基于样本不能识别出参数的唯一值。
在文献中,还有多种识别SVAR结构的方法,包括短期或者长期参数的约束,或者脉冲响应的符号约束[例如,见Fry-Pagan(2011)]。其中很多方法在R中仍然没有本地支持。这里,我们只介绍施加短期参数约束的一组标准技术,它们分别称为A模型、B模型和AB模型,每种技术在vars包里都有本地支持。
脉冲响应分析常常是建立VAR模型的主要目标之一。脉冲响应函数本质上刻画了一个变量对系统中任何其他变量被冲击的反应(响应)。如果系统包含K个变量,那么可以确定{{K}^{2}} 个脉冲响应函数。脉冲响应可以通过VAR过程的向量移动平均形式推导出数学方程,类似于单变量情形[细节参见Lutkepohl(2007)]。
VAR案例实现
作为一个说明性的案例,我们使用以下部分建立三元VAR模型。
股票收益率:本书中指定为从2004年1月1日到2014年3月3日微软的价格指数(注,原文如此)。
股票指数:它指定为从2004年1月1日到2014年3月1日的S&P500指数。
从2004年1月1日到2014年3月3日的美国国债利率。
我们的首要目的是通过额外变量预测股票市场指数,并识别脉冲响应。在这里,我们假设在给定的股票、股票市场整体和债券市场之间存在一种隐性长期关系。选择这个例子主要为了展示R编程环境中多种数据操作的可能性,以及通过一个很简单的案例说明详尽内容,而不是为了它的经济含义。
我们使用vars和quantmod包。如果你还没有这两个包,别忘了安装并加载它们:
install.packages('vars');library('vars')
install.packages('quantmod');library('quantmod')
quantmod包提供了大量工具,可以直接从在线资源下载金融数据,在本书中我们会频繁地需要。我们使用getSymbols()函数:
getSymbols('MSFT', from='2004-01-02', to='2014-03-31')
getSymbols('SNP', from='2004-01-02', to='2014-03-31')
getSymbols('DTB3', src='FRED')
默认状态下,雅虎财经(yahoofinance)用作股票和指数价格序列的数据源(参数设置为src='yahoo',在本例中被省略了)。惯例是下载开盘价、最高价、最低价、收盘价、成交量及调整价格。下载的数据存储在一个xts数据类里,默认根据股票代码自动命名(MSFT和SNP)。通过调用泛型plot函数可以画出收盘价,但quantmod包的chartSeries函数提供了更好的图形示例。
使用以下缩写可以访问下载数据的各个部分:
Cl(MSFT) #收盘价
Op(MSFT) #开盘价
Hi(MSFT) #当日最高价
Lo(MSFT) #当日最低价
ClCl(MSFT) #收盘价对收盘价的日收益率
Ad(MSFT) #当日调整收盘价
比如,使用这些缩写,日收盘价的收益率可以按以下方式绘制出来:
chartSeries(ClCl(MSFT)) #利用代码缩写的画图例子
上述命令输出如图1-3所示。
利率下载自联储经济数据(Federal Reserve Economic Data,FRED)数据源。接口的当前版本不允许对日期取子集。但是,下载的数据存储在一个xts数据类中,我们可以直接对需要的时期取子集。
DTB3.sub <- DTB3['2004-01-02/2014-03-31']
下载的价格(假设是非平稳时间序列)需要先转化为平稳序列才能分析。换句话说,我们处理的是根据调整序列计算出的对数收益率:
MSFT.ret <- diff(log(Ad(MSFT)))
SNP.ret <- diff(log(Ad(SNP)))
在转向VAR模型拟合之前,我们最后需要一个数据清洗的步骤才能继续。通过目测数据,我们可以看到在T-bill收益率序列中存在着缺失数据,而且数据集的长度各不相同(在某些日期,有利率报价,但没有股票价格)。为了解决这些数据质量问题,我们选择现在最易行的一种解决方案:合并数据集(通过省略那些没有全部3个数据的点),并删掉所有的NA数据。前者通过内连接参数执行(细节参见merge函数的帮助文档)。
dataDaily <- na.omit(merge(SNP.ret,MSFT.ret,DTB3.sub), join='inner')
在这里需要注意,VAR建模通常对低频数据进行。有一种简单的方法,可以把数据转成为月度或者季度的频率,使用以下函数可以返回给定时期内的开盘价、最高价、最低价和收盘价:
SNP.M <- to.monthly(SNP.ret)$SNP.ret.Close
MSFT.M <- to.monthly(MSFT.ret)$MSFT.ret.Close
DTB3.M <- to.monthly(DTB3.sub)$DTB3.sub.Close
简单的缩减VAR模型可以使用vars包的VAR()函数拟合数据。下列代码中的参数化允许在方程中有最大4阶的滞后,并且通过使用最优(最低)的赤池信息量值(Akaike Information Criterion)选择模型:
var1 <- VAR(dataDaily, lag.max=4, ic="AIC")
对于更多已有模型的选择,可以考虑使用VARselect(),它提供了多种信息准则(输出省略):
>VARselect(dataDaily,lag.max=4)
结果对象是一个varest类的对象。通过summary()方法或者show()方法可以获得参数估计和其他更多统计结果(换句话说,只需输入变量):
summary(var1)
var1
还有其他方法值得一提。varest包的自定义绘图方法可以对所有变量——包括它的拟合值、残差、残差的自相关和偏自相关函数——分别生成图像。你需要敲击回车键获得新变量的图像。vars包还提供了大量自定义设置,请查阅这个包的文档。
plot(var1) #Diagram of fit and residuals for each variables
coef(var1) #concise summary of the estimated variables
residuals(var1) #list of residuals (of the corresponding ~lm)
fitted(var1) #list of fitted values
Phi(var1) #coefficient matrices of VMA representation
通过简单地调用predict函数并加上想要的置信区间,可以得到使用估计的VAR模型进行的预测。
var.pred <- predict(var1, n.ahead=10, ci=0.95)
脉冲响应由irf()函数首先生成数值结果,然后可以通过plot()方法绘出图形。接着我们可以再得到每个变量的不同图像,包括各个脉冲响应函数以及相应自助置信区间,如下列命令所示:
var.irf <- irf(var1)
plot(var.irf)
现在,考虑使用之前讲过的A模型参数约束拟合结构VAR模型。识别SVAR模型需要frac{K(K-1)}{2} 个约束,在我们的例子里,约束个数是3。
小提示
细节可以参见Lütkepohl(2007)。本来额外需要frac{K(K+1)}{2} 个约束,但对角元素标准化为1,因而我们所需额外约束数如上。
SVAR模型的分析始于一个已估计的缩减型VAR模型(var1)。再用一个恰当的结构约束矩阵修正它。
为了简化,我们使用下列约束。
S&P指数的冲击对微软股票不存在同期影响。
S&P指数的冲击对利率不存在同期影响。
国债利率的冲击对微软股票不存在同期影响。
这些约束通过在矩阵A中设置相应的0,施加到SVAR模型中,矩阵A如下:
当在R中设定矩阵A为SVAR的估计参数,需要估计的参数的位因果设为NA值。这可以通过下列分配完成:
amat <- diag(3)
amat[2, 1] <- NA
amat[2, 3] <- NA
amat[3, 1] <- NA
最后,我们可以拟合SVAR模型,并且绘出脉冲响应函数(输出省略):
svar1 <- SVAR(var1, estmethod='direct', Amat = amat)
irf.svar1 <- irf(svar1)
plot(irf.svar1)
1.1.3 协整VAR和VECM
最后,我们综合已学内容,并且讨论协整VAR和误差修正模型(Vector Error Correction Models,VECM)的概念。
我们从一个协整变量系统(例如,在交易情形下,这表示一组可能由相同基本面驱动的相似股票)开始。前面讨论过的标准VAR模型必须在变量平稳时才能估计。我们知道,移除单位根模型的传统方法是对序列取一阶差分。但是,在协整序列情形下,这会导致过度差分,并且损失了变量水平长期共同运动表达的信息。最终,我们的目的是建立一个平稳变量的模型,它也包含初始协整非平稳变量之间的长期联系,即建立一个协整VAR模型。向量误差修正模型(VECM)捕捉了这种思想,它包括变量差分的p-1阶VAR模型和一个从已知的(估计的)协整关系推导出的误差修正项。从直觉上,使用股票市场案例,VECM模型建立了股票收益率之间的短期关系,同时通过对价格长期共同变动的偏离加以修正。
一个两变量的VECM可以正式写成下面公式,并作为一个数值例子进行讨论。设{{y}_{t}} 是一个由两个非平稳单位根序列y_{t}^{(1)}、y_{t}^{(2)} 组成的向量,这两个序列协整,协整向量为beta =(1,beta )。因此,一个恰当的VECM模型可以如下面的公式所示:
这里,Delta {{y}_{t}}={{y}_{t}}-{{y}_{t-1}} 且其中第一项通常称为误差修正项。
实践中有两种方法可以检验协整关系,并建立误差修正模型。在两变量情形下,Engle-Granger方法很有指导性,我们的数值案例基本沿袭了这种思想。在多变量情形下,其中可能的协整关系个数最大为(n-1),这时需要采用Johansen过程进行协整检验。尽管后者的理论框架远超本书范围,我们仍然会简要介绍实用工具,并且为你更深的研究提供参考书。
为了讲授一些运用于VECM建模的基本R功能,我们使用一个标准案例。它包括3个月和6个月的国债二级市场利率,正如之前所讨论的,可以从FRED数据库下载。我们先任意选择某个时期,如从1984年~2014年,再考虑检验这段时间内的数据。ADF检验(Augmented Dickey Fuller tests)表明不能拒绝单位根原假设。
library('quantmod')
getSymbols('DTB3', src='FRED')
getSymbols('DTB6', src='FRED')
DTB3.sub = DTB3['1984-01-02/2014-03-31']
DTB6.sub = DTB6['1984-01-02/2014-03-31']
plot(DTB3.sub)
lines(DTB6.sub, col='red')
我们通过运行一个简单的线性回归,可以一致地估计两个序列之间的协整关系。为了简化代码,我们定义变量{{x}_{1}}、{{x}_{2}}表示两个序列,y表示相应的向量序列。代码片段中的其他变量名惯例是明显的:
x1=as.numeric(na.omit(DTB3.sub))
x2=as.numeric(na.omit(DTB6.sub))
y = cbind(x1,x2)
cregr <- lm(x1 ~ x2)
r = cregr$residuals
如果回归残差(变量r)恰好是变量的某个线性组合构成的平稳序列,那么这两个序列确实协整。你可以使用常见的ADF方法进行检验,但在这个情形下,传统的临界值不合适,应该使用修正值[例如,参见Phillips and Ouliaris(1990)]。
因此对于协整的存在性,更合适的方法是使用指定检验,如Phillips-Ouliaris检验,它在tseries和urca包中都可以运用。下面采用最基本的tseries包,演示如下:
install.packages('tseries');library('tseries');
po.coint <- po.test(y, demean = TRUE, lshort = TRUE)
原假设表示两个序列不协整,因此p值小表示拒绝原假设并且协整关系存在。
当协整关系个数可能大于1时,适合使用Johansen过程。它的实施可以在urca包中找到:
yJoTest = ca.jo(y, type = c("trace"), ecdet = c("none"), K = 2)
######################
# Johansen-Procedure #
######################
Test type: trace statistic , with linear trend
Eigenvalues (lambda):
[1] 0.0160370678 0.0002322808
Values of teststatistic and critical values of test:
test 10pct 5pct 1pct
r <= 1 | 1.76 6.50 8.18 11.65
r = 0 | 124.00 15.66 17.95 23.52
Eigenvectors, normalised to first column:
(These are the cointegration relations)
DTB3.l2 DTB6.l2
DTB3.l2 1.000000 1.000000
DTB6.l2 -0.994407 -7.867356
Weights W:
(This is the loading matrix)
DTB3.l2 DTB6.l2
DTB3.d -0.037015853 3.079745e-05
DTB6.d -0.007297126 4.138248e-05
对r=0(不存在协整关系)的检验统计量大于临界值,这表明拒绝原假设。然而,当rleqslant 1时,不能拒绝原假设。因此,我们认为存在协整关系。协整向量根据检验结果下方的标准化特征向量的第一列给出。
最后一步是得出这个系统的VECM表达式,换句话说,先计算协整方程,再求出差分变量的滞后和误差修正项,再对它们运行OLS回归。所选择的适合的函数里使用了我们之前创建的ca.jo对象类。下面代码里的参数r=1表示了协整的秩:
>yJoRegr = cajorls(dyTest, r=1)
>yJoRegr
$rlm
Call:
lm(formula = substitute(form1), data = data.mat)
Coefficients:
x1.d x2.d
ect1 -0.0370159 -0.0072971
constant -0.0041984 -0.0016892
x1.dl1 0.1277872 0.1538121
x2.dl1 0.0006551 -0.0390444
$beta
ect1
x1.l1 1.000000
x2.l1 -0.994407
正如我们所预计的,误差修正项的系数是负的。从长期均衡水平上的短期的偏离会把变量推向零均衡偏离。
可以很容易地在二元情形下进行检查。Johansen过程会得到一个和采用了Engle-Grange过程从而一步步运用ECM相同的结果。这种观点在上传的R代码文件中有所示意。