Cross Sectional Correlation
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Diversification is hard to find nowadays because financial markets are becoming increasingly correlated. I found a good visually presentation of Cross Sectional Correlation of stocks in the S&P 500 index in the Trading correlation by D. Varadi and C. Rittenhouse article.
Let’s compute and plot the average correlation among stocks in the S&P 500 index and the the average correlation between SPY and stocks in the S&P 500 index using the Systematic Investor Toolbox:
###############################################################################
# Load Systematic Investor Toolbox (SIT)
# http://systematicinvestor.wordpress.com/systematic-investor-toolbox/
###############################################################################
con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb'))
source(con)
close(con)
#*****************************************************************
# Load historical data
#******************************************************************
load.packages('quantmod')
tickers = sp500.components()$tickers
data <- new.env()
getSymbols(tickers, src = 'yahoo', from = '1970-01-01', env = data, auto.assign = T)
for(i in ls(data)) data[[i]] = adjustOHLC(data[[i]], use.Adjusted=T)
bt.prep(data, align='keep.all', dates='1970::')
spy = getSymbols('SPY', src = 'yahoo', from = '1970-01-01', auto.assign = F)
ret.spy = coredata( Cl(spy) / mlag(Cl(spy))-1 )
#*****************************************************************
# Code Logic
#******************************************************************
prices = data$prices['1993:01:29::']
nperiods = nrow(prices)
ret = prices / mlag(prices) - 1
ret = coredata(ret)
# require at least 100 stocks with prices
index = which((count(t(prices)) > 100 ))
index = index[-c(1:252)]
# average correlation among S&P 500 components
avg.cor = NA * prices[,1]
# average correlation between the S&P 500 index (SPX) and its component stocks
avg.cor.spy = NA * prices[,1]
for(i in index) {
hist = ret[ (i- 252 +1):i, ]
hist = hist[ , count(hist)==252, drop=F]
nleft = ncol(hist)
correlation = cor(hist, use='complete.obs',method='pearson')
avg.cor[i,] = (sum(correlation) - nleft) / (nleft*(nleft-1))
avg.cor.spy[i,] = sum(cor(ret.spy[ (i- 252 +1):i, ], hist, use='complete.obs',method='pearson')) / nleft
if( i %% 100 == 0) cat(i, 'out of', nperiods, '\n')
}
#*****************************************************************
# Create Report
#******************************************************************
sma50 = SMA(Cl(spy), 50)
sma200 = SMA(Cl(spy), 200)
cols = col.add.alpha(spl('green,red'),50)
plota.control$col.x.highlight = iif(sma50 > sma200, cols[1], cols[2])
highlight = sma50 > sma200 | sma50 < sma200
plota(avg.cor, type='l', ylim=range(avg.cor, avg.cor.spy, na.rm=T), x.highlight = highlight,
main='Average 252 day Pairwise Correlation for stocks in SP500')
plota.lines(avg.cor.spy, type='l', col='blue')
plota.legend('Pairwise Correlation,Correlation with SPY,SPY 50-day SMA > 200-day SMA,SPY 50-day SMA < 200-day SMA',
c('black,blue',cols))
The overall trend for correlations is up. Moreover, correlations are usually rising in the bear markets, when SPY 50-day SMA < 200-day SMA.
To view the complete source code for this example, please have a look at the bt.rolling.cor.test() function in bt.test.r at github.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
