Многократная регрессия (процедура Фама-Макбета) - PullRequest
0 голосов
/ 26 апреля 2020

Введение в проблему

Привет всем,

В настоящее время я делаю свою диссертацию, используя знаменитую процедуру Fama-Macbeth Rolling windows для оценки модели. со многими независимыми переменными и с несбалансированными данными панели. Сделаем сравнение с разными многофакторными моделями. Здесь я прошу полный (8 факторов), поскольку полный код будет использоваться в качестве справочного материала для моделей меньшего размера.

Проблема возникает именно здесь, так как многие учебники в Интернете имеют дело с непрерывной регрессией, но очень мало показать это в режиме множественной регрессии. Моих знаний в области кодирования пока недостаточно для постановки такой проблемы без достаточного количества ссылок на предыдущие примеры. Более того, если бы кто-то знал Python лучше, я также был бы очень признателен за Python версию этого кода.

Я исследовал много подобных проблем, но, за исключением одной, я не смог найти что-то правильно применимое. к моим данным. Кажется, что одним из самых быстрых способов было использование матричной алгебры или «rollRegres». Ну, версия «rollRegres» работала правильно до того момента, когда мои данные отображали пропущенные значения (пустые ячейки), автоматически преобразованные в «NA». Однако эти пропущенные данные отображают разные даты выпуска по разным ценным бумагам, что означает, что с этими недостающими ячейками не должно предприниматься никаких действий.

Поэтому, если кто-то знал, как ускорить этот код (в данном случае он далек от эффективности больших наборов данных), предложите что-нибудь еще или правильно покажите мне, как это сделать в матричной форме, я бы от всего сердца оценил.

Обобщение:

  • Скользящая регрессия (8 экз. + 1300 деп. Вар с окном 60 дней) - нужны бета-версии
    • Большой набор данных "Y" (1,300 деп. Вар с каждой из 1000 записей)
    • Набор данных "X" (8 независимых переменных - все с тысячами записей)
  • Любая возможность сделать его устойчивым (заменен lm () на rlm () библиотеки) МАССА безуспешно)
  • NA в наборе данных "Y" из-за разных дат выпуска (особенность данных)
  • Эффективность (проблемы со скоростью)
  • Вывод (проблемы с экспортом)

Код

Справедливый представитель родукция моего набора данных выглядит следующим образом. Имейте в виду, что исходный набор данных намного больше, и подобный код будет далек от эффективности.

###LIBRARIES
library(zoo)


###DATASET

set.seed(10000000)

df <- data.frame(

##Date
Date = seq(as.Date("2000/01/01"), by = "day", length.out = 5000),  

##Factors (indep var)
MKTRF = sample(1:100, 5000, replace=TRUE),
SMB = sample(1:100, 5000, replace=TRUE),
HML = sample(1:100, 5000, replace=TRUE),
RMW = sample(1:100, 5000, replace=TRUE),
CMA = sample(1:100, 5000, replace=TRUE),
MOM = sample(1:100, 5000, replace=TRUE),
TERM = sample(1:100, 5000, replace=TRUE),
DEF = sample(1:100, 5000, replace=TRUE),

##Securities (dep var)
#type 0
B1 = c(rep(NA, 1000), sample(1:100, 3000, replace=TRUE), rep(NA, 1000)),
B2 = c(rep(NA, 1500), sample(1:100, 3000, replace=TRUE), rep(NA, 500)),
B3 = c(sample(1:100, 3000, replace=TRUE), rep(NA, 2000)),
B4 = c(rep(NA, 1000), sample(1:100, 4000, replace=TRUE)),
B5 = c(sample(1:100, 5000, replace=TRUE)),

#type 1
GB1 = c(rep(NA, 1500), sample(1:100, 2000, replace=TRUE), rep(NA, 1500)),
GB2 = c(rep(NA, 1500), sample(1:100, 3000, replace=TRUE), rep(NA, 500)),
GB3 = c(sample(1:100, 3000, replace=TRUE), rep(NA, 2000)),
GB4 = c(rep(NA, 1000), sample(1:100, 4000, replace=TRUE)),
GB5 = c(sample(1:100, 5000, replace=TRUE)))


###REGRESSION

#Setting the problem
z <- read.zoo(df, FUN = as.yearmon, format = "%Y/%m/%d")
View(z)

getCoef <- function(z, lhs, rhs) {
  if (all(is.na(z[, lhs]))) "Empty"         #"Empty" is for me to spot empty cells due to different issue dates
  else coef(lm(paste(lhs, "~", rhs), z))
}

roll <- function(z, lhs, rhs = "MKTRF + SMB + HML + RMW + CMA + MOM + TERM + DEF") {
  rollapplyr(z, 60, getCoef, by.column = FALSE, coredata = FALSE, lhs = lhs, rhs = rhs)
}

ynames <- c("B1", "B2", "B3", "B4", "B5", "GB1", "GB2", "GB3", "GB4", "GB5")

#Regress
L <- lapply(ynames, roll, z = z)

#Save outputs
output <- Map(fortify.zoo, L)


Этот код из аналогичной проблемы, связанной со переполнением стека, работает, но показывает небольшую проблему. в выводе (станет ясно со скриншота - пирамидальные результаты в первых строках данных). Более того, это абсолютно не эффективно для длинных наборов данных. Наконец, я хотел бы экспортировать все бета-версии для каждой ценной бумаги в четкой и сжатой форме (в данном случае B1: GB5); теперь они остаются в списке «вывод»; желательно в таблице, чтобы открыть с примечаниями.

Если кто-то будет так любезен, чтобы предложить какой-либо тип улучшения, это действительно будет высоко ценится. Более того, я думаю, что это может остаться solid справкой для других, имеющих дело с таким типом регрессии.

Изображение - Pyramidal_outputs

Спасибо в авансовый!

1 Ответ

1 голос
/ 26 апреля 2020

Мы можем сделать несколько улучшений:

  • использовать матрицы X и Y
  • для каждого подмножества, мы можем регрессировать все столбцы Y одновременно, уменьшая количество обращений к регрессии функция на порядок
  • обрабатывает ошибки NA
  • с перекатом по индексу, а не по данным
  • используйте .lm.fit вместо lm
  • преобразовать результат в трехмерный массив

В результате получается следующий код.

library(zoo)

nr <- nrow(df)
X <- cbind(1, as.matrix(df[2:9]))
Y <- as.matrix(df[10:19])

coef_fun <- function(ix) {
  co <- try(coef(.lm.fit(X[ix, ], Y[ix, ])))
  if (inherits(co, "try-error")) NA else c(co)
}
out <- rollapplyr(1:nr, 60, coef_fun, fill = NA)

out <- array(out, c(nr, ncol(X), ncol(Y)), 
  dimnames = list(NULL, colnames(X), colnames(Y)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...