r-天真的投资组合选择规则



我有一个xts文件,里面有17个行业投资组合的月度回报。数据如下:

Cars Chems Clths Cnstr Cnsum Durbl FabPr Finan  Food Machn Mines   Oil Other Rtail Steel Trans
1926-07-31   4.77  1.20 -0.09  4.20  2.05  1.33  0.61  0.44  0.46  2.06  2.65 -2.57  1.99  1.46  3.05 -0.69
1926-08-31  -1.11  3.55  3.57  0.85  4.10  0.75 -0.49  8.84  4.72  5.57  1.16  3.85  4.81  0.63 -0.58  4.96
1926-09-30  -3.39  1.85 -4.89 -1.06  2.50  1.27 -3.10 -2.55  1.66  0.52  1.44 -4.93 -2.09 -1.20  2.28  0.06
1926-10-31 -10.66 -9.15  0.49 -6.49 -1.41 -5.02 -3.92 -4.40 -4.79 -4.52  5.73  0.23 -3.50 -2.44 -4.98 -2.79
1926-11-30  -0.73  4.98  2.66  2.91  8.35  0.12  1.36 -0.27  7.04 -0.75  1.13  2.92 -0.47  1.72  1.81  1.38
1926-12-31   5.14  2.59  2.30  3.37  1.96  4.23  2.22  2.40 -1.39  2.93 -1.38  6.39  2.59  3.06  2.17  2.18
Utils
1926-07-31  4.85
1926-08-31 -2.00
1926-09-30  2.06
1926-10-31 -2.98
1926-11-30  5.71
1926-12-31  1.72

我的目标是用一个天真的投资组合选择规则进行回溯测试。我不想持有同等权重的投资组合,而是想根据以下天真的规则对权重进行分类:

  • 为历史回报率高于中位数的每项资产分配权重2/N
  • 如果低于历史回报中值,则指定权重0

代替相等加权向量:

w <- c(rep(1/17,17))

这个加权向量可以很好地获得投资组合的回报。为此,我使用了以下功能:

portfolio_returns_tq_rebl <- 
returns %>% 
tq_portfolio(assets_col = symbol,
returns_col = return,
weights = w, # here i want to have a weighting function?!
col_rename = "returns",
rebalance_on = "months")

我坚持将加权函数合并到标准的回溯测试脚本中(tidyquant、PerformanceAnalytics、quantmod(。在大多数情况下,只能解决优化问题,而不能解决简单的天真规则。

有人知道如何用一个简单的投资组合选择规则进行这样的回溯测试吗?

谢谢你的帮助!

如果一个替代包也是可以接受的:下面是我维护的PMwR的示意图。我从一个示例数据集开始:Kenneth French网站上的17个行业投资组合(可能与您使用的数据集相同(。

library("PMwR")
library("NMOF")
P <- French(tempdir(),
"17_Industry_Portfolios_daily_CSV.zip",
frequency = "daily",
price.series = TRUE)

str(P)
## 'data.frame':    24935 obs. of  17 variables:
##  $ Food : num  1 1 1 1 1.01 ...
##  $ Mines: num  1 1 1.01 1 1 ...
##  $ Oil  : num  1 1.01 1.01 1.02 1.01 ...
##  $ Clths: num  1 1 1 1 1.01 ...
##  $ Durbl: num  1 0.989 0.983 0.965 0.964 ...
##  $ Chems: num  1 1.01 1.02 1.02 1.03 ...
##  $ Cnsum: num  1 1 1.01 1.01 1.01 ...
##  $ Cnstr: num  1 1 1 1.01 1.01 ...
##  $ Steel: num  1 0.994 1.006 1.007 1.007 ...
##  $ FabPr: num  1 0.992 1.002 1.008 1.032 ...
##  $ Machn: num  1 0.999 1.003 1.008 1.006 ...
##  $ Cars : num  1 0.999 1.009 1.018 1.019 ...
##  $ Trans: num  1 1 1 1 1 ...
##  $ Utils: num  1 1.01 1.01 1.02 1.02 ...
##  $ Rtail: num  1 1 1 0.998 0.992 ...
##  $ Finan: num  1 1.01 1.01 1.01 1 ...
##  $ Other: num  1 1 1 1.01 1.01 ...

可以使用函数btest运行回测。主";成分";的a";信号";在任何时刻调用并返回所需投资组合的函数。举个例子:这里的函数回顾250天,计算资产的回报,然后保留那些回报高于中位数的资产。

above_median <- function() {
## get the most recent 250 days
H <- Close(n = 250)
## compute total return of industries
R <- H[nrow(H), ] / H [1L, ]
## include only those with an above-median return
include <- R > median(R)
w <- numeric(ncol(H))
w[include] <- 1/sum(include)
w
}

此函数传递给btest,并带有每季度调用一次的指令。

bt <- btest(prices = list(as.matrix(P)),
timestamp = as.Date(row.names(P)),
signal = above_median,
do.signal = "lastofquarter",
b = 250, ## burnin
initial.cash = 100,
convert.weights = TRUE)

你可以分析结果。

summary(NAVseries(bt))
journal(bt)

更新,注释如下:btest不对数据频率施加限制。以下是每月数据的示例,从每月回报开始。

P <- French(tempdir(),
"17_Industry_Portfolios_CSV.zip",
price.series = FALSE)
head(P)  ## returns
##               Food   Mines     Oil  Clths   Durbl   Chems  Cnsum   Cnstr
## 1926-07-31  0.0048  0.0378 -0.0141 0.0602 -0.0162  0.0846 0.0142  0.0231
## 1926-08-31  0.0291  0.0069  0.0360 0.0015 -0.0196  0.0570 0.0584  0.0433
## ....

将收益转化为总收益系列:

P <- apply(P + 1, 2, cumprod)
head(P)  ## returns => 'prices'
##                Food    Mines       Oil    Clths     Durbl    Chems    Cnsum
## 1926-07-31 1.004800 1.037800 0.9859000 1.060200 0.9838000 1.084600 1.014200
## 1926-08-31 1.034040 1.044961 1.0213924 1.061790 0.9645175 1.146422 1.073429

调整每月数据的信号功能:

above_median <- function() {
## get the most recent 12 months
H <- Close(n = 12)
## compute total return of industries
R <- H[nrow(H), ] / H [1L, ]
## include only those with an above-median return
include <- R > median(R)
w <- numeric(ncol(H))
w[include] <- 1/sum(include)
w
}

使用适当的烧录b运行回测。

bt <- btest(prices = list(as.matrix(P)),
timestamp = as.Date(row.names(P)),
signal = above_median,
do.signal = "lastofquarter",
b = 12, ## burnin
initial.cash = 100,
convert.weights = TRUE)
unique(journal(bt)$timestamp)  ## timestamps of trades 
## [1] "1927-09-30" "1927-12-31" "1928-03-31" "1928-06-30" "1928-09-30"
## [6] "1928-12-31" "1929-03-31" "1929-06-30" "1929-09-30" "1929-12-31"
## ....

相关内容

  • 没有找到相关文章

最新更新