我试图在R中编写一个函数来以编程方式选择一组日期,每次迭代都依赖于之前的日期选择。我无法解决的挑战是如何系统地分析数据集,在分析的每个阶段选择日期,然后使用该日期作为选择下一个日期的起点。对于每次新迭代,一次一个地执行此操作是微不足道的。问题是如何编写一个函数,当数据集中没有剩余日期满足条件时,该函数将自动停止?我知道有一个解决方案,可能使用for()和/或while()循环,可能还有break()命令。但到目前为止,我无法找到答案。任何帮助,将不胜感激。作为我试图解决的过程的一个简单例子:
# create fake data for 12 months with dates
library("xts")
set.seed(67)
dat <-xts(rnorm(12)+100,seq(as.Date("2001/1/1"), as.Date("2001/12/1"), "1 months"))
查看原始数据:
dat
[,1]
2001-01-01 101.21940
2001-02-01 99.87560
2001-03-01 99.04250
2001-04-01 99.92083
2001-05-01 98.85659
2001-06-01 98.94281
2001-07-01 99.61547
2001-08-01 100.60834
2001-09-01 101.67247
2001-10-01 98.46271
2001-11-01 98.62171
2001-12-01 100.49543
接下来,创建第一个选择第一个日期的函数,在这种情况下只需选择第二个日期条目:
f.1 <-function(x) {
a <-as.Date(index(dat[2]))
}
创建第二个函数,查看第一个日期之后的日期,并选择那些日期&gt; 101。
f.2 <-function(x,y) { # x=dat, y=previous foo.date
a <-x[paste0(y+1, "/")]
b <-as.Date(index(a[a >101]))
}
最后,运行函数并收集日期......
foo.date.1 <-f.1(dat)
foo.date.2 <-f.2(dat,foo.date.1)
foo.date.3 <-f.2(dat,foo.date.2)
汇总3个foo.date文件的输出:
dat.all <-c(foo.date.1, foo.date.2, foo.date.3)
dat.all
[1] "2001-02-01" "2001-09-01"
请注意,所选的最后日期是foo.date.2。第三次尝试 - 根据foo.date.3 - 没有执行,因为2001-09-01之后没有值超过101的日期。然而,对于具有数千甚至数万个日期的数据集,找到与标准匹配的确切日期集是非常低效的。有关如何以编程方式找到解决方案的任何想法?在上面的例子中,通过函数的解决方案将a)发现只有2个日期符合标准,因此函数将在第二次尝试之后结束而不是尝试第三次搜索; b)在一个文件输出中汇总相关日期。
提前感谢您的任何答案!
答案 0 :(得分:1)
如果我理解正确,你想找到每次观察后观察的指数值&gt; 101。
一个简单有效的解决方案是首先lag
你的系列,然后简单地选择&gt;的观察的所有索引值。 101。
datlag <- lag(dat)
index(datlag[datlag > 101])
# [1] "2001-02-01" "2001-10-01"
基于此评论:
他的“标准”(目标)是确定投资组合中的权重偏离目标权重x(对于给定的回报系列)的日期。这对每个日期都很容易,一次一个。第一个函数标识第一个日期;第二个函数与使用前一个日期的区别相同。第二个功能可能会重复,具体取决于第一个功能超出第一个功能。#/ p>
问题似乎是真正的递归,这是使用循环的一个很好的理由(尽管你仍然需要注意在循环中增长对象)。
在这种情况下,您会定期将投资组合权重重置为目标。这意味着您必须重新计算所有未来的投资组合余额。
以下是2个资产的示例。
# asset return data
set.seed(67)
dat <- xts(matrix(rnorm(24, 0, 0.02),12,2),
seq(as.Date("2001/1/1"), as.Date("2001/12/1"), "1 months"))
# constraints
target_weights <- c(0.5, 0.5)
tol <- 0.01 # each asset must be +/-1% of its target
rebal_dates <- start(dat) # assume allocation on first observation
# loop until break
while (last(rebal_dates) < end(dat)) {
# date range, starting from period after last rebalance date
date_range <- paste0(last(rebal_dates) + 1, "/")
# portfolio balance over date range
bal <- cumprod(1 + dat[date_range,])
# portfolio weights
wts <- bal / rowSums(bal)
# deviations from target portfolio
dev <- abs(wts - rep(target_weights, nrow(wts))) > tol
# next rebalance date
next_rebal <- which(rowSums(dev) > 0)
# break the loop if there are no more rebalance dates
if (length(next_rebal) == 0)
break
# append rebalance date to our vector
# (yes, this is growing an object, but it's small and not very frequent)
rebal_dates <- c(rebal_dates, index(dev)[next_rebal[1]])
}
rebal_dates
# [1] "2001-01-01" "2001-06-01" "2001-09-01" "2001-10-01" "2001-11-01"
答案 1 :(得分:0)
我不熟悉xts格式,因此我使用标准数据框重新创建了数据,date
:日期字段和x
:随机值。
set.seed(4)
dat <- data.frame(date=as.Date(paste0("2001-", 1:12, "-1")), x=rnorm(12)+100)
head(dat)
date x
1 2001-01-01 100.21675
2 2001-02-01 99.45751
3 2001-03-01 100.89114
4 2001-04-01 100.59598
5 2001-05-01 101.63562
6 2001-06-01 100.68928
提取x > 101
的日期:
lapply(1:nrow(dat), function(x){
d2 <- dat[x:nrow(dat), ]
d2[d2$x > 101, "date"]
})
[[1]]
[1] "2001-05-01" "2001-09-01" "2001-10-01"
[[2]]
[1] "2001-05-01" "2001-09-01" "2001-10-01"
[[3]]
[1] "2001-05-01" "2001-09-01" "2001-10-01"
[[4]]
[1] "2001-05-01" "2001-09-01" "2001-10-01"
[[5]]
[1] "2001-05-01" "2001-09-01" "2001-10-01"
[[6]]
[1] "2001-09-01" "2001-10-01"
[[7]]
[1] "2001-09-01" "2001-10-01"
[[8]]
[1] "2001-09-01" "2001-10-01"
[[9]]
[1] "2001-09-01" "2001-10-01"
[[10]]
[1] "2001-10-01"
[[11]]
character(0)
[[12]]
character(0)