R конвертирует почасовые данные в сутки до 0:00 вместо 23:00

Как вы устанавливаете 0:00 как конец дня вместо 23:00 в почасовых данных? У меня есть эта борьба при использовании period.apply или же to.period оба возвращающихся дня заканчиваются в 23:00. Вот пример:

x1 = xts(seq(as.POSIXct("2018-02-01 00:00:00"), as.POSIXct("2018-02-05 23:00:00"), by="hour"), x = rnorm(120))

Следующие функции показывают периоды, заканчивающиеся в 23:00

to.period(x1, OHLC = FALSE, drop.date = FALSE, period = "days")
x1[endpoints(x1, 'days')]

Итак, когда я собираю почасовые данные в ежедневные, у кого-то есть идея, как установить конец дня в 0:00?

2 ответа

Решение

Как уже было указано другим ответом здесь, to.period в дни вычисляет данные с метками времени между 00:00:00 и 23:59:59.9999999 в указанный день. поэтому 23:00:00 рассматривается как последняя отметка времени в ваших данных, а 00:00:00 соответствует значению на следующий день "bin".

Что вы можете сделать, это сдвинуть все временные метки назад на 1 час, использовать to.period получить ежедневные данные точек из часовых точек, а затем с помощью align.time чтобы выровнять метки времени правильно.

(В более общем смысле, to.period полезен для генерации данных типа OHLCV, и поэтому, если вы, скажем, генерируете, скажем, часовые бары из тиков, имеет смысл взглянуть на все тики между 23:00:00 и 23: 59: 59.99999 при создании бара. затем с 00:00:00 до 00:59:59.9999.... образуется следующий почасовой бар и т. д.)

Вот пример:

> tail(x1["2018-02-01"])
# [,1]
# 2018-02-01 18:00:00 -1.2760349
# 2018-02-01 19:00:00 -0.1496041
# 2018-02-01 20:00:00 -0.5989614
# 2018-02-01 21:00:00 -0.9691905
# 2018-02-01 22:00:00 -0.2519618
# 2018-02-01 23:00:00 -1.6081656

> head(x1["2018-02-02"])
# [,1]
# 2018-02-02 00:00:00 -0.3373271
# 2018-02-02 01:00:00  0.8312698
# 2018-02-02 02:00:00  0.9321747
# 2018-02-02 03:00:00  0.6719425
# 2018-02-02 04:00:00 -0.5597391
# 2018-02-02 05:00:00 -0.9810128

> head(x1["2018-02-03"])
# [,1]
# 2018-02-03 00:00:00  2.3746424
# 2018-02-03 01:00:00  0.8536594
# 2018-02-03 02:00:00 -0.2467268
# 2018-02-03 03:00:00 -0.1316978
# 2018-02-03 04:00:00  0.3079848
# 2018-02-03 05:00:00  0.2445634

x2 <- x1
.index(x2) <- .index(x1) - 3600

> tail(x2["2018-02-01"])
# [,1]
# 2018-02-01 18:00:00 -0.1496041
# 2018-02-01 19:00:00 -0.5989614
# 2018-02-01 20:00:00 -0.9691905
# 2018-02-01 21:00:00 -0.2519618
# 2018-02-01 22:00:00 -1.6081656
# 2018-02-01 23:00:00 -0.3373271

x.d2 <- to.period(x2, OHLC = FALSE, drop.date = FALSE, period = "days")

> x.d2
# [,1]
# 2018-01-31 23:00:00  0.12516594
# 2018-02-01 23:00:00 -0.33732710
# 2018-02-02 23:00:00  2.37464235
# 2018-02-03 23:00:00  0.51797747
# 2018-02-04 23:00:00  0.08955208
# 2018-02-05 22:00:00  0.33067734

x.d2 <- align.time(x.d2, n = 86400)

> x.d2
# [,1]
# 2018-02-01  0.12516594
# 2018-02-02 -0.33732710
# 2018-02-03  2.37464235
# 2018-02-04  0.51797747
# 2018-02-05  0.08955208
# 2018-02-06  0.33067734

Хотите убедить себя? Попробуйте что-то вроде этого:

x3 <- rbind(x1, xts(x = matrix(c(1,2), nrow = 2), order.by = as.POSIXct(c("2018-02-01 23:59:59.999", "2018-02-02 00:00:00"))))

x3["2018-02-01 23/2018-02-02 01"]
# [,1]
# 2018-02-01 23:00:00.000 -1.6081656
# 2018-02-01 23:59:59.999  1.0000000
# 2018-02-02 00:00:00.000 -0.3373271
# 2018-02-02 00:00:00.000  2.0000000
# 2018-02-02 01:00:00.000  0.8312698
x3.d <- to.period(x3, OHLC = FALSE, drop.date = FALSE, period = "days")


> x3.d <- align.time(x3.d, 86400)
> x3.d
[,1]
2018-02-02  1.00000000
2018-02-03 -0.09832625
2018-02-04 -0.65075506
2018-02-05 -0.09423664
2018-02-06  0.33067734

Обратите внимание, что значение 2 в 00:00:00 не сформировало последнее наблюдение дня за 2018-02-02 (00:00:00), которое прошло с 2018-02-01 с 00:00:00 до 2018-02-01 23:59:59,9999.

Конечно, если вы хотите, чтобы дневная метка времени была началом дня, а не концом дня, который будет 2018-02-01 в качестве начала бара для первой строки, в x3.d выше, вы можете перенести день назад на один. Вы можете сделать это относительно безопасно для большинства часовых поясов, когда ваши данные не включают даты выходных:

index(x3.d) = index(x3.d) - 86400

Я говорю относительно безопасно, потому что есть угловые случаи, когда есть временные сдвиги в часовом поясе. Например, будьте осторожны с экономией дневного света. Простое вычитание -86400 может быть проблемой при переходе с воскресенья на субботу в часовых поясах, где происходит переход на летнее время:

  #e.g. bad:  day light savings occurs on this weekend for US EST
  z <- xts(x = 9, order.by = as.POSIXct("2018-03-12", tz = "America/New_York"))
  > index(z) - 86400
  [1] "2018-03-10 23:00:00 EST"

т. е. временная метка отключается на один час, когда вам действительно нужна метка полуночи (00:00:00).

Вы можете обойти эту проблему, используя что-то более безопасное, как это:

  library(lubridate)

  # right
  > index(z) - days(1)
  [1] "2018-03-11 EST"

Я не думаю, что это возможно, потому что 00:00 это начало дня. Из руководства:

Эти конечные точки выровнены по времени POSIXct с нулевой секундой дня в начале и 59,9999-й секундой 59-й минуты 23-го часа последнего дня

Я думаю, что решение здесь состоит в том, чтобы использовать минуты вместо часов. Используя ваш пример:

x1 = xts(seq(as.POSIXct("2018-02-01 00:00:00"), as.POSIXct("2018-02-05 23:59:99"), by="min"), x = rnorm(7200))
to.period(x1, OHLC = FALSE, drop.date = FALSE, period = "day")
x1[endpoints(x1, 'day')]
Другие вопросы по тегам