library(Quandl)
Quandl.api_key("KmxULt3z1Vz1neVxGioB")

library("vars")
library("urca")
library("gdata")
library("stargazer")
library("KFAS")

(a) Construct the time series for monthly returns

First, we load data.

SP500 <- Quandl("YAHOO/INDEX_GSPC/CLOSE", collapse = "monthly", type = 'zoo')
IBM <- Quandl("GOOG/NYSE_IBM/CLOSE", collapse = "monthly", type = 'zoo')
Tbill3m <- Quandl("FRED/TB3MS", type = 'zoo')
rsp500 <- 100*diff(log(SP500), differences = 1)
rIBM <- 100*diff(log(IBM), differences = 1)
rTbill3m <- Tbill3m / 12
par(mfrow=c(3,2))
plot(log(SP500), main=expression("logged SP500"))
plot(rsp500, main=expression("100*differentiated logged SP500"))
plot(IBM, main=expression("logged IBM"))
plot(rIBM, main=expression("100*differentiated logged IBM"))
plot(Tbill3m, main=expression("Tbill 3month"))
plot(rTbill3m, main=expression("100*differentiated logged Tbill 3month"))

summary(rsp500)
##      Index          rsp500        
##  Min.   :1950   Min.   :-24.5428  
##  1st Qu.:1967   1st Qu.: -1.7583  
##  Median :1984   Median :  0.9057  
##  Mean   :1984   Mean   :  0.6118  
##  3rd Qu.:2001   3rd Qu.:  3.4312  
##  Max.   :2017   Max.   : 15.1043
summary(rIBM)
##      Index           rIBM         
##  Min.   :1981   Min.   :-30.3834  
##  1st Qu.:1990   1st Qu.: -3.7874  
##  Median :1999   Median :  0.4004  
##  Mean   :1999   Mean   :  0.5231  
##  3rd Qu.:2008   3rd Qu.:  4.8545  
##  Max.   :2017   Max.   : 30.2914
summary(rTbill3m)
##      Index         rTbill3m        
##  Min.   :1934   Min.   :0.0008333  
##  1st Qu.:1955   1st Qu.:0.0316667  
##  Median :1976   Median :0.2533333  
##  Mean   :1976   Mean   :0.2931917  
##  3rd Qu.:1996   3rd Qu.:0.4460417  
##  Max.   :2017   Max.   :1.3583333
rsp5002 <- window(rsp500, start = 1981 + 3/12, end = 2017 + 3/12)
rIBM2 <- window(rIBM, start = 1981 + 3/12, end = 2017 + 3/12)
rTbill3m2 <- window(rTbill3m, start = 1981 + 3/12, end = 2017 + 3/12)

(b) Estimate a simple OLS relating excess returns for IBM and excess returns for S&P 500

excessIBM <- rIBM2 - rTbill3m2
excessSP500 <- rsp5002 - rTbill3m2

sOLS <- lm(excessIBM  ~ excessSP500)
plot(excessIBM, excessSP500, main="A simple OLS relating excess returns for IBM S&P500")
abline(lm(excessSP500~excessIBM))

summary(sOLS)
## 
## Call:
## lm(formula = excessIBM ~ excessSP500)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -31.2343  -3.1235  -0.1644   3.4677  24.5022 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -0.09957    0.29559  -0.337    0.736    
## excessSP500  0.92509    0.06804  13.597   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.134 on 431 degrees of freedom
## Multiple R-squared:  0.3002, Adjusted R-squared:  0.2986 
## F-statistic: 184.9 on 1 and 431 DF,  p-value: < 2.2e-16

According to the results, \(\alpha\) (intercept) is -0.09957 and \(\beta\) is 0.92509.

(c) Estimate a CAPM model with time-varying coefficients with time varying coefficient alpha and beta using Kalman filter. Create a plot showing how the smoothed states alpha and beta changed over time.

excesssp500ts <- as.ts(excessSP500)
excessIBMts <- as.ts(excessIBM)

T <- length(excesssp500ts)

# construct system matrices for state-space model 
Zt <- array(rbind(rep(1,T), excesssp500ts), dim=c(1,2,T))
Ht <- matrix(NA)
Tt <- diag(2)
Rt <- diag(2)
Qt <- matrix(c(NA,0,0,NA), 2,2)

# use diffuse prior
a1 <- matrix(c(0, 1), 2, 1)
P1 <- matrix(0, 2, 2)
P1inf <- diag(2)

# define state-space CAPM model
y.SS <- SSModel(excessIBMts ~ -1 + SSMcustom(Z=Zt, T=Tt, R=Rt, Q=Qt, a1=a1, P1=P1, P1inf=P1inf), H=Ht)

# estimate variances of innovations using maximum likelihood
y.SS.ML <- fitSSM(y.SS, inits = c(0.001,0.001,0.001), method="BFGS")

# Kalman filtering and smoothing, with parameters in Q and H set to maximum likelihood estimates
y.SS.KFS <- KFS(y.SS.ML$model)

Then, we get coefficients.

alpha.KFS <- ts( cbind(y.SS.KFS$a[,1], y.SS.KFS$alphahat[,1]), start=c(1981,4), frequency=12)
beta.KFS <- ts( cbind(y.SS.KFS$a[,2], y.SS.KFS$alphahat[,2]), start=c(1981,4), frequency=12)
par(mfrow=c(2,1), mar=c(4,4,2,1))
# plot filtered and smoothed state alpha and betta
plot.ts(alpha.KFS, plot.type="single", xlab="",ylab="Alpha", col=c("blue","red"), lwd=2)
legend("topright", c("filtered","smoothed"), col=c("blue","red"), lwd=2, cex=0.7, bty="n")
plot.ts(beta.KFS, plot.type="single", xlab="",ylab="Beta", col=c("blue","red"), lwd=2)
legend("topright", c("filtered","smoothed"), col=c("blue","red"), lwd=2, cex=0.7, bty="n")

par(mfrow=c(2,1), mar=c(4,4,2,1))
# plot smoothed state alpha and betta
plot.ts(alpha.KFS[,2], plot.type="single", xlab="",ylab="Alpha", col="red", lwd=2)
legend("topright", "smoothed", col="red", lwd=2, cex=0.7, bty="n")
plot.ts(beta.KFS[,2], plot.type="single", xlab="",ylab="Beta", col="red", lwd=2)
legend("topright", "smoothed", col="red", lwd=2, cex=0.7, bty="n")

(d) Compare alpha and beta from (b) and (c)

#A simple OLS alpha, beta
mean(sOLS$coefficients[1])
## [1] -0.09956639
mean(sOLS$coefficients[2])
## [1] 0.9250887
#Kalman filtered alpha, beta
mean(y.SS.KFS$a[, 1])
## [1] -0.06942577
mean(y.SS.KFS$a[, 2])
## [1] 0.9198105
#Kalman filtered smoothed alpha, beta
mean(y.SS.KFS$alphahat[, 1])
## [1] -0.07471126
mean(y.SS.KFS$alphahat[, 2])
## [1] 0.9228255