Home > Software engineering >  How to automate a function containing for loop to take inputs dynamically in r?
How to automate a function containing for loop to take inputs dynamically in r?

Time:09-09

I am trying to fetch data for some stocks using quantmod and it worked when I did for just 1 stock. But when I try to automate it for list of multiple Stock Symbols then I am not getting the results

Below Code works for getting just 1 Stock Symbol data by making it Static:

library(tidyverse)
library(quantmod)

# Creating Empty dataframe to collect final results
df_append <- setNames(data.frame(matrix(ncol = 8, nrow = 0)), 
                      c("Date", "Symbol", "Open","High","Low","Close","Volume","Adjusted"))

fetch_stock_data_fn <- function(){
  
  # Fetching Stock data for each symbol
  df_quant <- quantmod::getSymbols(Symbols = "SHREECEM.NS", src="yahoo",
                                   from = "2021-05-01",auto.assign = F) %>% 

  # converting time series to dataframe
              data.frame(as.matrix(.), Date=time(.), row.names = NULL) %>% 
    
  # Adding Symbol Column
              mutate(Symbol = "SHREECEM.NS",
                     Symbol = str_remove(Symbol, ".NS")) %>% 
              select(Date,Symbol,everything())

  # Removing String from Column Names
  for (col in 3: ncol(df_quant)){
    
      colnames(df_quant)[col] <- str_remove(colnames(df_quant)[col],"SHREECEM.NS.")
  }
  
  # Selecting Required columns only
  df_quant <- df_quant %>% 
              select(Date:Adjusted)
  
  # Append data to final dataframe
  df_append <- rbind(df_append,df_quant)
  
  return(df_append)
}

fetch_stock_data_fn()

Now when I try to modify this to accept stock symbol names for multiple symbols then I am not getting results. I think I am close to the solution but probably messing up with names in quotes while passing them as argument in the function call:

library(tidyverse)
library(quantmod)

# Creating Empty dataframe to collect final results
df_append <- setNames(data.frame(matrix(ncol = 8, nrow = 0)), 
                      c("Date", "Symbol", "Open","High","Low","Close","Volume","Adjusted"))

fetch_stock_data_fn <- function(stock_name){
  
  # Fetching Stock data for each symbol
  df_quant <- quantmod::getSymbols(Symbols = {{stock_name}}, src="yahoo",
                                   from = "2021-05-01",auto.assign = F) %>% 

  # converting time series to dataframe
              data.frame(as.matrix(.), Date=time(.), row.names = NULL) %>% 
    
  # Adding Symbol Column
              mutate(Symbol = {{stock_name}},
                     Symbol = str_remove(Symbol, ".NS")) %>% 
              select(Date,Symbol,everything()) 

  # Removing String from Column Names
  for (col in 3: ncol(df_quant)){
    
      colnames(df_quant)[col] <- str_remove(colnames(df_quant)[col],paste0({{stock_name}},"."))
  }
  
  # Selecting Required columns only
  df_quant <- df_quant %>% 
              select(Date:Adjusted)
  
  # Append data to final dataframe
  df_append <- rbind(df_append,df_quant)
  
  return(df_append)
}

Calling Function:

test_vector <- c("SHREECEM.NS","ADANIPORTS.NS")

for (vec_count in 1: length(test_vector)){
  
  # print(test_vector[vec_count])
  fetch_stock_data_fn(test_vector[vec_count])
}

CodePudding user response:

You could simplify your code a bit by using e.g. purrr::map_df to get rid of the rbind in your function and the for loop. Additionally I use rename_with to rename column names and finally there is IMHO no need for {{ as you are passing character strings:

library(tidyverse)
library(quantmod)

fetch_stock_data_fn <- function(stock_name) {
  # Fetching Stock data for each symbol
  df_quant <- quantmod::getSymbols(
    Symbols = stock_name, src = "yahoo",
    from = "2021-05-01", auto.assign = F
  )
  
  df_quant <- df_quant %>%
    # converting time series to dataframe
    data.frame(as.matrix(.), Date = time(.), row.names = NULL) %>%
    # Adding Symbol Column
    mutate(Symbol = str_remove(stock_name, ".NS")) %>%
    select(Date, Symbol, everything()) %>%
    # Removing String from Column Names
    rename_with(~ str_remove(.x, paste0(stock_name, "."))) %>%
    select(Date:Adjusted)

  return(df_quant)
}

test_vector <- c("SHREECEM.NS", "ADANIPORTS.NS")

df_append <- purrr::map_df(test_vector, fetch_stock_data_fn)

head(df_append)
#>         Date   Symbol     Open     High     Low    Close Volume Adjusted
#> 1 2021-05-03 SHREECEM 27500.00 28080.55 27327.6 27989.85  38741 27817.85
#> 2 2021-05-04 SHREECEM 28111.35 28111.50 27531.0 27753.30  41857 27582.75
#> 3 2021-05-05 SHREECEM 27850.00 28044.40 27713.3 27844.20  24250 27673.09
#> 4 2021-05-06 SHREECEM 27845.00 27946.25 27500.0 27736.20  33337 27565.75
#> 5 2021-05-07 SHREECEM 27847.00 27948.25 27700.0 27840.00  21548 27668.92
#> 6 2021-05-10 SHREECEM 27979.00 28035.15 27238.4 27309.95  49736 27142.12

count(df_append, Symbol)
#>       Symbol   n
#> 1 ADANIPORTS 338
#> 2   SHREECEM 338
  • Related