0

我已经成功地计算了我的xts对象中的滚动相关性

x <- cbind(market_return,stock_returns)
rollcor_3year <- rollapplyr(
    x, width=width_cor,function(x) cor(x[,1],x[,-1],
    use="pairwise.complete.obs"),by.column=FALSE)

该相关性后来用于计算滚动 Beta。

现在我CAPM.betaPerformanceAnalytics包中找到了这个功能,我想知道为什么我不能使用

beta <- rollapplyr(x,width=width_cor,function(x) CAPM.beta(x[,1],x[,-1]),by.column=FALSE)

或者

beta <- rollapplyr(stock_returns,width=width_cor,CAPM.beta,Rb=market_return,by.column=FALSE)

直接地。

使用这两个功能,它开始计算但不会停止......

很高兴看看我是否从预定义的函数中获得了相同的 beta,但显然它不是那样工作的。我做错了什么?

4

2 回答 2

1

Actually, the PerformanceAnalytics function will give the same results but it takes longer to do it. The code below uses sample data for 2017-01-01 to now with AMZN and XOM as stocks and SPY as a proxy for market returns. A window of 40 trading days is used in the rolling calculations. The rolling beta value is calculated using the CAPM.beta and BetaCoVariance functions from PerformanceAnalytics and by three methods which directly calculate the covariance matrix and then taking the ratio of the pairwise covariances to the market variance. The results from the methods are displayed to show they are the same. microbenchmark from the microbenchmark package is used to measure execution times for all methods. The direct calculations is one to two orders of magnitude faster.

  library(xts)
  library(quantmod)
  library(PerformanceAnalytics)
  library(microbenchmark)
#
#  get price time histories and calculate returns
#  use SPY as proxy for S&P 500; SPY should be first symbol in assets
#
  assets <- c("SPY", "AMZN", "XOM")   
  getSymbols( assets, from = "2017-01-01", auto.assign = TRUE)

  asset_prices <- xts()
  asset_prices <- Reduce(f=function(x,y) {y_sym=eval(as.name(y));  merge(x,y_sym[,paste0(y,".Adjusted")])},
                         x = assets, init=asset_prices) 
  asset_returns <- diff.xts(asset_prices, arithmetic = FALSE, na.pad=FALSE)-1

  market_return <- asset_returns$SPY.Adjusted
  stock_returns <- asset_returns[,-1] 

#
#  calculate rolling beta with a 40 trading-day window using CAPM.beta.roll
#  For this amount of data and calculating daily betas (by = 1), calculation should take 5-10 seconds
#
  width_cor = 40
  CAPM.beta_roll <- rollapply(data=stock_returns, FUN=CAPM.beta, Rb= market_return, Rf = 2.5/252, 
                       width = width_cor, by = 1, align = "right", by.column=TRUE)

#
#  calculate rolling beta with a 40 trading-day window by calculating the covariance matrix and taking ratio of two elements
#  For this amount of data and calculating daily betas (by = 1), calculation should be very quick
#
  CovVar <- function(Ra, Rb) {R = merge.xts(Rb, Ra, join="inner"); cv=cov(x=R);  
                               cv[1,-1]/cv[1,1,drop=TRUE]}
  CovVar_roll <- rollapplyr(data=stock_returns, width=width_cor,
                            FUN= CovVar,  Rb = market_return, by.column=FALSE)

#
#  since rollapply does not apply the window to Rb, it is done in CovVar for each time window
#  CovVar1 is a faster version which passes the merged market and stock return to cov directly
#  Its single argument R must be the merged data matrix R
#
  CovVar1 <- function(R){  cv=cov(x=R); cv[-1,1]/cv[1,1]}
  CovVar1_roll <- rollapplyr(data=merge(market_return, stock_returns), width=width_cor,
                             FUN= CovVar1,  by.column=FALSE)

  #
  #  CovVar2 is a faster version which passes the merged market and stock return to cov directly and 
  #  calculates the covariances only between the market returns and stock_returns.  For a small number of stocks,
  #  this is less efficient than calculating the entire covariance for a single matrix as in CovVar1 but it should become more 
  #  efficient for a larger number of stocks.
  #  Its single argument R must be the merged data matrix R
  #
  CovVar2 <- function(R){  cv = cov(R[,1], R );  cv[,-1]/cv[1,1] }
  CovVar2_roll <- rollapplyr(data=merge(market_return, stock_returns), width=width_cor,
                             FUN= CovVar2,  by.column=FALSE)

#
# Compare to verify that results are the same 
#
  print(tail(merge(CAPM.beta_roll, CovVar_roll, CovVar1_roll, CovVar2_roll )))
#
#  Compare execution times for four above methods and third method using BetaCovariance function from PerformanceAnalytics
#  This should take 25-35 seconds to run
#

  elapsed_times <- microbenchmark(
                  CAPM.beta_roll = rollapplyr(data=stock_returns, width=width_cor,
                                              FUN= CAPM.beta, Rb=market_return,by.column=FALSE),
                  BetaCoVar_roll = rollapplyr(data=stock_returns, width=width_cor,
                                               FUN= BetaCoVariance, Rb=market_return,by.column=FALSE),
                  CovVar_roll = rollapplyr(data=stock_returns, width=width_cor,
                                           FUN= CovVar,  Rb = market_return, by.column=FALSE),
                  CovVar1_roll = rollapplyr(data=merge(market_return, stock_returns), width=width_cor,
                                             FUN= CovVar1,  by.column=FALSE),
                  CovVar2_roll = rollapplyr(data=merge(market_return, stock_returns), width=width_cor,
                                             FUN= CovVar2,  by.column=FALSE),
                   times = 3)

# 
#  Direct calculation using covariance matrix, CovVar, is 50 - 100 times faster than PerformanceAnalytics functions 
#
  print(elapsed_times)

The execution times are:

Unit: milliseconds
           expr        min         lq       mean     median         uq        max neval
 CAPM.beta_roll 3007.34309 3009.92618 3016.57905 3012.50928 3021.19703 3029.88477     3
 BetaCoVar_roll 3453.83531 3471.70954 3478.91433 3489.58377 3491.45383 3493.32390     3
    CovVar_roll   69.19571   69.57012   69.83189   69.94453   70.14999   70.35544     3
   CovVar1_roll   38.72437   39.17021   39.33052   39.61605   39.63359   39.65113     3
   CovVar2_roll   60.75020   61.08255   61.36130   61.41490   61.66684   61.91878     3 

CovVar1 is the quickest since at least for a small number of dimensions, R calculates the covariance matrix much more efficiently for a single matrix input than for an input of two matrices where it has to align the matrices. For some larger number of dimensions, the CovVar2 should be faster.

于 2018-06-29T16:15:02.127 回答
1

这是WaltS 的答案中的解决方案,但比使用包的CovVar2功能快 16 倍rollRegres

library(xts)
library(quantmod)
library(PerformanceAnalytics)
library(microbenchmark)

# setup
assets <- c("SPY", "AMZN", "XOM")
getSymbols( assets, from = "2017-01-01", auto.assign = TRUE)
#R [1] "SPY"  "AMZN" "XOM"

asset_prices <- xts()
asset_prices <- Reduce(f=function(x,y) {y_sym=eval(as.name(y));  merge(x,y_sym[,paste0(y,".Adjusted")])},
                       x = assets, init=asset_prices)
asset_returns <- diff.xts(asset_prices, arithmetic = FALSE, na.pad=FALSE)-1

market_return <- asset_returns$SPY.Adjusted
stock_returns <- asset_returns[,-1]

# solution from WaltS's answer
width_cor <-  40
CovVar2 <- function(R){  cv = cov(R[,1], R );  cv[,-1]/cv[1,1] }
CovVar2_roll <- rollapplyr(
  data = merge(market_return, stock_returns), width=width_cor,
  FUN= CovVar2,  by.column=FALSE)

# rollRegres solution
library(rollRegres)
dat <- as.matrix(merge(market_return, stock_returns))
X  <- cbind(1, dat[, 1])
Ys <- dat[, -1, drop = FALSE]
roll_out <- apply(Ys, 2, function(y)
  roll_regres.fit(x = X, y = y, width = width_cor)$coefs[, 2])

# gives the same
all.equal(as.matrix(CovVar2_roll), roll_out, check.attributes = FALSE)
#R [1] TRUE

# much faster
microbenchmark(
  CovVar2 = rollapplyr(
    data = merge(market_return, stock_returns), width=width_cor,
    FUN= CovVar2,  by.column=FALSE),
  rollRegres = {
    dat <- as.matrix(merge(market_return, stock_returns))
    X  <- cbind(1, dat[, 1])
    Ys <- dat[, -1, drop = FALSE]
    roll_out <- apply(Ys, 2, function(y)
      roll_regres.fit(x = X, y = y, width = width_cor)$coefs[, 2])
  }, times = 10)
#R Unit: milliseconds
#R       expr       min        lq      mean    median        uq      max neval
#R    CovVar2 37.669941 39.086237 39.877981 39.530485 41.011374 41.71893    10
#R rollRegres  1.987162  2.036149  2.486836  2.102717  3.342224  3.73689    10
于 2018-07-02T21:21:33.643 回答