Skip to content

Instantly share code, notes, and snippets.

@JoesDataDiner
Last active December 14, 2015 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoesDataDiner/5138210 to your computer and use it in GitHub Desktop.
Save JoesDataDiner/5138210 to your computer and use it in GitHub Desktop.
The Financial Crisis on Tape Part II
rm(list=ls())
#install the superb quantmod library
#we will use it to download the data and compute returns
library(quantmod)
#install various other libraries for the data manipulation and graphing.
library(ggplot2)
library(scales)
library(RColorBrewer)
library(reshape2)
library(grid)
library(gridExtra)
# load historical prices from Yahoo Finance
# I use a set that I saw used by Systematic Investor
symbols = c('SPY','QQQ','EEM','IWM','EFA','TLT','IYR','GLD')
symbols.names = c('S&P 500,Nasdaq 100,Emerging Markets,Russell 2000,EAFE,20 Year
Treasury,U.S. Real Estate,Gold')
#Download the data from yahoo (default choice of getSymbols)
#It loads directly to the environment which depending on your R background may seem surprising
#One can use the 'get' function below to obtain the results.
getSymbols(symbols, src = 'yahoo', from = '2005-01-01')
#obtain the daily closing price for each and form into a data frame
#and compute the returns of the adjusted prices
hist.returns =
do.call(cbind,
lapply(symbols, function(symbol){
symbol.data = get(symbol) #get yahoo data from the environment
symbol.data.adj = Ad(symbol.data) #extract the adjusted prices
symbols.data.adjret = ROC(symbol.data.adj, n=1, type="continuous", na.pad=TRUE) #compute the simple returns
symbols.data.adjret
})
)
#we will also need to get the plain adjusted prices which we will use later
hist.prices =
do.call(cbind,
lapply(symbols, function(symbol){
symbol.data = get(symbol) #get yahoo data from the environment
symbol.data.adj = Ad(symbol.data) #extract the adjusted price
symbol.data.adj
})
)
#a little prep for plotting with ggplot later
hist.prices = data.frame(this.date = index(hist.prices),hist.prices)
colnames(hist.prices) = gsub(".Adjusted","",colnames(hist.prices))
hist.prices.melt = melt(hist.prices,id.vars="this.date")
#define preferred order of the assets in the graphs.
pref.order = c("SPY","QQQ","EEM","IWM","EFA","IYR","GLD","TLT")
hist.prices.melt$variable = factor(hist.prices.melt$variable,pref.order)
###########################################################
##############Compute Rolling Correlations#################
###########################################################
#there are many ways to apply a function to a rolling historical window
#I'm going to roll a very simple one of my own
#Function to compute the correlation matrix from an dataframe of returns:
DataFrameCorOutput<-function(hist.returns){
require(reshape2)
correls = melt(cor(as.matrix(na.omit(hist.returns)))) #r's built in correlation function returns the correlation matrix
colnames(correls) = c("Var1","Var2","Correl") #label the melted correlation matrix
#rename some of the series to make obtaining a pretty plot a little easier!
correls$Var1 = factor(gsub(".Adjusted","",correls$Var1),rev(pref.order))
correls$Var2 = factor(gsub(".Adjusted","",correls$Var2),rev(pref.order))
list(correls = correls,min.date = min(index(hist.returns)),max.date = max(index(hist.returns))) #return all three objects
}
#choose the window length over which we will compute the correlation
window.length = 120 #~6M of business days
#calculate the dates on which we have sufficient data to compute the correlation (i.e. a window.length of history)
dates.to.do = tail(index(hist.returns),-(window.length - 1)) #these are the dates to right of the first window
#calculate the correlation for an N day window before each of these dates
rolling.correls = lapply(dates.to.do,FUN<-function(this.date){
return(DataFrameCorOutput(tail(hist.returns[index(hist.returns)<=this.date,],window.length)))
})
names(rolling.correls) = dates.to.do
#function to extract the correlation matrix from rolling.correls
#and plot it using the ggplot package.
PlotCorrelsForThisDate<-function(this.date){
#extract the relevant correlmatrix from the list of correl matrices
correlmatrix = rolling.correls[[as.character(this.date)]][["correls"]]
#I want to use a bespoke colour pallete see Part I of "The Financial Crisis on Tape" for an explanation.
my.col.vec = c(
rev(brewer.pal(8,"Blues")),
colorRampPalette(
c(
colorRampPalette(c("white",brewer.pal(9,"Set3")[2],
brewer.pal(9,"Set1")[c(6,5,1)]))(10),
rev(brewer.pal(9,"PRGn")[1])
)
)(9)
)
#plot a simple heat-map using ggplot
correl.plot<-ggplot(correlmatrix, aes(x = Var1, y = Var2, fill = Correl)) +
geom_tile() +
scale_fill_gradientn(colours = my.col.vec
,limits = c(-1,1)) +
theme_bw()+
theme(panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.x=element_text(angle=90))
return(correl.plot)
}
#The below is a funtion that given an index, j, produces the graphic for the date dates.to.do[j]
ProduceFilmStill<-function(j){
#the main reason I use j rather than lapplying to a list of dates
#is I wish to call the output Plot_j.png, so I need to record j.
this.date = dates.to.do[j]
#use the previous function to produce the correlation heatmap
correlplot = PlotCorrelsForThisDate(this.date)
#the strip.data highlights the period of time used to compute the correlation
strip.data = data.frame(xmin=rolling.correls[[as.character(this.date)]][["min.date"]], xmax=this.date,ymin=-Inf,ymax=Inf)
#Plot the timeseries plots:
#the idea of these is that the dot shows the current point in time whilst the period used is shaded grey.
#this gives context to the the correlation calculation
timeseries.plot = ggplot(hist.prices.melt,aes(x=this.date,y=value,colour=variable))+
geom_line()+
geom_rect(data=strip.data,aes(xmin=xmin,xmax=xmax,ymin=ymin,ymax=ymax),fill="grey", alpha=0.2, inherit.aes = FALSE)+
geom_point(data = hist.prices.melt[hist.prices.melt$this.date == this.date,],size=3.5)+
theme_bw() +
scale_y_continuous("Price")+
scale_colour_brewer("",palette="Set1")+
facet_grid(variable~.,scales="free_y")+
theme(axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.margin = unit(c(0.53,0.2,0.75,0), "cm"))+
guides(colour=FALSE)
library(gtable)
#Combine the two ggplots using gtable into a single graphic.
#thanks to numerous stack-overflow posters
#for your help with learning about gtable!
gA <- ggplot_gtable(ggplot_build(timeseries.plot))
gB <- ggplot_gtable(ggplot_build(correlplot))
maxWidth = grid::unit.pmax(gA$widths[2:3], gB$widths[2:3])
gA$widths[2:3] <- as.list(maxWidth)
gB$widths[2:3] <- as.list(maxWidth)
gt <- gtable(widths = unit(c(0.8, 1), "null"), height = unit(1, "null"))
gt <- gtable_add_grob(gt, gA, 1, 1)
gt <- gtable_add_grob(gt, gB, 1, 2)
#save the graphic as png
#this will form a single frame in the video
base.graphpath = "~\\FilmStills_"
graphpath = paste(base.graphpath,j,".png",sep="")
png(graphpath,
width = 1500,
height = 750,
res = 150
)
grid.newpage()
grid.draw(gt)
dev.off()
return (graphpath)
}
#produce a graphic for each date in the date range
FilmStillPaths = lapply(1:length(dates.to.do),ProduceFilmStill)
#use the ffmpeg program to combine the pngs to make an mpeg.
#ffmpeg -y -r 50 -s 1500X750 -f image2 -i "FilmStills_%d.png" FinancialCrisisOnTape.mpg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment