CAPM.beta 滚动应用
CAPM.beta rollapply
我已经成功计算了我的 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)
相关性后来用于计算滚动贝塔。
现在我从PerformanceAnalytics
包中找到了函数CAPM.beta
,我想知道为什么我不能使用
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)
直接。
有了这两个函数,它开始计算但不会停止...
很高兴看到我是否从预定义函数中得到了相同的测试版,但显然它不能那样工作。我做错了什么?
实际上,PerformanceAnalytics
函数会给出相同的结果,但需要更长的时间。下面的代码使用 2017-01-01 到现在的样本数据,AMZN 和 XOM 作为股票,SPY 作为市场的代理 returns。滚动计算使用 window 40 个交易日。滚动 beta 值是使用 PerformanceAnalytics
中的 CAPM.beta
和 BetaCoVariance
函数以及通过直接计算协方差矩阵然后取成对协方差与市场方差之比的三种方法计算的。显示这些方法的结果以表明它们是相同的。 microbenchmark
包中的 microbenchmark
用于测量所有方法的执行时间。直接计算要快一到两个数量级。
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)
执行时间为:
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 是最快的,因为至少对于少量维度,R 计算协方差矩阵对于单个矩阵输入比对于必须对齐矩阵的两个矩阵输入更有效。对于一些更大的维度,CovVar2 应该更快。
这是一个与 相同的解决方案,但比使用 rollRegres
包
的 CovVar2
函数快大约 16 倍
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
我已经成功计算了我的 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)
相关性后来用于计算滚动贝塔。
现在我从PerformanceAnalytics
包中找到了函数CAPM.beta
,我想知道为什么我不能使用
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)
直接。
有了这两个函数,它开始计算但不会停止...
很高兴看到我是否从预定义函数中得到了相同的测试版,但显然它不能那样工作。我做错了什么?
实际上,PerformanceAnalytics
函数会给出相同的结果,但需要更长的时间。下面的代码使用 2017-01-01 到现在的样本数据,AMZN 和 XOM 作为股票,SPY 作为市场的代理 returns。滚动计算使用 window 40 个交易日。滚动 beta 值是使用 PerformanceAnalytics
中的 CAPM.beta
和 BetaCoVariance
函数以及通过直接计算协方差矩阵然后取成对协方差与市场方差之比的三种方法计算的。显示这些方法的结果以表明它们是相同的。 microbenchmark
包中的 microbenchmark
用于测量所有方法的执行时间。直接计算要快一到两个数量级。
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)
执行时间为:
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 是最快的,因为至少对于少量维度,R 计算协方差矩阵对于单个矩阵输入比对于必须对齐矩阵的两个矩阵输入更有效。对于一些更大的维度,CovVar2 应该更快。
这是一个与 rollRegres
包
CovVar2
函数快大约 16 倍
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