We consider the monthly time series for the Consumer Price Index for all Urban Consumers: All Items Not Seasonally Adjusted the FRED Database.
First we load the “Quandl” packages as well as others.
library("Quandl")
library("tseries")
library("urca")
library("KFAS")
The symbol is FRED/CPIAUCNS. First lets find the month over month inflation rate, \(y_t= Delta log CPI_t\).
cpia<-Quandl("FRED/CPIAUCNS", type="timeSeries")
cpia<-window(cpia,start="1955-01-01", end="2013-12-01")
cpia.l<-log(cpia)
cpia.ld<-diff(cpia.l,1)
par(mfrow=c(1,2))
plot(cpia.ld,xlab="", ylab="",main=expression("Yearly Inflation Yt"))
plot(cpia.l,xlab="", ylab="",main=expression("Log CPI"))
T<-length(cpia.ld)
cpi.model<-SSModel(cpia.ld~ SSMtrend(degree=1,Q=NA)+SSMseasonal(period=12,sea.type="dummy",Q=NA),H=NA)
cpi.model$T
## , , 1
##
## level sea_dummy1 sea_dummy2 sea_dummy3 sea_dummy4 sea_dummy5
## level 1 0 0 0 0 0
## sea_dummy1 0 -1 -1 -1 -1 -1
## sea_dummy2 0 1 0 0 0 0
## sea_dummy3 0 0 1 0 0 0
## sea_dummy4 0 0 0 1 0 0
## sea_dummy5 0 0 0 0 1 0
## sea_dummy6 0 0 0 0 0 1
## sea_dummy7 0 0 0 0 0 0
## sea_dummy8 0 0 0 0 0 0
## sea_dummy9 0 0 0 0 0 0
## sea_dummy10 0 0 0 0 0 0
## sea_dummy11 0 0 0 0 0 0
## sea_dummy6 sea_dummy7 sea_dummy8 sea_dummy9 sea_dummy10
## level 0 0 0 0 0
## sea_dummy1 -1 -1 -1 -1 -1
## sea_dummy2 0 0 0 0 0
## sea_dummy3 0 0 0 0 0
## sea_dummy4 0 0 0 0 0
## sea_dummy5 0 0 0 0 0
## sea_dummy6 0 0 0 0 0
## sea_dummy7 1 0 0 0 0
## sea_dummy8 0 1 0 0 0
## sea_dummy9 0 0 1 0 0
## sea_dummy10 0 0 0 1 0
## sea_dummy11 0 0 0 0 1
## sea_dummy11
## level 0
## sea_dummy1 -1
## sea_dummy2 0
## sea_dummy3 0
## sea_dummy4 0
## sea_dummy5 0
## sea_dummy6 0
## sea_dummy7 0
## sea_dummy8 0
## sea_dummy9 0
## sea_dummy10 0
## sea_dummy11 0
cpi.model$R
## , , 1
##
## [,1] [,2]
## level 1 0
## sea_dummy1 0 1
## sea_dummy2 0 0
## sea_dummy3 0 0
## sea_dummy4 0 0
## sea_dummy5 0 0
## sea_dummy6 0 0
## sea_dummy7 0 0
## sea_dummy8 0 0
## sea_dummy9 0 0
## sea_dummy10 0 0
## sea_dummy11 0 0
cpi.model$Z
## , , 1
##
## level sea_dummy1 sea_dummy2 sea_dummy3 sea_dummy4 sea_dummy5
## [1,] 1 1 0 0 0 0
## sea_dummy6 sea_dummy7 sea_dummy8 sea_dummy9 sea_dummy10 sea_dummy11
## [1,] 0 0 0 0 0 0
cpi.model$Q
## , , 1
##
## [,1] [,2]
## [1,] NA 0
## [2,] 0 NA
cpi.model$H
## , , 1
##
## [,1]
## [1,] NA
Now that we defined the local level model with a seasonal component and checked the system matrices, now we define update function for maximum likelihood estimation, and estimate the model parameters using maximum likelihood.
cpi.updatefn<-function(pars, model) {
model$Q[,,1] <- diag(exp(pars[1:2]))
model$H[,,1] <- exp(pars[3])
model}
pars<-log(c(.1,.01,.001))
cpi.fit<-fitSSM(cpi.model,inits=pars,updatefn=cpi.updatefn,method="BFGS")
cpi.fit$optim.out$par
## [1] -249.95806 -100.75446 -11.37012
cpi.fit$model$Q
## , , 1
##
## [,1] [,2]
## [1,] 2.783526e-109 0.000000e+00
## [2,] 0.000000e+00 1.749413e-44
cpi.fit$model$H
## , , 1
##
## [,1]
## [1,] 1.153504e-05
# Kalman filtering and smoothing
cpi.out <- KFS(cpi.fit$model, smoothing=c("state","disturbance"))
colnames(cpi.out$alphahat)
## [1] "level" "sea_dummy1" "sea_dummy2" "sea_dummy3" "sea_dummy4"
## [6] "sea_dummy5" "sea_dummy6" "sea_dummy7" "sea_dummy8" "sea_dummy9"
## [11] "sea_dummy10" "sea_dummy11"
# construct smoothed time series - add smmothed level and smoothed seasonal components
cpi.KF <- cpi.out$a %*% as.vector(cpi.out$model$Z)
cpi.KS <- cpi.out$alphahat %*% as.vector(cpi.out$model$Z)
# find position of level and first seasonal dummy
ilvl <- which(colnames(cpi.out$a)=="level")
isea <- which(colnames(cpi.out$a)=="sea_dummy1")
# construct 90% confidence intervals for filtered state
cpi.KF.CI.lvl <- as.vector(cpi.out$a[-(T+1),ilvl]) + qnorm(0.95)* sqrt(cbind(cpi.out$P[ilvl,ilvl,-(T+1)])) %*% cbind(-1,1)
cpi.KF.CI.sea <- as.vector(cpi.out$a[-(T+1),isea]) + qnorm(0.95)* sqrt(cbind(cpi.out$P[isea,isea,-(T+1)])) %*% cbind(-1,1)
# construct 90% confidence intervals for smoothed state
cpi.KS.CI.lvl <- as.vector(cpi.out$alphahat[,ilvl]) + qnorm(0.95)* sqrt(cbind(cpi.out$V[ilvl,ilvl,])) %*% cbind(-1,1)
cpi.KS.CI.sea <- as.vector(cpi.out$alphahat[,isea]) + qnorm(0.95)* sqrt(cbind(cpi.out$V[isea,isea,])) %*% cbind(-1,1)
Now plot the series
# actual, filtered and seasonal component
par(mfrow=c(2,1))
plot.ts( cbind(cpia.ld, cpi.out$a[-(T+1),ilvl], cpi.KF.CI.lvl), col=c("black","blue","blue","blue"), lty=c(1,1,3,3), plot.type="single", xlab="", ylab="", main="actual and filtered values" )
plot.ts( cbind(cpi.out$a[-(T+1),isea], cpi.KS.CI.sea), col="blue", lty=c(1,3,3), plot.type="single", xlab="", ylab="", main="seasonal component" )
abline(h=0, lty=3)
# actual, smoothed and seasonal component
par(mfrow=c(2,1))
plot.ts( cbind(cpia.ld, cpi.out$alphahat[,ilvl], cpi.KS.CI.lvl), col=c("black","red","red","red"), lty=c(1,1,3,3), plot.type="single", xlab="", ylab="", main="actual and smoothed values" )
plot.ts( cbind(cpi.out$alphahat[,isea], cpi.KS.CI.sea), col="red", lty=c(1,3,3), plot.type="single", xlab="", ylab="", main="seasonal component" )
abline(h=0, lty=3)
# Irregular component actual, smoothed and seasonal component
par(mfrow=c(3,1))
plot.ts( exp( cbind(cpia.ld, cpi.out$alphahat[,ilvl], cpi.KS.CI.lvl) ), col=c("black","red","red","red"), lty=c(1,1,3,3), plot.type="single", xlab="", ylab="", main="actual and smoothed values" )
plot.ts( exp( cbind(cpi.out$alphahat[,isea], cpi.KS.CI.sea) ), col="red", lty=c(1,3,3), plot.type="single", xlab="", ylab="", main="seasonal component" )
abline(h=1, lty=3)
plot.ts( exp( cpi.out$epshat ), col="red", plot.type="single", xlab="", ylab="", main="irregular component" )
abline(h=1, lty=3)
# forecast horizon
h <- 36
cpi.fcst <- predict(cpi.out$model, interval="confidence", level=0.9, n.ahead=h, filtered=TRUE)
cpi.fcst <- predict(cpi.out$model, interval="confidence", level=0.9, n.ahead=h)
cpi.fcst <- ts(cpi.fcst, start=(index(cpia.ld)[length(cpia.ld)]+0.25), frequency=12)
# plot the forecast
lcolor <- c(1,2,2,2)
lwidth <- c(2,2,1,1)
ltypes <- c(1,1,2,2)
plot.ts( cbind(cpia.ld, cpi.fcst), plot.type="single", col=lcolor, lwd=lwidth, lty=ltypes, xlab="", ylab="", main="CPI Not Seasonally Adjusted Log Transformed")
legend("topleft", legend = c("actual data","forecast","90% confidence interval"),
col=lcolor, lwd=lwidth, lty=ltypes, bty="n", cex=0.5 )
plot.ts( exp( cbind(cpia.ld, cpi.fcst) ), plot.type="single", col=lcolor, lwd=lwidth, lty=ltypes, xlab="", ylab="", main="CPI Not Seasonally Adjusted")
legend("topleft", legend = c("actual data","forecast","90% confidence interval"),
col=lcolor, lwd=lwidth, lty=ltypes, bty="n", cex=0.5 )
Yes, it does seem as though the predicted values are within the range of the actual values.