(本文首发于个人公众号“数据与平行世界”,欢迎关注!)
从这一篇开始,我们讨论时间序列的建模和预测。
之前,我们从数据探索的角度所讨论的时间序列,是按时间顺序排列的一个观测序列。从模型的角度,一个时间序列
对时间序列模型进行统计推断的基础是平稳性(stationary)。
我们对一个时间序列进行观察,观测值或许具有随机性,但是从一个时间周期到下一个时间周期,有些序列的观测会表现出相同的随机模式。比如,观察上证指数2010-2019年这10年间的每日收盘价格和日对数收益率序列(图-的上方和下方),我们会发现每一年价格序列的均值随时间剧烈波动,对数收益率序列的均值却几乎不变:
library(tsibble)
library(tidyverse)
library(feasts)
library(tsibbledata)
library(lubridate)
library(cowplot)
library(pedquant)
szzs<-md_stock("000001.ss",source="163",from='2010-01-01',to='2019-12-31')
szzs_tbl<-as_tibble(szzs[[1]])%>%
mutate(return=c(0,diff(close)/close[-nrow(szzs[[1]])]),
logreturn=c(0,diff(log(close))))
p1<-szzs_tbl%>%
ggplot(aes(x=date,y=close))+
geom_line(color='blue')+
theme_bw()
p2<-szzs_tbl%>%
ggplot(aes(x=date,y=logreturn))+
geom_line(color='blue')+
theme_bw()
plot_grid(p1,p2,nrow=2,align="v",rel_heights=c(1,1))
时间序列的平稳性指的就是这种统计特征不随时间而变的性质。平稳性有两种类型。如果一个时间序列的统计特征都随时间不变(也就是常数),那么可称为严平稳。此时,从序列中任取两个包含n个连续观测的子序列,它们的概率分布都是相同的。这是一种很强的数学假设。实际上,可以把要求放宽,如果一个序列的均值、方差具有时间不变性,就称之为弱平稳。我们一般所说的平稳序列,指的就是弱平稳。
弱平稳时间序列还有一个重要的性质,两个观测之间的协方差(时间序列的术语称为自协方差)和相关系数(自相关系数)仅和两个观测之间的时间间隔(滞后,lag)有关,因此也具有时间不变性。
平稳性的好处是能够用尽可能少的参数来对时间序列进行建模。比如说,每个
许多时间序列本身并不是平稳的,通常可以通过一些变换使它变得平稳,比如,对数变换有助于稳定时间序列的方差,差分法可以通过消除时间序列取值水平的变化来帮助稳定时间序列的平均值,从而消除(或减少)趋势和季节性。对一个时间序列,又该如何判断它是否平稳呢?可以通过对时间序列图形进行观察,平稳的时间序列会显示出在某个固定水平振荡(这种现象称为均值回复),但直接的观察显然并不不可靠,需要一些进一步的辅助手段,比如本文后面的ACF图。当然,更严格的判断还是要通过假设检验。差分法和平稳性检验会在之后的文章会讲到。
序列值
ACF在线性时间序列分析中的作用非常重要,一个线性时间序列模型可以完全由其ACF进行刻画,并且在建模过程中由ACF来决定数据的线性动态关系。自相关函数往往以图形的方式进行展示,我们可以通过自相关图(ACF图)判断序列的特点。R中有多个计算自相关的函数,在feasts包中,使用ACF()计算自相关,autoplot()可用来绘制自相关图:
###将序列从tibble对象转换为tsibble对象
szzs_tsbl<-szzs_tbl%>%
mutate(index=1:nrow(szzs_tbl))%>%
as_tsibble(index=index)
p1<-szzs_tsbl%>%
ACF(close,lag_max=100)%>%
autoplot()+theme_bw()
ggtitle("price:acf")
p2<-szzs_tsbl%>%
ACF(logreturn,lag_max=100)%>%
autoplot()+ theme_bw()+
ggtitle("logreturn:acf")
plot_grid(p1,p2,nrow=2,align="v",rel_heights=c(1,1))
在自相关图中,会绘制两条检查边界(图-2中的蓝色虚线),取值等于2个标准误,即
自相关图有助于识别非平稳的时间序列。对于一个平稳的时间序列,ACF会相对迅速地降到零,而非平稳序列的ACF下降缓慢。
R中有多个函数用来绘制自相关图,这些自相关图都有一个特点,功能性大于美观性。在这里,我们给出一个自定义的自相关图函数,用它来绘制一个“python风格”的自相关图:
gg_acf<-function(ACF,col,T){
ACF%>%
ggplot(aes(x=lag,y=acf))+
geom_ribbon(aes(ymin=-2/sqrt(T),ymax=2/sqrt(T)),
fill=col,alpha=0.4)+
geom_segment(aes(x=lag,xend=lag,y=0,yend=acf),color=col)+
geom_point(shape=21,color=col,fill=col)+
theme_bw()
}
####上证指数日对数收益率的ACF图
szzs_tsbl %>%
ACF(logreturn,lag_max=100)%>%
gg_acf("red",nrow(szzs_tsbl))
得到的图-3实际上是一种“棒棒糖”图。这个函数用 geom_point()绘制自相关系数的取值,用geom_segment()绘制自相关取值到x轴的连线,用geom_ribbon()将两条检查边界之间的区域着色。这个函数接受ACF()的计算结果,需要读者指定颜色并输入序列长度T。
ACF图上的检查边界实际上就给出了一种关于单个自相关系数是否为0的检验,其中的原假设是单个自相关系数为0,当自相关系数超过边界时,就拒绝原假设。这个检验的检验水平是0.05,因此可以预期在原假设为真时,20个自相关系数中大约会有1个超过检验边界。
在应用中更为常见的情况是,联合检验多个自相关系数是否同时为0。其原假设是
ljung_box(szzs_tsbl$logreturn,lag=10)
# lb_stat lb_pvalue
#3.683976e+01 6.032136e-05
ljung_box(szzs_tsbl$close,lag=10)
# lb_stat lb_pvalue
# 23384.03 0.00
检验的结果包括检验统计量值和对应的p值。我们看到这两个序列检验的p值都小于0.05,因此这两个序列都存在着显著的滞后相关。
对ACF进行假设检验,等价于序列观测独立性/相关性的检验。
当序列有趋势时,较小滞后阶数的自相关往往是较大的且为正,因为时间接近的观测值在大小上也是接近的。因此,趋势时间序列的ACF趋于正值,随着滞后时间的增加,ACF逐渐减小。
当序列有季节性时,季节性滞后(季节性频率的倍数)的自相关将大于其他滞后。当序列同时具有趋势和季节性时,会看到这两种效应的组合。USgas是美国天然气月度消费数据,图-4上方的图形展示了这个时间序列,冬季是消费高峰,夏季是消费低谷:
library(TSstudio)
USgas_tsbl<-as_tsibble(USgas)
p1<-USgas_tsbl%>%autoplot()+ggtitle("usgas")
p2<-USgas_tsbl%>%
ACF(value,lag_max=100)%>%
gg_acf("steelblue",nrow(USgas_tsbl))+
ggtitle("usgas/acf")
plot_grid(p1,p2,nrow=2,align="v",rel_heights=c(1,1))
图-4下方是序列的ACF图,ACF随滞后增加而缓慢下降是由于趋势,而略带“扇形”的形状则是由于季节性的影响。
如果一个时间序列${y_t}$是一个独立同分布(i.i.d.)的随机变量序列,并且具有有限的均值和方差,这个序列就叫做白噪声。白噪声是最简单的平稳过程之一。特别地,如果
set.seed(1234)
wn <- tsibble(sample = 1:100, value = rnorm(100), index = sample)
p1 <- wn %>% autoplot(value)+ggtitle("wn")+theme_bw()
p2 <- wn%>%ACF(value,lag_max=75)%>%
gg_acf("steelblue",nrow(wn))+ggtitle("wn-acf")+theme_bw()
plot_grid(p1,p2,nrow=2,align="v",rel_heights=c(1,1))
从独立同分布的性质可知,白噪声的自相关函数恒等于0。在实际的观察中,白噪声的各个自相关系数应该接近于0。从图-5可见,我们选取了75阶滞后,只有1个自相关值超过了检查边界,说明这确实是一个白噪声。或者,由定义可知白噪声是一个独立序列,也可以使用Ljung-Box检验来判定序列是否为白噪声:
ljung_box(wn$value,lag=10)
lb_stat lb_pvalue
16.47583218 0.08679738
可见,对于10阶滞后的p值大于0.05,不能拒绝该序列没有显著相关性的原假设,可认为该序列是一个白噪声。
由于没有相关性,白噪声序列中不包含任何可以用来预测未来值的信息。
在时间序列分析中,经常会见到滞后这个术语,它指的是两个观测之间的时间间隔。在自相关系数显著不为零时,滞后值
p1<-USgas_tsbl%>%autoplot()+ggtitle("usgas")
p2<-USgas_tsbl%>%
gg_lag(value,geom='point',lag=1:12)+
ggtitle("usgas/lag")
plot_grid(p1,p2,nrow=2,align="v",rel_heights=c(1,3))
图-6下方的图形就是滞后图,以散点图的形式展示了每个当前值及其k阶滞后值之间的关系(这里,共展示了12阶滞后),每个数据点根据其周期(这里是月)给予不同的颜色。我们看到相同季节的滞后(如k=1,2,11,12)表现出了很强的正相关,不同的季节(特别是k=6,对应6个月的滞后)表示了明显的负相关。