AXP vs SPY rolling alpha

This post is an extension of the work of Jonathan Regenstein, author of the book “Reproducible Finance with R.”  If you don’t have a copy of this book, it is available here.   Additionally, Jonathan’s blog is up on RStudio’s website.  I highly recommend the book if you have any interest in investing using a tool kit beyond what is available with Excel and a legacy data terminal, and learning to do so in a way that’s written for investment professionals.

What I’ve done here is extend and amend a simple framework of the Shiny App code in Jonathan’s book, and changed the core of it to explore a different idea I’ve been thinking about: Rolling Alpha.

The Rolling Alpha Shiny App is here.  The verbiage explaining the app, as well as the code, follows below:

Alpha is the difference between a stock’s actual return and the expected return, given by the the stock’s Beta * the market’s return for a given period.

As a money manager, I’m less interested in whether my stocks behave in an absolute sense than I am in whether they behave better than they should.  I view this metric as an indication of whether I’m adding value as a manager.  I’m always working inside the context of a hedged portfolio where allocating capital is a dynamic ordinal value process and hedging is expected to handle both exogenous volatility and excess covariance, and so at the end of the day it’s all just an exercise in isolating the effectiveness of stock picking, of which alpha is my measure.  

So, every day watching the book I would be looking at the actual returns vs their forecasted returns using CAPM.  Ideally, on a ongoing basis, my longs would outperform what they were expected to do, and shorts underperform similarly.  

To that end I have begun implementing this idea systematically using the R language skills I’ve learned over the past two years in my job as Senior Data Scientist at Sentieo.  I plan to share generic code samples with the community, as a way of giving back from what I’ve learned for free from so many others.  Production code at Sentieo – obviously – won’t be on this blog.  What I plan to share here are broad ideas for discussion.  Perhaps in the end this will just be a blog about extensions to the PerformanceAnalytics R package.  

At any rate, this little Alpha Returns app simply takes daily returns of the market and a given stock, calculates the beta of the stock over a rolling window (I use 60 days as a convention but you can change it) and applies that beta to the market’s daily returns.  The difference between the stock’s actual return and the market return * beta expected return is alpha.  The cumulative sum of alpha is shown on the chart along with the cumulative return of the stock and the market.

I like this idea as a simple visual proxy for whether a given stock is “adding alpha” against its index.  Extending this idea into portfolio management and modeling its portfolio / predictive value is the work of future posts.

A caveat: I used a mix of Tidyverse, XTS, and matrix dataframes in order to use a wonderful package called rollRegress for the rolling beta calculation. 

I’m aware that having only one foot in the Tidyverse makes for a lot of miserable data frame conversions – I have the same issue in our production work at Sentieo, where I use the data.table package a lot for speed while yet implementing dplyr functions from time to time.  It’s a trade-off I’m willing to make specifically in this case for rollRegress vs an implementation using tibbletime’s rollify function, but that route is certainly an option if you choose to make the change yourself.  And to be fair I haven’t microbenchmarked rollify vs rollRegress so I would accept that potential mistake if it were one.

To the code, and again I strongly recommend Jonathan’s book for additional reference.

---
title: "Alpha Returns"
output: flexdashboard::flex_dashboard
runtime: shiny
---

```{r global, include=FALSE}
library(tidyverse)
library(PerformanceAnalytics)
library(quantmod)
library(rollRegres) #very fast rolling regression library
```

Sidebar {.sidebar}
=====================================

```{r}

fluidRow(
  column(6,
  textInput("ticker","Ticker","AXP"))
)
fluidRow(
  column(6,
  textInput("index","Index","SPY"))
)
fluidRow(
  column(7,
  dateInput("date",
  "Starting Date",
  "2013-01-01",
  format="yyyy-mm-dd"))
)
fluidRow(
  column(6,
  textInput("beta_days","Rolling Beta Window","60"))
)


actionButton("go","Submit")

portfolio_returns_byhand <- eventReactive(input$go, {
symbols <- c(input$ticker,
             input$index)

beta_days <- as.numeric(input$beta_days)

#QUANTMOD GET PRICES
prices <- getSymbols(symbols,
                     src="yahoo",
                     from=input$date,
                     to=Sys.Date(),
                     auto.assign=TRUE,
                     warnings=FALSE) %>%
  map(~Ad(get(.))) %>%
  reduce(merge) %>%
  'colnames<-'(c("ticker","index"))

#USE PORTFOLIO ANALYTICS FOR LOG RETURNS
asset_returns_daily <- prices %>%
  Return.calculate(method="log") %>%
  na.omit()

#ROLLING REGRESSION
m.returns <- as.matrix(merge(asset_returns_daily[,2], asset_returns_daily[,1]))
v.X  <- cbind(1, m.returns[, 1])
v.Y <- m.returns[, -1, drop = FALSE]
roll_out <- apply(v.Y, 2, function(y)
  roll_regres.fit(x = v.X, y = y, width = beta_days)$coefs[, 2])

#SOME XTS PRETZEL LOGIC
xts.returns<-as.xts(roll_out)
xts.returns<-data.frame(date=index(xts.returns), coredata(xts.returns)) %>%
  select(-date)
colnames(xts.returns)<-c("beta")

#MAGRITTR CREATE COLUMNS FOR GRAPHING
asset_returns_daily<-(cbind(xts.returns,data.frame(date=index(asset_returns_daily), coredata(asset_returns_daily)))) %>%
  select(date,ticker,index,beta) %>%
  mutate(predicted=index*beta) %>%
  mutate(alpha=ticker-predicted) %>%
  mutate(cpalpha=(1+alpha)) %>%
  mutate(cpindex=1+index) %>%
  mutate(cpticker=1+ticker) %>%
  na.omit()

#CALCULATE CUMULATIVE PRODUCT
fun_cumulative_prod <- function(x) cumprod(x) #HELPER FUNCTION

asset_returns_daily[,7:9]<-lapply(asset_returns_daily[,7:9],FUN = fun_cumulative_prod)

portfolio_returns_byhand<-asset_returns_daily

})
```

Returns
=====================================  


Row {.tabset .tabset-fade}
-------------------------------------


```{r}
renderPlot({
  portfolio_returns_byhand() %>%
  ggplot(aes(x=date)) +
  geom_line(aes(y=cpalpha,color="Alpha")) +
  geom_line(aes(y=cpindex,color=input$index)) +
  geom_line(aes(y=cpticker,color=input$ticker)) +
  theme_minimal() +
  labs(title="Cumulative Daily Alpha") +
  labs(color="")
})
```

Leave a Reply

Your email address will not be published. Required fields are marked *