【问题标题】:index an xts object by the date nearest to the Nth of every month按最接近每月第 N 天的日期索引 xts 对象
【发布时间】:2015-11-22 01:46:49
【问题描述】:

我想按最接近每个月的第 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() 会这样吗?

【问题讨论】:

  • 不完全相同,但也许这有帮助:mail-archive.com/r-sig-finance@r-project.org/msg06264.html
  • 这很有趣 - 谢谢 - 但你说得对,这不是我想要做的。诀窍是,如果有第 N 个日期,我想要那个确切的日期;如果没有,我想要该系列中存在的下一个日期。通过蛮力,我可以检查这一天是否存在,如果不存在,则循环遍历日期,直到找到确实存在的日期。我希望我可以在没有循环的情况下完成它......
  • 您在.indexmday 中看到的行为可能是xts 开发版中已修复的时区错误。
  • 我想知道为什么它对我失败但对其他人有效。无论如何,我会同时使用这个解决方法:SPY[.indexmday(SPY) >= 14 & .indexmday(SPY)<=25] 谢谢!
  • 正如我所说,它可能对你不起作用,因为你没有使用 xts 的开发版本。

标签: r xts


【解决方案1】:

嗯,这是一种方法,但它赋予了“丑陋”这个词新的含义。

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)>=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

【讨论】:

  • 老实说,我很难从头开始想出一个体面的方法,但你的回答让我意识到我可以按照我在回答中的方式做到这一点。所以,谢谢!
【解决方案2】:

在看到jlhoward's answer 之后,我能够想出这种方法,非常感谢他们!使用 jlhoward 的示例数据,这里是单行:

R> do.call(rbind, lapply(split(sp500[.indexmday(sp500) >= 15], "months"), first))
           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

解压:首先使用.indexmday 提取每月15 日或之后的所有日期。然后在该结果上调用 split 以创建所有单独月份的列表,并使用 lapplyfirst 提取该月 15 日之后的数据中的第一天。最后,使用do.callrbind 将所有内容重新组合在一起。

【讨论】:

  • 是的,这是一个更好的答案。
  • 是的,这样更好。 &gt;= 是我错过的聪明部分。
【解决方案3】:

我发现 bizdays 和 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")]

输出sn-p

           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

【讨论】:

    猜你喜欢
    • 2014-03-18
    • 2011-08-25
    • 2022-01-08
    • 2012-10-11
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 1970-01-01
    相关资源
    最近更新 更多