Wednesday, March 15, 2017

An R Script to Calculate and Plot Alpha

Alpha is the essence of trading. Getting risk-adjusted returns above the market is a zero sum game and what leads to value. Here's an R script to calculate and plot the alpha of an asset. Any asset that is available for download in Yahoo is OK. It also outputs some related statistics.

For example, supposing we wanted to analyze the materials etf XLB. We would call the function with

> AlphaPlot('XLB')

and the function would output:

[1] "Number of Trading Days is  4585"
[1] "Beta is  0.96"
[1] "Beta of Last 100 Days is 1.04"
[1] "Annualized Total Return 0.07657"
[1] "Annualized Alpha 0.01973"
[1] "Ending Cumulative Alpha is 0.4208"

In the plot window, this graph of cumulative alpha over time will appear:

If you want to try this, here's the code. The usual disclaimers apply:
This is not investment advice. Don't blame me if you lose money.
The code may have bugs I didn't catch. Kindly make a comment if you find one.
You may not agree with my interpretation of modern finance.
Alpha here is purely historical. We all know about past performance and such.

# Typical call
# AlphaPlot('PUTW','SPY')
library(quantmod)
#
AlphaPlot <- function( asset, baseAsset = 'SPY', period = 'd', judgemtl = 'n', plotLength = 'all', yLog=TRUE){
#   Creates and plots a alpha series of 'asset' against 'baseAsset'
  # asset       = the asset to get the alpha of
  # baseAsset   = the base (independent) asset or index
  # period      = 'd', 'm', or 'y'
  # judgemtl    = used to assign a non-statistical beta
  # plotLength  = if a number, plots the last plotLength days
  
  if ( !plotLength == 'all') {
    if ( !is.numeric(plotLength ) ) {
      print('plotLength must be set to all or a number')
      return()
    }
  }

  myEnv <- new.env()
  getSymbols(c( asset, baseAsset ), from = '1990-01-01', env = myEnv)
  MainXTS <- do.call(merge, c(eapply(myEnv, Ad),all=FALSE))
  
  period   <- tolower(period)
  prd <- c( 'daily', 'monthly', 'yearly')
  dum <- substring(prd,1,1)
  inx <- which( period==dum)
  dum <- prd[inx]
  a <- periodReturn( MainXTS[,1], period = dum )
  b <- periodReturn( MainXTS[,2], period = dum)
  
  
print( paste("Number of Trading Days is ",length(MainXTS[,1])) )
  if (judgemtl == 'n'){
    reg <- lm( a ~ b )
    beta <- reg$coeff[2]
  }
  if ( judgemtl != 'n' ) beta <- judgemtl
  title = paste('Cumulative Alpha', asset, dum, 'versus', baseAsset, collapse='   ')
  alpha <- cumprod(1 + (a - beta * b))
  print( paste( 'Beta is ', format(beta, digits = 2 ) ) )
  dumm <- lm( tail(a,100) ~ tail(b,100) )
  print( paste("Beta of Last 100 Days is", format(dumm$coeff[2], digits = 3)) )
  annAlpha <- as.numeric( tail( alpha,1 ) )
  annAlpha <- annAlpha ^ (255/length(MainXTS[,1]))
  gg=as.numeric(tail(MainXTS[,1],1)) / as.numeric(head(MainXTS[,1],1))
  print( paste( 'Annualized Total Return',  format( gg ^ (255/length(MainXTS[,1]))-1,digits = 4 ) ) )
  print(paste( 'Annualized Alpha', format(annAlpha-1, digits = 4) ) )
  print( paste( 'Ending Cumulative Alpha is', format(alpha[length(alpha)]-1,digits = 4) ) )
  
  if (plotLength == 'all') plot( alpha, main = title )
  else plot( tail( alpha, plotLength ), main = title )
  #legend( 'topleft', c( paste( 'Beta = ', sprintf("%5.2f", beta) ) ) )

}

As you can see there are a number of options. If you just call it with the symbol (in quotes), it will default to using SPY as the base with which to calculate the alpha. If you give it a second symbol, it will use that as the base. It defaults to daily prices, but you can specify 'm' for monthly or 'y' for yearly. Beta comes out of the calculation, but if you want to use your judgement for it, specify "judgement=" and a number. It also defaults to using all the downloaded data, but you can use the "plotlength=" and put in a number for the last number of days.

Good luck everyone! I'll be putting more of this kind of stuff up soon.