Question

START <- '2013-09-03'    
symbolList <- list("AAPL", "MSFT", "TSLA", "GOOG", "IBM")
for (ii in 1:length(symbolList))
  {
  getSymbols(paste(symbolList[ii]), src='yahoo', from=START)
  }

This will generate 5 xts objects, each with 6 columns. I want to create mergedData, but by referencing symbolList, and not the brute force way I am doing it below.

mergedData <- merge(AAPL[,6], MSFT[,6], TSLA[,6], GOOG[,6], IBM[,6])
colnames(mergedData) <- c("Apple", "Microsoft", "Tesla", "Google", "IBM")

How would I rewrite the last 2 lines above using a method that loops through symbolList? Also, I would bet the original list having quotes might be part of my problem, as the created xts's are AAPL, MSFT, etc w/out the quotes. How do I get around that?

Thanks!

Was it helpful?

Solution 2

You could write those last two lines using get (which converts symbol names to symbols), do.call (which applies a function to a list), and lapply (which creates a list from the results of a [different] function):

mergedData <- do.call(merge, lapply(symbolList, function(sym) {  get(sym)[,6] }) )
colnames(mergedData) <- c("Apple", "Microsoft", "Tesla", "Google", "IBM")

But you could also simplify your whole process considerably by using auto.assign=FALSE in getSymbols. (I've also changed symbolList from a list to a named vector, which is really all you need.):

library(quantmod)
START <- '2013-09-03'    
symbolList <- c(Apple="AAPL", Microsoft="MSFT", Tesla="TSLA", Google="GOOG", IBM="IBM")
dataList <- lapply(symbolList, function(sym) {
  setNames(getSymbols(sym, src='yahoo', from=START, auto.assign=FALSE)[,6], names(sym))
})
mergedData <- do.call(merge, dataList)

Or if you want really dense code:

mergedData <- do.call(merge, lapply(symbolList, function(sym) {
  setNames(getSymbols(sym, src='yahoo', from=START, auto.assign=FALSE)[,6], names(sym))
}))

Appendix - An explanation of the lapply call (in response to your comment)

In this line:

dataList <- lapply(symbolList, function(sym) {
  setNames(getSymbols(sym, src='yahoo', from=START, auto.assign=FALSE)[,6], names(sym))
})

I've passed two arguments to lapply: the vector symbolList (could have been a list) and a function function(sym) { ... }. I could have passed a pre-defined function -- for example, if I wanted to count the number of characters in each symbol, I could have passed in nchar:

lapply(symbolList, nchar)

and that would have been the same as calling

list(Apple=nchar(symbolList[[1]]), Microsoft=nchar(symbolList[[2]]), Tesla=nchar(symbolList[[3]]), Google=nchar(symbolList[[4]]), IBM=nchar(symbolList[[5]]))

where both return a list of the form

list(Apple=4, Microsoft=4, Tesla=4, Google=4, IBM=3)

But instead of using nchar, I wrote my own function. This function returns things I want in place of the 4, 4, 4, 4, and 3 in the nchar example. The function could be defined separately:

myfun <- function(sym) {
  setNames(getSymbols(sym, src='yahoo', from=START, auto.assign=FALSE)[,6], names(sym))
}

And we could then have passed myfun to lapply to get the result we want:

dataList <- lapply(symbolList, myfun)

In this case, rather than 4, 4, 4, 4, and 3, we get a list of xts objects. We also could have constructed that same list this way:

dataList2 <- list(Apple=myfun(symbolList[[1]]), Microsoft=myfun(symbolList[[2]]), Tesla=myfun(symbolList[[3]]), Google=myfun(symbolList[[4]]), IBM=myfun(symbolList[[5]]))

but of course the lapply version is cleaner and more flexible about the number and names of the list elements.

In practice, it's often a little clunky to first assign the function to some variable (myfun in this case) and then pass the function to lapply. So in my original answer I chose instead to define the function within the lapply call, without ever giving it a name. myfun and function(sym) { ... } are equivalent function objects. Given that information, I hope you can now understand (or even modify) the lapply call from my original answer, copied here:

dataList <- lapply(symbolList, function(sym) {
  setNames(getSymbols(sym, src='yahoo', from=START, auto.assign=FALSE)[,6], names(sym))
})

OTHER TIPS

Here's a solution that uses getSymbols with an environment:

# easier if this is a character vector instead of a list
symbolList <- c("AAPL", "MSFT", "TSLA", "GOOG", "IBM")
# corresponding vector of company names
symbolNames <- c("Apple", "Microsoft", "Tesla", "Google", "IBM")
e <- new.env()                             # new environment
getSymbols(symbolList, from=START, env=e)  # store symbols in 'e'
# eapply() loops over all objects in 'e' and applies the Ad() function
# objects in 'e' won't be in a known order, so we order by symbolList
# then we merge and set the column names to the company names
mergedData <- setNames(do.call(merge, eapply(e, Ad)[symbolList]), symbolNames)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top