braverock / PerformanceAnalytics

209 stars 105 forks source link

table.CAPM Fails when no negative value for Rb #67

Closed mdancho84 closed 7 years ago

mdancho84 commented 7 years ago

Great package. Running into an issue with the table.CAPM function. I've drilled into the issue and it looks like table.CAPM fails when Rb does not include negative observations. The culprit seems to be CAPM.beta.bear which needs at least one negative observation in Rb to function properly. A possible solution is to return an NA if the subset is of length zero (prior to the lm call) or if the function errors out. You might also want to apply the same error handling with CAPM.beta.bull which can run into the same problem if all observations are negative. I've provided a text file with the R code to reproduce the issue. Let me know if you need anything else.

capm_test.txt

braverock commented 7 years ago

It seems that it would be better to fix PerformanceAnalytics:::.beta so that it can handle an NA subset.

mdancho84 commented 7 years ago

That would work as well. Thanks for the quick reply.

braverock commented 7 years ago

If you have time to propose a patch, that would be ideal. I don't find the CAPM to be useful enough to put it high on my priority list otherwise. Thanks!

mdancho84 commented 7 years ago

I sure can. I'll get back to you shortly.

mdancho84 commented 7 years ago

@braverock Sorry it's taking me a little bit to get back to you. My recommendation is to modify the CAPM.beta.bull and CAPM.beta.bear functions since the underlying .beta function is universally used for all cases. I have modified both functions in the forked PA repo here: https://github.com/mdancho84/PerformanceAnalytics/blob/master/R/CAPM.beta.R

I tested under two situations: all negative and all positive Rb values. Both return a warning message stating what the issue was and a value of NA, which is desirable since you don't want the entire calculation to fail. Here's a sample reprex output for one of the test cases:

library(tidyquant) # Loads Performance Analytics, tidyverse, etc
data_xts <- tribble(
    ~date,       ~z_score,    ~ROC,
    "2015-06-30",  0.9897708, -0.0430388593,
    "2015-09-30",  1.2130662, -0.0009265045,
    "2015-12-31", -1.3818587, -0.1362931345,
    "2016-03-31", -1.0039285, -0.0258810865,
    "2016-06-30", -0.3959101, -0.1164113133,
    "2016-09-30", -0.1024458, -0.0470085008
    ) %>%
    mutate(date = as_date(date)) %>%
    as_xts(date_col = date)

table.CAPM(Ra = data_xts[,1], Rb = data_xts[,2])
#> Function CAPM.beta.bull: Cannot perform lm. All Rb values are negative.
#>                     z_score to ROC
#> Alpha                       0.6708
#> Beta                       12.7351
#> Beta+                           NA
#> Beta-                      12.7351
#> R-squared                   0.4189
#> Annualized Alpha            6.7938
#> Correlation                 0.6472
#> Correlation p-value         0.1647
#> Tracking Error              2.0226
#> Active Premium             -0.7479
#> Information Ratio          -0.3698
#> Treynor Ratio              -0.0767
joshuaulrich commented 7 years ago

And here is a minimal reproducible example:

require(PerformanceAnalytics)
data_xts <- as.xts(read.zoo(text="date,z_score,ROC
2015-06-30,0.9897708,-0.0430388593
2015-09-30,1.2130662,-0.0009265045
2015-12-31,-1.3818587,-0.1362931345
2016-03-31,-1.0039285,-0.0258810865
2016-06-30,-0.3959101,-0.1164113133
2016-09-30,-0.1024458,-0.0470085008",
  sep = ",", header = TRUE))
table.CAPM(Ra = data_xts[,1], Rb = data_xts[,2])