将xts对象索引到最接近每个月N日的日期

时间:2015-08-27 15:22:21

标签: r xts

我想用最接近每个月n日的日期索引xts对象。

换句话说,我想要每个月15日的股票价格。但是,15日不是有效月份的有效交易日,因为它可能发生在周末或假日。对于那些月份,我想选择下一个(或者前一个)下一个有效交易日。

例如,2015年前四个月的“下一个第15个”系列将在1月15日,2月17日,3月16日和4月15日返回观察结果。

to.period( )通过选择每个月的最后一天,无论是30日,31日,28日还是29日,都可以有效地做到这一点。我想在一个月的任意一天概括这一点。

我已经能够通过蛮力来做到这一点,但我想知道是否有一种聪明的方法来做到这一点。

提前谢谢。

更新 -

Josh的回答几乎适合我 - 由于.indexmday()访问的索引值很奇怪,我的脚本最终失败了。

例如,

getSymbols("SPY", from="2015-01-01")
SPY[.indexmday(SPY) == 30]

产量

           SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted
2015-03-31   207.26   208.10  206.36    206.43  126768700     205.4304
2015-05-01   209.40   210.77  209.28    210.72  103399700     209.6996
2015-07-01   207.73   208.03  206.56    207.57  129406500     207.5700
2015-07-31   211.42   211.45  210.16    210.45   97697400     210.4500

因为.indexmday()检索5月1日和7月1日的索引值为30而不是0.我无法解释原因。我可以解决它 - 但解决方法是如此不优雅。有人知道.indexmday()这样做的原因吗?

2 个答案:

答案 0 :(得分:2)

嗯,这是一种方式,但它给“丑陋”这个词带来了新的含义。

library(quantmod)    # for getSymbols
sp500 <- getSymbols("^GSPC", from="2015-01-01",auto.assign=FALSE)

result <- apply.monthly(sp500,function(x)first(x[as.POSIXlt(index(x))$mday>=15],"day"))
result
#                GSPC.Open GSPC.High GSPC.Low GSPC.Close GSPC.Volume GSPC.Adjusted
# 2015-01-30   2013.75   2021.35  1991.47    1992.67  4276720000       1992.67
# 2015-02-27   2096.47   2101.30  2089.80    2100.34  3361750000       2100.34
# 2015-03-31   2055.35   2081.41  2055.35    2081.19  3295600000       2081.19
# 2015-04-30   2097.82   2111.91  2097.82    2106.63  4013760000       2106.63
# 2015-05-29   2122.07   2123.89  2116.81    2122.73  3092080000       2122.73
# 2015-06-30   2091.34   2091.34  2072.49    2084.43  3061570000       2084.43
# 2015-07-31   2109.01   2114.14  2102.49    2107.40  3261810000       2107.40
# 2015-08-26   2089.70   2102.87  2079.30    2102.44  2867690000       2102.44

因此,我们按月对sp500进行分组(使用apply.monthly(...)),并为每个组提取日期(POSIXlt对象中的mday)&gt; = 15的所有行,然后找到该子集中的第一个日期。

如果查看原始sp500对象,您会看到数据来自正确的日期,但apply.monthly(...)会将结果的索引设置为月末。要获得实际日期(AFAICT)更复杂:

indx <- as.Date(as.integer(apply.monthly(sp500,function(x)index(first(x[as.POSIXlt(index(x))$mday>=15],"day")))))
indx
# [1] "2015-01-15" "2015-02-17" "2015-03-16" "2015-04-15" "2015-05-15" "2015-06-15" "2015-07-15" "2015-08-17"

最后,把它们放在一起,

index(result) <- indx
result
#            GSPC.Open GSPC.High GSPC.Low GSPC.Close GSPC.Volume GSPC.Adjusted
# 2015-01-15   2013.75   2021.35  1991.47    1992.67  4276720000       1992.67
# 2015-02-17   2096.47   2101.30  2089.80    2100.34  3361750000       2100.34
# 2015-03-16   2055.35   2081.41  2055.35    2081.19  3295600000       2081.19
# 2015-04-15   2097.82   2111.91  2097.82    2106.63  4013760000       2106.63
# 2015-05-15   2122.07   2123.89  2116.81    2122.73  3092080000       2122.73
# 2015-06-15   2091.34   2091.34  2072.49    2084.43  3061570000       2084.43
# 2015-07-15   2109.01   2114.14  2102.49    2107.40  3261810000       2107.40
# 2015-08-17   2089.70   2102.87  2079.30    2102.44  2867690000       2102.44

答案 1 :(得分:0)

我找到了bizdays&amp; timeDate包在这方面很有帮助。 bizdays有助于将日期向量调整到下一个或上一个工作日。您还可以使用rmetrics从timeDate包导入NYSE日历,以便假期匹配。

library(bizdays)
library(timeDate)

getSymbols('^GSPC',from='2010-01-01')
load_rmetrics_calendars(2010:2017)
min <- index(GSPC)[1]
max <- index(GSPC)[length(index(GSPC))]
rng2 <- seq.Date(min,max,"month")
GSPC[adjust.next(rng2, cal = "Rmetrics/NYSE")]

输出摘录

           GSPC.Open GSPC.High GSPC.Low GSPC.Close
2010-01-04   1116.56   1133.87  1116.56    1132.99
2010-02-04   1097.25   1097.25  1062.78    1063.11
2010-03-04   1119.12   1123.73  1116.66    1122.97
2010-04-05   1178.71   1187.73  1178.71    1187.44
2010-05-04   1197.50   1197.50  1168.12    1173.60
2010-06-04   1098.43   1098.43  1060.50    1064.88
2010-07-06   1028.09   1042.50  1018.35    1028.06