Search code examples
rloopsquantmod

Loop function & quantmod


Hy community, That's my code. It runs with no errors or warning. By the way if you look at x.df (final database) there something wrong at SMA & Bollinger bands columns. They are both "NA" filled. Then, BBands drops some columns after merge. What's wrong ?

library(quantmod) 
stockData <- new.env() #Make a new environment for quantmod to store data in
tickers <- c("AAPL","GOOG","YHOO","FB") # choose Symbols
start_date <- as.Date("2014-01-01") #Set start date
getSymbols(tickers, src="yahoo", env=stockData, from=start_date) # get data
x <- list() 

# loop on tickers
for (i in 1:length(tickers)) {
x[[i]] <- get(tickers[i], pos=stockData)   # get data from stockData environment  
colnames(x[[i]]) <- c("Open", "High", "Low", "Close","Volume", "Adjusted")  # rename Header for all tables in list
x[[i]]$gl <-((Cl(x[[i]])-Op(x[[i]]))/Op(x[[i]]))*100   # Daily gain loss percentage
SMA.n10 <- SMA(x[[i]][,4],n = 10)  # Calculate moving averages (MA) on "Close Price" <-column(4)
BBands<- BBands(x[[i]][,2:4])
x[[i]]$Symbol<- 0   # create "0" vector for Symbol name
x[[i]]$Symbol<- tickers[[i]]  # add Symbol name
x[[i]]<-data.frame(x[[i]],SMA.n10[[i]],BBands[[i]])  # merge data
}
x.df<- do.call(rbind, x) # call rbind to merge all xts objs in a single dataframe

Thanks

EDIT: My goal is to obtain a single dataframe (x.df) with the following columns:

"Open", "High", "Low","Close","Volume", "Adjusted", Symbol,"SMA10", "dn","mavg","up","pctB".

But if you run the code you can see NA values on SMA columns. ThentThere is no trace about "dn","mavg","up","pctB" ( Bollinger Bands values).


Solution

  • This corrects some mistakes in your code:

    x <- list() 
    
    # loop on tickers
    for (i in 1:length(tickers)) {
        x[[i]] <- get(tickers[i], pos=stockData)   # get data from stockData environment  
        colnames(x[[i]]) <- c("Open", "High", "Low", "Close","Volume", "Adjusted")  # rename Header for all tables in list
        x[[i]]$gl <-((Cl(x[[i]])-Op(x[[i]]))/Op(x[[i]]))*100   # Daily gain loss percentage
        SMA.n10 <- SMA(x[[i]][,4],n = 10)  # Calculate moving averages (MA) on "Close Price" <-column(4)
        BBands<- BBands(x[[i]][,2:4])
        x[[i]]$Symbol<- 0   # create "0" vector for Symbol name
        x[[i]]$Symbol<- tickers[i]  # add Symbol name
        x[[i]]<-data.frame(x[[i]], coredata(SMA.n10), coredata(BBands))  # merge data
    }
    x.df<- do.call(rbind, x) # call rbind to merge all xts objs in a single dataframe
    

    You should learn about the differences between subsetting vectors, lists, dataframes with [] and [[]]. I recommend this resource for learning more: http://adv-r.had.co.nz/Subsetting.html

    coredata(SMA.n10) returns the underlying matrix of values, which works as expected provided NROW(SMA.n10) == NROW(x[[i]]) while SMA.n10[[i]] returns NA, and with recycling rules in R will create a column of NA values in data.frame(.....), not what you expect.

    Something like this is a better way of arranging your data if you want to include a correct "time/date" column in x.df (using the row names of x.df to hold the times, as you do in your code, gives nonsensical values when you're binding data across symbols):

    x <- list() 
    
    # loop on tickers
    for (i in 1:length(tickers)) {
        tmp <- get(tickers[i], pos=stockData)   # get data from stockData environment  
        colnames(tmp) <- c("Open", "High", "Low", "Close","Volume", "Adjusted")  # rename Header for all tables in list
        tmp$gl <-((Cl(tmp)-Op(tmp))/Op(tmp))*100   # Daily gain loss percentage
        SMA.n10 <- SMA(tmp[,4],n = 10)  # Calculate moving averages (MA) on "Close Price" <-column(4)
        BBands<- BBands(tmp[,2:4])
        tmp <- merge(tmp, SMA.n10, BBands)
    
        x[[i]]<-data.frame("time" = index(tmp), coredata(tmp), "Symbol" = tickers[i])  # merge data
    
    }
    x.df<- do.call(rbind, x) # call rbind to merge all xts objs in a single dataframe