Archive

Tag Archives: Financial Sector

In this post, the standard event study methodology will be applied to measure the effect of 2 rounds of quantitative easing on the cumulative abnormal returns (CAR) for individual financial firms listed on the SP 500 as well as the cumulative average abnormal returns (CAAR) across all firms in the financial sector. Stock data will be downloaded for the period : 2005-11-25 :: 2011-12-31

The standard methodology can be summarised as follows :

  1. Define the event and establish the estimation / event windows. For the purposes of this post, the event(s) we are interested in are the different stages associated with the 2 rounds of quantitative easing. For more information on each stage of each round of QE click here.  Estimation window : 3 years of daily data up to the date of the events Event window: 30 days after the event occurence.

  2. Establish firm selection criteria. The firms we are interested in are all the 82 financial firms listed on the SP500 . Tabulated Information on the composition of the SP500 can be downloaded from the following Wikipedia entry, where firms listed on the index can be sorted according to the desired industry sector ( financial in our case) before being copied to Excel, saved as a CSV file and imported into R.
  3. Calculate normal and abnormal returns for securities in the sample set.Once we have determined the event dates and the associated subset of the SP 500 index, the next step would be to estimate the normal return for each stock in the period after each event. This is then compared to the actual return observed for the corresponding stock for the same period to gauge abnormal returns. Specifically, return data in the estimation window will be fed into a single index model (CAPM) to elicit coefficient estimates. These estimates will then be applied to data in the event window to determine the normal or expected returns. The abnormal return for each stock in the event window is simply the difference between the actual returns in the period and the estimated returns : εi,t = Ri,t – βi(Rm,t-rf,t).

Click here for more information

l

setwd("C:/University of Warwick/R experiments/Event Study")

library(quantmod)
library(timeSeries)
library(RColorBrewer)
library(plotrix)
library(rpanel)

#Download Data & initialise
beg=as.Date('2005-11-25')
end=as.Date('2011-12-31')

getSymbols('^GSPC',from=beg,to=end)
SP500.daily.prices<-GSPC[,4]
SP500.monthly.prices<-to.monthly(SP500.daily.prices)[,4]
SP500.daily.returns<-Delt(SP500.daily.prices,type='arithmetic')[-1,]*100
SP500.monthly.returns<-Delt(SP500.monthly.prices,type='arithmetic')[-1,]*100

events<-c('The Federal Reserve Board \n announces a new program to \n purchase direct obligations \n of housing related \n government-sponsored \n enterprise',' The Committee is evaluating \n the potential benefits of \n purchasing longer-term \n Treasury securities.','The Federal Reserve continues \n to purchase large quantities \n of agency debt and MBS','U.S. Congress approves \n Obamas Stimulus Package.','The stock market bottoms.','The FOMC decides to purchase \n up to $300 billion of \n longer-term Treasury securities \n over the next six months to \n help improve conditions','The Committee will continue \n to monitor the economic outlook \n and financial developments and \n will employ its policy tools \n as necessary to promote \n economic recovery and price stability.','QE1 ends.','The Committee will continue to \n roll over the Federal Reserves \n holdings of Treasury securities \n as they mature.','Ben Bernanke states that the \n committee is prepared to \n provide additional monetary \n accommodation through \n unconventional measures if it \n proves necessary','The FOMC announces its \n decision to expand its \n holdings of securities in \n order to promote \n a stronger pace of economic \n recovery','The Committee will complete \n its purchases of $600 billion \n of longer-term Treasury securities \n by the end of this month and will \n maintain its existing policy of \n reinvesting principal payments.','QE2 ends, with no immediate \n plans for a third round of \n quantitative easing.')
ind<-LETTERS[1:length(events)]
events.ind<-cbind(ind,events)
rownames(events.ind)<-c('2008-11-25','2008-12-16','2009-01-28','2009-02-13','2009-03-9','2009-03-18','2010-03-16','2010-03-31','2010-08-10','2010-08-27','2010-11-03','2011-06-22','2011-06-30')
rownames(SP500.daily.returns)<-'SP500'

event.idx<-NULL
event.y<-NULL
for(i in 1:nrow(events.ind)){
  event.idx[i]<-which(index(SP500.daily.prices)==as.Date(rownames(events.ind)[i]))
  event.y[i]<-SP500.daily.prices[event.idx[i]]
}

ff.data<-read.zoo("vv.csv",header=T,sep=',')
rf<-as.xts(window(ff.data,start=beg,end=end)[-1,4])

#Financial firms data and estimation window

fin.list<-as.matrix(read.table('finexcel.csv',header=F,sep=''))

n<-length(fin.list)
b<-as.Date('2005-11-25')
e<-end

assets<-NULL
for(i in 1:n){
  getSymbols(fin.list[i],from=b,end=e)
  print(paste('Downloading data for :',fin.list[i]))
  assets$returns[[i]]<-as.timeSeries(dailyReturn(get(fin.list[i])[,4],type='arithmetic')*100)
}

matrix.returns<-NULL
for(i in 1:n){
  matrix.returns<-cbind(matrix.returns,assets$returns[[i]])
}
mat<-matrix.returns[-1,]
colnames(mat)<-fin.list
events.window<-matrix(c(event.idx-(3*252)+1,event.idx),nrow=nrow(events.ind),ncol=2,dimnames=list(ind,c('Beg.est','End.est')))
events.window.pred<-matrix(c(event.idx+1,event.idx+31),nrow=nrow(events.ind),ncol=2,dimnames=list(ind,c('Beg.pred','End.pred')))

est<-NULL
prem<-SP500.daily.returns-rf
colnames(prem)<-'Prem'

for(i in 1:nrow(events.ind)){
  est$pred[[i]]<-list()
  for(j in 1:n){
    est$pred[[i]]$fit[[j]]<-lm(mat[events.window[i,1]:events.window[i,2],j]~prem[events.window[i,1]:events.window[i,2]])
    est$pred[[i]]$alphas[[j]]<-as.matrix(coef(est$pred[[i]]$fit[[j]])[1])
    est$pred[[i]]$betas[[j]]<-as.matrix(coef(est$pred[[i]]$fit[[j]])[2])

    est$pred[[i]]$estnorm[[j]]<-est$pred[[i]]$betas[[j]]*prem[(events.window[i,2]-30):events.window[i,2]]
    est$pred[[i]]$estabnorm[[j]]<-mat[(events.window[i,2]-30):(events.window[i,2]),j]-est$pred[[i]]$estnorm[[j]]
    est$pred[[i]]$estcumu[[j]]<-cumsum(est$pred[[i]]$estabnorm[[j]])

    est$pred[[i]]$norm[[j]]<-est$pred[[i]]$betas[[j]]*prem[events.window.pred[i,1]:events.window.pred[i,2]]
    est$pred[[i]]$abnorm[[j]]<-mat[events.window.pred[i,1]:events.window.pred[i,2],j]-est$pred[[i]]$norm[[j]]
    est$pred[[i]]$cumu[[j]]<-cumsum(est$pred[[i]]$abnorm[[j]])

   est$pred[[i]]$comb[[j]]<-rbind(est$pred[[i]]$estcumu[[j]],est$pred[[i]]$cumu[[j]])
  }

}

#Average residuals across firms
avg<-NULL

for(i in 1:nrow(events.ind)){
  avg[[i]]<-as.matrix(est$pred[[i]]$abnorm[[1]])
  for(j in 2:n){
    avg[[i]]<-cbind(avg[[i]],as.matrix(est$pred[[i]]$abnorm[[j]]))
}
}

tot<-NULL
for(i in 1:nrow(events.ind)){
  tot[[i]]<-as.matrix(rowMeans(avg[[i]]))
}

tot.cumu<-NULL
for(i in 1:nrow(events.ind)){
  tot.cumu[[i]]<-as.matrix(cumsum(tot[[i]]))
}

#Visualise SP500 and events

p<-as.matrix(SP500.daily.prices)
pl<-as.matrix(p[index(p)[rownames(p)==as.Date('2008-10-27')]:last(index(p))])
rownames(pl)<-rownames(p)[index(p)[rownames(p)==as.Date('2008-10-27')]:last(index(p))]
pl.event.idx<-NULL
pl.event.y<-NULL
for(i in 1:nrow(events.ind)){
  pl.event.idx[i]<-which((rownames(pl))==as.Date(rownames(events.ind)[i]))
  pl.event.y[i]<-pl[pl.event.idx[i]]
}
Qe1.ind.l<-which(rownames(pl)==as.Date('2008-11-25'))
Qe1.ind.r<-which(rownames(pl)==as.Date('2010-03-31'))

temp.l<-which(rownames(pl)==as.Date('2010-08-10'))
temp.r<-which(rownames(pl)==as.Date('2010-11-03'))

Qe2.ind.l<-which(rownames(pl)==as.Date('2010-11-03'))
Qe2.ind.r<-which(rownames(pl)==as.Date('2011-06-30'))

box.col<-as.matrix(topo.colors(Qe1.ind.r-Qe1.ind.l,alpha=0.30))

windows(width=14,height=12)
layout(matrix(c(1,1,2,3,4,5),nrow=3,ncol=2,byrow=T))
par(mai=c(0.5,1,0.1,0.1))

if (interactive()) {
  draw <- function(panel) {
    par(mai=c(0.5,0.5,0.1,0.1))

    plot(type='l',ylim=c(min(SP500.daily.prices)-50,max(SP500.daily.prices)),col='blue',lwd=1.35,pl,las=2,ylab='SP 500 closing values',cex.axis=0.75,cex.lab=0.95,bty='o',xlab='',xaxt='n')
    mtext(padj=1,cex=0.75,side=1,paste('EVENT :','[',panel$event,']',':::','ASSET :','[',fin.list[panel$asset],']'),font=2)
    grid('lightgrey',nx=32,ny=9,lty=1,lwd=0.5)
    rect(xleft=Qe1.ind.l,ybottom=min(SP500.daily.prices)-100,xright=Qe1.ind.r,ytop=max(SP500.daily.prices)+100,col=box.col[42],border=NA)
    rect(xleft=Qe2.ind.l,ybottom=min(SP500.daily.prices)-100,xright=Qe2.ind.r,ytop=max(SP500.daily.prices)+100,col=box.col[42],border=NA)
    rect(xleft=temp.l,ybottom=min(SP500.daily.prices)-100,xright=temp.r,ytop=max(SP500.daily.prices)+100,col=box.col[65],border=NA)
    text(x=pl.event.idx+5,y=ifelse(pl.event.y==min(pl.event.y),pl.event.y-55,pl.event.y-95),events.ind[,1],cex=0.95,font=1,col='black')
    text(x=(Qe1.ind.r-Qe1.ind.l)-150,y=max(SP500.daily.prices)-50,'Quantitative Easing \n Round 1',col='black',cex=1.1)
    text(x=Qe2.ind.r-85,y=min(SP500.daily.prices)+50,'Quantitative Easing \n Round 2',col='black',cex=1.1)

    for(i in 1:nrow(events.ind)){
      abline(v=pl.event.idx[i],col=ifelse(pl.event.idx[i]==pl.event.idx[panel$event],'red','darkgreen'),lwd=1.2)
      points(pl.event.idx[i],pl[pl.event.idx[i]],col=ifelse(pl.event.idx[i]==pl.event.idx[panel$event],'red','darkgreen'),cex=1.2,pch=16)
      rect(xleft=pl.event.idx[nrow(events.ind)]+3,ybottom=1000,xright=850,ytop=1060,col='orange',border=NA)
      text(x=pl.event.idx[nrow(events.ind)]+3+(840-pl.event.idx[nrow(events.ind)]+2)/2,y=1030,paste('EVENT :',events.ind[panel$event,1],' [',rownames(events.ind)[events.ind[,1]==events.ind[index(pl.event.idx)[panel$event]]],']'),cex=0.75,font=1)
      rect(xleft=pl.event.idx[nrow(events.ind)]+3,ybottom=600,xright=850,ytop=995,col='white',border=NA)
      text(x=pl.event.idx[nrow(events.ind)]+85,y=815,col='black',cex=0.75,font=1,events.ind[,2][rownames(events.ind)[events.ind[,1]==events.ind[index(pl.event.idx)[panel$event]]]])

    }

    stackpoly(border='black',xaxt='n',axis4=F,xaxlab=NA,col='blue',as.matrix(mat[(event.idx[panel$event]-30):events.window.pred[panel$event,2],panel$asset]),ylab='Estimation/Event Windows',xlab='')
    abline(v=30,lwd=2,col='darkorange')
    mtext(side=3,'Estimation Window Event Window',col='black',cex=0.85)

    plot(type='l',col='black',lwd=1.35,(mat[events.window.pred[panel$event,1]:events.window.pred[panel$event,2],panel$asset]),las=2,ylab=' Actual/Normal Returns',cex.axis=0.75,cex.lab=0.95,bty='o',xlab='',xaxt='n')
    lines(type='l',col='red',lwd=1.35,(est$pred[[panel$event]]$norm[[panel$asset]]),las=2,ylab='',cex.axis=0.75,cex.lab=0.95,bty='c',xlab='',xaxt='n')
    legend("topleft",fill=c('black','red'),legend=c('Actual Returns','Normal Returns'),ncol=1,bty='n',border='white')

    cg<-as.matrix(est$pred[[panel$event]]$comb[[panel$asset]])
    tg<-tot.cumu[[panel$event]]

    stackpoly(border='black',xaxt='n',axis4=F,col='red',cg,ylab=paste('CAR for ',fin.list[panel$asset]),xlab='',cex.axis=0.75,cex.lab=0.95)
    rect(xleft=0,ybottom=-100,xright=30,ytop=100,col=box.col[42],border=NA)

    stackpoly(border='black',xaxt='n',axis4=F,col='dark orange',tg,ylab='CAAR for financials',xlab='',cex.axis=0.75,cex.lab=0.95)
    panel
}
  panel<- rp.control(event = 1,asset=1)
  rp.slider(panel,event,1,length(pl.event.idx), action=draw,resolution=1,showvalue=TRUE)
  rp.slider(panel,asset,1,n,action=draw,resolution=1,showvalue=TRUE)
}

lThe rpanel package allows us to select the event and security of interest individually.

Suppose we are interested in the effect of Event C, which corresponds to ‘ The Fed contintuing to purchase large quantities of agency debt and MBS ‘ around 2009-01-28, on Aon plc. We would push the ‘event slider’ to 3 and the ‘asset slider’ to 24 to yield the following plot window :

Click here for : High quality Image

The first plot charts the SP 500 closing values along with the time periods corresponding to the 2 rounds of quantitative easing ( blue shaded areas). The little box in the bottom right corner of the plot is a quick summary of the selected event and its date of occurrence.  The vertical green lines and the labels [A:M] reflect individual events that took place in each round of QE. The vertical red lines indicate which of these events is currently selected.

The blue area plot in the second row of the plot window is a snapshot of the estimation and event windows. We are using 3 years of data up to the date associated with Event C for estimation purposes. The event window itself stretches from event date to 30 days after the event. Visually, the estimation and event windows are separated using an orange line. While we are using 3 years worth of data for estimation purposes, we are only displaying the stock returns 30 days before and after the event.

The line plot in the second row charts both the estimated normal return and the actually observed return in the event window. The 3 years of data in the estimation window has been fed into a single index model to elicit coefficient estimates. These estimates were then applied to data in the event window to calculate normal/expected returns according to the CAPM. The difference between the actual and normal returns (black and red lines respectively) represent abnormal returns for the security.

The red area plot in the last row charts the cumulative abnormal returns (CAR) for Aon plc both 30 days before and 30 days after the selected event. It appears that about a week after the Fed’s continuing purchase of debt ( pumping liquidity into the economy), Aon plc has experienced a surge in abnormal returns.

The final orange area plot represents the cumulative average abnormal return (CAAR) acoss all the 82 financial firms listed on the SP 500 for the period from the event date to 30 days after the event date.

Advertisements