2

I am trying to compute various technical indicators that will be used to predict the stock price movement of around 100 stocks. For example, I want to calculate the Average True Range (ATR) for each of the companies in my time series, which I am trying to do with the TTR package in R. However, the problem is that I can't figure out how to do it for each of the companies in my dataset. I have tried to use dplyr::group_by(company) which doesn't work.

data_ATR <- data_price %>%
  dplyr::group_by(company) %>%
  TTR::ATR(data_price[,c("PRICE HIGH", "PRICE LOW", "CLOSING PRICE")], n=14)

Any help would be greatly appreciated!

hellberg30
  • 33
  • 5

1 Answers1

1

We may use group_modify here

library(dplyr)
data_price %>%
  dplyr::group_by(company) %>%
  dplyr::group_modify(~ as.data.frame(TTR::ATR(.[,c("PRICE HIGH", 
     "PRICE LOW", "CLOSING PRICE")], n=14)))

Update

If there are NAs we may need to get the index of the first non-NA row among all the subset of columns

data_price %>%
  dplyr::group_by(company) %>%
  dplyr::group_modify(~ 
     {
      tmp <- .x[,c("PRICE HIGH", "PRICE LOW", "CLOSING PRICE")]
      i1 <- which(rowSums(!is.na(tmp)) == ncol(tmp))[1]
      tmp <- tmp[i1:nrow(tmp), ]
      
     
      tryCatch(as.data.frame(TTR::ATR(tmp, n= min(c(nrow(tmp)-1, 
         14)))), error = function(e) data.frame(tr = NA_real_))

     })

Using a reproducible example

library(TTR)
data(ttrc)
ttrc %>% 
 mutate(company = as.integer(gl(n(), 25, n()))) %>% 
 group_by(company) %>% 
 group_modify(~ as.data.frame(ATR(.[c("High", "Low", "Volume")], n = 14))) %>% 
ungroup
# A tibble: 5,550 × 5
   company       tr   atr trueHigh trueLow
     <int>    <dbl> <dbl>    <dbl>   <dbl>
 1       1      NA     NA       NA   NA   
 2       1 1870903.    NA  1870906    3.09
 3       1 3099503.    NA  3099506    3.08
 4       1 2274154.    NA  2274157    3.07
 5       1 2086755.    NA  2086758    3.08
 6       1 2166345.    NA  2166348    3.1 
 7       1 3441795.    NA  3441798    3.14
 8       1 7550745.    NA  7550748    3.2 
 9       1 4853309.    NA  4853312    3.22
10       1 5814822.    NA  5814825    3.28
# … with 5,540 more rows

data

data_price <- structure(list(company = c("1", "1", "1", "1", "1", "1", "1", 
"1", "1", "2", "2", "2", "2"), `PRICE HIGH` = c(NA, NA, NA, 2, 
3, 5, 10, 15, 12, NA, NA, NA, 2), `PRICE LOW` = c(NA, NA, 2, 
3, 4, 7, 11, 4, 5, NA, NA, 2, 3), `CLOSING PRICE` = c(NA, NA, 
5, 6, 9, 10, 15, 12, 15, NA, NA, 5, 6)), class = "data.frame", row.names = c(NA, 
-13L))
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Hi akrun, In my dataset, I have NA values in the beginning because some of the companies had not been listed on the stock exchange until later on. Therefore, it doesn't work because the series contains non-leading NAs. However, It worked perfectly when I filled the NA values for the companies that were listed later on. Is it possible to code so it calculates the ATR also for these companies but starting from when price information is available? Thank you very much. – hellberg30 Jun 07 '22 at 15:49
  • @hellberg30 do you want to start i.e. suppose a company values are `c(NA, NA, 2, 3)`, from 2 onwards? – akrun Jun 07 '22 at 15:50
  • Yes, I want to start whenever there is available price data. For example, when I have computed simple moving average I just did ``` data_MA <- data_test %>% mutate(MA5 = zoo::rollmeanr(`CLOSING PRICE`, 5, fill = NA)) ``` – hellberg30 Jun 07 '22 at 16:02
  • I get the error message: " Error: unexpected ']' in: " as.data.frame(TTR::ATR(tmp]" > }) Error: unexpected '}' in " }" Update: I solved the error, however, still the issue that the series contains non-leading NAs. – hellberg30 Jun 07 '22 at 16:40
  • @hellberg30 the reproducoible example works i.e. `ttrc %>% mutate(company = as.integer(gl(n(), 25, n()))) %>% group_by(company) %>% dplyr::group_modify(~ {tmp <- .x[,c("High", "Low", "Volume")]; i1 <- which(rowSums(!is.na(tmp)) == ncol(tmp))[1]; tmp <- tmp[i1:nrow(tmp), ]; as.data.frame(TTR::ATR(tmp, n=14))})` – akrun Jun 07 '22 at 16:44
  • Hm, it doesn't seem to work for me. I get the error message: Error in EMA(c(NA, 1.01, 1.85, 0.669999999999995, 1.68, 0.68, 0.669999999999995, : Series contains non-leading NAs I appreciate that you are trying to help :) – hellberg30 Jun 07 '22 at 16:50
  • @hellberg30 this could be a case where you have more number of NA's than the `n` mentioned. – akrun Jun 07 '22 at 16:53
  • @hellberg30 exmaple `structure(list(v1 = c(NA, NA, NA, 2, 3, 5, 10, 15, 12), v2 = c(NA, NA, 2, 3, 4, 7, 11, 4, 5), v3 = c(NA, NA, 5, 6, 9, 10, 15, 12, 15)), class = "data.frame", row.names = c(NA, -9L)); TTR::ATR(df1[4:nrow(df1), ], n = 15)# Error in EMA(c(`4` = NA, `5` = 2, `6` = 2, `7` = 0, `8` = 11, `9` = 7), : n = 15 is outside valid range: [1, 6]` whereas `TTR::ATR(df1[4:nrow(df1), ], n = 5)# tr atr trueHigh trueLow 4 NA NA NA NA 5 2 NA 6 4...` – akrun Jun 07 '22 at 16:54
  • @hellberg30 Do you want to skip those groups or specify `n = min(nrow(tmp), 14)` – akrun Jun 07 '22 at 16:54
  • @hellberg30 i guess the updated one should work even if you have all `NA` values for a particular group as I added `tryCatch` – akrun Jun 07 '22 at 17:08