Thursday, April 21, 2011

Great FAJ Article on Statistical Measure of Financial Turbulence

faj abstract

I particularly liked this well-written paper, since unlike most academic research, I was able to understand it, replicate it, and incorporate it.  I know that the Financial Analyst Journal is not considered by the academic community as a top-tier journal, but its insights have deepened my understanding and stimulated a lot of very beneficial thoughts.

As usual, I have struggled with how I could write this post with public data, but have not found an adequate public replacement for the CRB Index, so I will show how I used R to get similar results and build a basic system around it without including a file with the CRB monthly closes.  Everything else is publicly available, and I hope that even though the data is not included, the method and result will be very clear.

From TimelyPortfolio

When building the system around it, I was hesitant to do an optimization window with a walkforward as the article suggests, so with hindsight unfortunately, I picked a value (1) that works well.  In the next iteration, I achieve much better results with far less hindsight optimization bias by using correlation instead of covariance.  I’ll save that for my next post after a short weekend trip to the beach.

From TimelyPortfolio

R code:

require(quantmod)
require(PerformanceAnalytics)

#get data from St. Louis Federal Reserve (FRED)
getSymbols("GS20",src="FRED") #load 20yTreasury; 20y has gap 86-93; 30y has gap in early 2000s
getSymbols("GS30",src="FRED") #load 30yTreasury to fill 20y gap 86-93
#getSymbols("BAA",src="FRED") #load BAA
getSymbols("SP500",src="FRED") #load SP500

#get CRB data from a csv file
CRB<-as.xts(read.csv("crb.csv",row.names=1))[,1]

#fill 20y gap from discontinued 20y Treasuries with 30y
GS20["1987-01::1993-09"]<-GS30["1987-01::1993-09"]

#do a little manipulation to get the data lined up on monthly basis
SP500<-to.monthly(SP500)[,4]
#get monthly format to yyyy-mm-dd with the first day of the month
index(SP500)<-as.Date(index(SP500))
#my CRB data is end of month; could change but more fun to do in R
CRB<-to.monthly(CRB)[,4]
index(CRB)<-as.Date(index(CRB))

#let's merge all this into one xts object; CRB starts latest in 1956
assets<-na.omit(merge(GS20,SP500,CRB))
#use ROC for SP500 and CRB and momentum for yield data
assetROC<-na.omit(merge(momentum(assets[,1])/100,ROC(assets[,2:3],type="discrete")))
#get Covariances and multiply to by 100000 for 20y to sp500 and crb and 1000 for sp500 to crb to standardize
#don't like this manual intervention; next post will use correlation instead
assetCovar<-runCov(assetROC[,1],assetROC[,2],n=2)*100000+runCov(assetROC[,1],assetROC[,3],n=2)*100000+runCov(assetROC[,2],assetROC[,3],n=2)*1000
assetROCSum<-assetROC[,1]+assetROC[,2]+assetROC[,3]
turbulence<-abs(assetCovar*assetROCSum)
chartSeries(turbulence,theme="white",name="Covariance and % Change as Measure of Financial Turbulence")

#wish I could remember where I got some of this code
#most likely candidate is www.fosstrading.com
#please let me know if you know the source
#so I can give adequate credit

#use turbulence to determine in or out of equal-weighted sp500 and crb
signal<-ifelse(turbulence>1,0,1)
signal<-lag(signal,k=1)
# Replace missing signals with no position
# (generally just at beginning of series)
signal[is.na(signal)] <- 0

#get returns from equal-weighted crb and sp500 position; Return.portfolio was causing problems, so did the hard way
ret<-(assetROC[,2]+assetROC[,3])/2
ret[1] <- 0

#get system performance
system_perf<-ret*signal
system_eq<- cumprod(1+ret*signal)

perf_comparison<-merge(lag((assetROC[,2]+assetROC[,3])/2,k=1),system_perf)
colnames(perf_comparison)<-c("Equal-weighted","System-with-turbulence-filter")

charts.PerformanceSummary(perf_comparison,ylog=TRUE,main="Turbulence-based System vs Equal-Weighted CRB and SP500")

No comments:

Post a Comment