Выполнять скользящую регрессию только в указанные c даты - PullRequest
2 голосов
/ 04 апреля 2020

Я пытаюсь выполнить следующую скользящую регрессию: stock_return = α + β market_return.

Мой набор данных "data" выглядит следующим образом:

Company Date        stock_return    market_return       Alpha   Beta
AAPL    01.01.2014  3%              4%
…
AAPL    31.12.2019  5%              1%
MSFT    01.01.2014  2%              4%
…
MSFT    31.12.2019  6%              1%

Более того, у меня есть фрейм данных с событиями, при которых должна выполняться регрессия:

Company Date        
AAPL    05.02.2015
…   
MSFT    04.08.2018

Я использую пакет бегуна для скользящей регрессии:

running_regression <- function(z) {
  coef(lm(stock_return ~ market_return , data = as.data.frame(z)))
}

output <- runner(seq_along(data$market_return), 
                         k = 180, 
                         lag = 5,
                         at = ?
                         f = running_regression)

Однако я борюсь со своей функцией и с тем, что поставить в "at", чтобы просто выполнить регрессию для событий во втором кадре данных.

Пожалуйста, см. ниже минимальный пример:

    Date <- seq(from = as.Date("2014-01-01"), to = as.Date("2019-12-31"), by = 'day')
    Date <- format(Date, format="%d.%m.%Y")

    Company.name <- c(replicate(2191, ""))
    AAPL <- data.frame(Company.name = "AAPL",Date)
    market_return <- c(rnorm(2191))
    AAPL <- cbind(AAPL, market_return)
    MSFT <- c(replicate(2191, "MSFT"))
    MSFT <- data.frame(Company.name = "MSFT",Date)
    MSFT <- cbind(MSFT, market_return)
    df <- rbind(AAPL, MSFT)
    stock_return <- c(rnorm(4382))
    df <- cbind(df,stock_return)
    df[,"Alpha"] <- NA
    df[,"Beta"] <- NA

    Company.name2 <- c(replicate(450, "AAPL"),replicate(450, "MSFT"))
    Event_date <- sample(seq(as.Date('2015/01/01'), as.Date('2019/12/31'), by="day"), 900)
    Event_date <- format(Event_date, format="%d.%m.%Y")
    df2 <- data.frame(Company.name2, Event_date)

    #____

    running_regression <- function(z) {
      coef(lmList(stock_return ~ market_return | Company.name, data=z))
    }


runner(df$market_return, 
       k = 180, 
       lag = 5,
       f = running_regression)

Ответы [ 2 ]

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

Начиная с версии бегуна 0.3.5 вы можете указать x = df и выполнить регрессию на windows с data.frame. Поскольку вы мутируете df2, вы должны изменить соответствующую часть df на x = df[df$Company.name == Company.name2,] - вы должны сделать то же самое с idx.

running_regression_intercept <- function(x) {
  coef(lm(stock_return ~ market_return, data = x))[1]
}

running_regression_slope <- function(x) {
  coef(lm(stock_return ~ market_return, data = x))[2]
}
library(dplyr)
library(runner)
df2 %>%
  group_by(Company.name2) %>%
  mutate(
    intercept = runner(
      x = df[df$Company.name ==  Company.name2[1], ],
      k = "180 days",
      lag = "5 days",
      idx = df$Date[df$Company.name == Company.name2[1]],
      at = Event_date,
      f = running_regression_intercept,
    ),
    slope = runner(
      x = df[df$Company.name == Company.name2[1], ],
      k = "180 days",
      lag = "5 days",
      idx = df$Date[df$Company.name == Company.name2[1]],
      at = Event_date,
      f = running_regression_slope
    )
  )

# Company.name2 Event_date    alpha     beta
#     <fct>         <date>        <dbl>    <dbl>
#   1 AAPL          2017-01-12  0.0114   0.00488
#   2 AAPL          2017-07-31 -0.0654   0.00574
#   3 AAPL          2019-02-27 -0.0861   0.0310 
#   4 AAPL          2018-09-06  0.0405  -0.0630 
#   5 AAPL          2015-09-03 -0.121   -0.0246 
#   6 AAPL          2018-11-20 -0.0283  -0.0254 
#   7 AAPL          2015-07-03 -0.116   -0.0186 
#   8 AAPL          2015-02-03  0.102    0.0409 
#   9 AAPL          2017-03-16 -0.0157   0.0124 
#   10 AAPL          2019-06-08 -0.00302  0.0532 

Мне нужно было немного измените ваши данные, потому что формат Event.Date изменился с Date на character.

Date <- seq(from = as.Date("2014-01-01"), 
            to = as.Date("2019-12-31"), 
            by = 'day')
market_return <- c(rnorm(2191))

AAPL <- data.frame(
  Company.name = "AAPL", 
  Date =  Date,
  market_return = market_return
)

MSFT <- data.frame(
  Company.name = "MSFT", 
  Date = Date,
  market_return = market_return
)

df <- rbind(AAPL, MSFT)
df$stock_return <- c(rnorm(4382))
df <- df[order(df$Date),]

df2 <- data.frame(
  Company.name2 = c(replicate(450, "AAPL"), replicate(450, "MSFT")), 
  Event_date = sample(
    seq(as.Date('2015/01/01'), 
        as.Date('2019/12/31'), 
        by="day"),
    size =  900)
  )
0 голосов
/ 04 апреля 2020

Надеюсь, я вас правильно понял,

Если вы хотите запустить регрессию только в указанные c даты в df2, быстрое решение - объединить их, используя соответствующие имена:

head(merge(df2,df,by.x=c("Company.name2","Event_date"),by.y=c("Company.name","Date")))
  Company.name2 Event_date market_return stock_return Alpha Beta
1          AAPL 01.01.2016    -0.4814525   -0.9864268    NA   NA
2          AAPL 01.01.2019    -1.3093155    0.8357707    NA   NA
3          AAPL 01.02.2017     1.5059626   -1.3181592    NA   NA
4          AAPL 01.03.2015    -1.3226590    1.4786993    NA   NA
5          AAPL 01.03.2016     2.1394338   -0.8900286    NA   NA
6          AAPL 01.03.2019     0.6035526    0.5453212    NA   NA

Вы можете видеть, что даты испорчены, поэтому имеет смысл отсортировать ваш df2 по компании и дате:

df2 = df2[order(df2$Company.name2,
as.Date(as.character(df2$Event_date),format="%d.%m.%Y")),]

df_merged = merge(df2,df,
by.x=c("Company.name2","Event_date"),
by.y=c("Company.name","Date"),sort=FALSE)

Чтобы выполнить скользящую регрессию, вы можете использовать lmList здесь, но он получит немного сложнее. Ниже я использую roll_lm из roll для вычисления коэффициента. Не совсем понимаю ваше отставание, может быть, вы можете уточнить это, но нет способа сделать регрессию на бегуне:

library(roll)
result = by(df_merged,df_merged$Company.name2,function(z){
roll_lm(z$market_return,z$stock_return,180)})

tail(result$AAPL$coefficients)
       (Intercept)         x1
[445,] -0.07817682 0.10662762
[446,] -0.06440454 0.09257577
[447,] -0.07007445 0.09461642
[448,] -0.05917523 0.09582312
[449,] -0.05292590 0.10025369
[450,] -0.04930798 0.09911921
...