If you google-finance AMZN you can see the beta is 0.93. I already wrote in the past about this illusive concept. Beta is suppose to reflect the risk of an instrument with respect for example to the market. However, you can estimate this measure in all kind of ways.
You can shrink your estimate to stabilize it. You can use the robust version, and there are other other issues. One additional aspect is non-linearity of this risk measure. The sensitivity to the market need not be the same on red and green days. Here is a motivating figure:
What we see here is that AMZN has stronger correlation with the market when the market is down and weaker correlation when the market is up. There is correlation and there is correlation structure. The google-finance beta is the correlation, it can be that throughout the distribution it is the same, but it does not have to necessarily hold. As it is, to take it to the extreme, you don’t want to have a symbol with beta equals 1 which is the average of 2- when the market is down and 0.5- when the market is up. If you are long, the reverse is great, a symbol that rally in green days and declines only slowly on bad days.
I played around with a few other financial stocks to see if this is typical, here is the barplot of the coefficients on the positive days (light) and on the negative days (darker).
Citi is the only symbols which has stronger correlation during market down moves, most have pretty constant correlation with the market across the distribution and Morgan Stanley is a nice symbol to hold in that respect.
We see exactly the reverse from AMZN, steeper slope during up days than during down days. Naturally, it will be interesting to see how a portfolio constructed using this criterion performs, but I leave it for now. Code is below as usual.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
library(quantmod) # yes, library, not 'require'!, # see: http://yihui.name/en/2014/07/library-vs-require/ sym = c('AMZN','SPY') end<- format(Sys.Date(),"%Y-%m-%d") nyears <- 1 # most recent year start<-format(Sys.Date() - (nyears*365),"%Y-%m-%d") # nyears years of data amazon <- (getSymbols(sym[1], src="google", from=start, to=end, ascii = TRUE, auto.assign = F, warnings = FALSE,symbol.lookup = F)) market <- (getSymbols(sym[2], src="google", from=start, to=end, ascii = TRUE, auto.assign = F, warnings = FALSE,symbol.lookup = F)) marketPrice <- (as.numeric(market$SPY.Open)+as.numeric(market$SPY.Close))/2 head(marketPrice) amazonPrice <- (as.numeric(amazon$AMZN.Open)+as.numeric(amazon$AMZN.Close))/2 p0 <- cbind(amazonPrice,marketPrice) clc <- na.omit(p0[-1,]/p0[-NROW(p0),] - 1) # close to close # Clean outliers - defined by a return larger in abslute value than 15% clc <- clc[abs(clc[,2])<.15,] colnames(clc) <- c('AMZN','MARKET') # prepare input for regression positive_only <- ifelse(clc[,'MARKET']>0,clc[,'MARKET'],0) x <- cbind(rep(1,TT),clc[,'MARKET'],positive_only) lm0 <- lm(clc[,'AMZN']~0+x[,2]) summary(lm0) lm1 <- lm(clc[,'AMZN']~0+x) summary(lm1) plot(clc[,'AMZN']~clc[,'MARKET'], ylab="", main="AMZN close to close return on market return", xlab="market") abline(lm0,col = 4,lwd=2) lmneg <- lm1$coef[2]-lm1$coef[3] lmpos <- lm1$coef[2] segments(min(clc[,'MARKET']),min(clc[,'MARKET'])*lmneg,x1 = 0, y1 = 0, lwd = 5,col =2) segments(0,0,x1 = max(clc[,'MARKET']), y1 = max(clc[,'MARKET'])*lmpos, lwd = 5,col =3) # few more symbols.. sym = c('GS','DB','MS','C','JPM','UBS','CS','WFC','SPY') l=length(sym) end<- format(Sys.Date(),"%Y-%m-%d") start<-format(as.Date("2007-01-01"),"%Y-%m-%d") dat0 = (getSymbols(sym[1], src="yahoo", from=start, to=end, auto.assign = F)) n = NROW(dat0) dat = array(dim = c(n,6,l)) ; prlev = matrix(nrow = n, ncol = l) for (i in 1:l){ dat0 = (getSymbols(sym[i], src="yahoo", from=start, to=end, auto.assign = F)) dat[1:length(dat0[,1]),,i] = dat0 # Average Price during the day prlev[1:length(dat0[,1]),i] = as.numeric(dat[,4,i]+dat[,1,i]+dat[,2,i]+dat[,3,i])/4 } TT <- dim(prlev)[1];TT ret <- prlev[2:TT,]/prlev[1:(TT-1),] - 1 colnames(ret) <- sym positive_only <- ifelse(ret[,'SPY']>0,ret[,'SPY'],0) x <- cbind(rep(1,TT),ret[,'SPY'],positive_only) # Help function get_non_linear_beta <- function(xx){ lm0 <- lm(xx~0+x) poscoef <- lm0$coef[2] negcoef <- lm0$coef[2] - lm0$coef[3] list(a=poscoef,b=negcoef) } cof <- matrix(nrow = (l-1), ncol=2) for (i in 1:(l-1)){ # the last one is the market hence l-1. cof[i,] <- as.numeric(get_non_linear_beta(ret[,i])) } # fancy colors col1 <- rgb(0,0,1,1/4) col2 <- rgb(1,0,0,1/4) barplot(cof[,1],names.arg=sym[-l],col=col1,ylim=c(0,3.5)) barplot(cof[,2],add=T,col=col2) i=3 # Morgan Stanley plot(ret[,'MS']~ret[,'SPY'],main=sym[i],ylab="",xlab="Market returns") segments(min(ret[,'SPY']),min(ret[,'SPY'])*cof[i,2],x1 = 0, y1 = 0, lwd = 5,col =2) segments(0,0,x1 = max(ret[,'SPY']), y1 = max(ret[,'SPY'])*cof[i,1], lwd = 5,col =3) # Cheers, Eran |
Hey Eran, I tried running the code however I’m getting the series of errors. The first one occurs as follow:
> x <- cbind(rep(1,TT),clc[,'MARKET'],positive_only)
Warning message:
In cbind(rep(1, TT), clc[, "MARKET"], positive_only) :
number of rows of result is not a multiple of vector length (arg 2)
Thanks
Yeah, I also had it, add TT <- NROW(positive_only) before binding.