Подтвердить что ты не робот

R data.table для отстающей регрессии

таблица с данными (ее объект data.table), который выглядит следующим образом:

      date         stock_id logret
   1: 2011-01-01        1  0.001
   2: 2011-01-02        1  0.003
   3: 2011-01-03        1  0.005
   4: 2011-01-04        1  0.007
   5: 2011-01-05        1  0.009
   6: 2011-01-06        1  0.011
   7: 2011-01-01        2  0.013
   8: 2011-01-02        2  0.015
   9: 2011-01-03        2  0.017
  10: 2011-01-04        2  0.019
  11: 2011-01-05        2  0.021
  12: 2011-01-06        2  0.023
  13: 2011-01-01        3  0.025
  14: 2011-01-02        3  0.027
  15: 2011-01-03        3  0.029
  16: 2011-01-04        3  0.031
  17: 2011-01-05        3  0.033
  18: 2011-01-06        3  0.035

Вышеуказанное может быть создано как:

DT = data.table(
   date=rep(as.Date('2011-01-01')+0:5,3) , 
   stock_id=c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3),
  logret=seq(0.001, by=0.002, len=18));

setkeyv(DT,c('stock_id','date'))

Конечно, реальная таблица больше со многими дополнительными знаками и датами. Цель состоит в том, чтобы изменить эту таблицу данных таким образом, чтобы я мог выполнить регрессию всех log_returns с помощью соответствующих log_returns с отставанием в 1 день (или предшествующим торгуемым днем ​​в выходные дни).

Окончательные результаты будут выглядеть так:

      date         stock_id logret lagret
   1: 2011-01-01        1  0.001    NA
   2: 2011-01-02        1  0.003    0.001
   3: 2011-01-03        1  0.005    0.003
   ....
  16: 2011-01-04        3  0.031  0.029
  17: 2011-01-05        3  0.033  0.031
  18: 2011-01-06        3  0.035  0.033

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

4b9b3361

Ответ 1

Просто некоторые дополнительные примечания из-за комментария Alex. Причина, по которой вам трудно понять, что происходит здесь, заключается в том, что многое делается в одной строке. Поэтому всегда полезно сломать вещи.

Чего мы действительно хотим? Нам нужен новый столбец lagret, а синтаксис для добавления нового столбца в data.table следующий:

DT[, lagret := xxx]

где xxx должно быть заполнено тем, что вы хотите иметь в столбце lagret. Поэтому, если нам просто нужен новый столбец, который дает нам строки, мы могли бы просто вызвать

DT[, lagret := seq(from=1, to=nrow(DT))]

Здесь мы действительно хотим отстающее значение logret, но мы должны учитывать, что здесь много акций. Поэтому мы делаем самосоединение, т.е. Присоединяем data.table DT к себе столбцами stock_id и date, но поскольку мы хотим иметь предыдущее значение каждого запаса, мы используем date-1. Обратите внимание, что мы должны сначала установить ключи для такого соединения:

setkeyv(DT,c('stock_id','date'))
DT[list(stock_id,date-1)]
    stock_id       date logret
 1:        1 2010-12-31     NA
 2:        1 2011-01-01  0.001
 3:        1 2011-01-02  0.003
 4:        1 2011-01-03  0.005
 5:        1 2011-01-04  0.007
 6:        1 2011-01-05  0.009
...

Как вы можете видеть, теперь у нас есть то, что мы хотим. logret теперь отстает на один период. Но мы действительно хотим, чтобы это было в новом столбце lagret в DT, поэтому мы просто получаем этот столбец, вызывая [[3L]] (это означает, что ничего больше, чем получить третий столбец) и назовите этот новый столбец lagret

DT[,lagret:=DT[list(stock_id,date-1),logret][[3L]]]
          date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-04        1  0.007  0.005
 5: 2011-01-05        1  0.009  0.007
...

Это уже правильное решение. В этом простом случае нам не нужно roll=TRUE, потому что в датах нет пробелов. Однако в более реалистичном примере (как упоминалось выше, например, когда у нас есть выходные), могут быть пробелы. Поэтому сделайте такой реалистичный пример, просто удалив два дня в DT для первого запаса:

DT <- DT[-c(4, 5)]
setkeyv(DT,c('stock_id','date'))
DT[,lagret:=DT[list(stock_id,date-1),logret][[3L]]]
          date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-06        1  0.011     NA
 5: 2011-01-01        2  0.013     NA
...

Как вы можете видеть, проблема в том, что у нас нет значения 6 января. Поэтому мы используем roll=TRUE:

DT[,lagret:=DT[list(stock_id,date-1),logret,roll=TRUE][[3L]]]
          date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-06        1  0.011  0.005
 5: 2011-01-01        2  0.013     NA
...

Просто ознакомьтесь с документацией о том, как roll=TRUE работает точно. В двух словах: если он не может найти предыдущее значение (здесь logret для 5 января), он просто берет последний доступный (здесь с 3 января).

Ответ 2

Обновление:

В текущей версии версии data.table v1.9.5, shift() реализовано # 965, который принимает два типа в настоящий момент type = "lag" (по умолчанию) и type = "lead". Подробнее см. ?shift.

С этим мы можем просто сделать:

# type="lag" may be omitted, as it is the default.
require(data.table) ## 1.9.5+
DT[, lagret := shift(logret, 1L, type="lag"), by=stock_id]
#           date stock_id logret lagret
#  1: 2011-01-01        1  0.001     NA
#  2: 2011-01-02        1  0.003  0.001
#  3: 2011-01-03        1  0.005  0.003
#  4: 2011-01-04        1  0.007  0.005
#  5: 2011-01-05        1  0.009  0.007
#  6: 2011-01-06        1  0.011  0.009
#  7: 2011-01-01        2  0.013     NA
#  8: 2011-01-02        2  0.015  0.013
#  9: 2011-01-03        2  0.017  0.015
# 10: 2011-01-04        2  0.019  0.017
# 11: 2011-01-05        2  0.021  0.019
# 12: 2011-01-06        2  0.023  0.021
# 13: 2011-01-01        3  0.025     NA
# 14: 2011-01-02        3  0.027  0.025
# 15: 2011-01-03        3  0.029  0.027
# 16: 2011-01-04        3  0.031  0.029
# 17: 2011-01-05        3  0.033  0.031
# 18: 2011-01-06        3  0.035  0.033

Ответ 3

Благодаря совету Мэтью Доула я смог использовать следующее:

DT[,lagret:=DT[list(stock_id,date-1),logret,roll=TRUE][[3L]]]

Результаты:

             date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-04        1  0.007  0.005
 5: 2011-01-05        1  0.009  0.007
 6: 2011-01-06        1  0.011  0.009
 7: 2011-01-01        2  0.013     NA
 8: 2011-01-02        2  0.015  0.013
 9: 2011-01-03        2  0.017  0.015
10: 2011-01-04        2  0.019  0.017
11: 2011-01-05        2  0.021  0.019
12: 2011-01-06        2  0.023  0.021
13: 2011-01-01        3  0.025     NA
14: 2011-01-02        3  0.027  0.025
15: 2011-01-03        3  0.029  0.027
16: 2011-01-04        3  0.031  0.029
17: 2011-01-05        3  0.033  0.031
18: 2011-01-06        3  0.035  0.033