简体   繁体   中英

Can I create new xts columns from a list of names?

My objective: read data files from yahoo then perform calculations on each xts using lists to create the names of xts and the names of columns to assign results to.

Why? I want to perform the same calculations for a large number of xts datasets without having to retype separate lines to perform the same calculations on each dataset.

First, get the datasets for 2 ETFs:

library(quantmod)
# get ETF data sets for example
startDate = as.Date("2013-12-15") #Specify period of time we are interested in
endDate = as.Date("2013-12-31")
etfList <- c("IEF","SPY")
getSymbols(etfList, src = "yahoo", from = startDate, to = endDate)

To simplify coding, replace the ETF. prefix from yahoo data

colnames(IEF) <- gsub("SPY.","", colnames(SPY))
colnames(IEF) <- gsub("IEF.","", colnames(IEF))
head(IEF,2)
             Open   High    Low  Close Volume Adjusted
#2013-12-16 100.86 100.87 100.52 100.61 572400    98.36
#2013-12-17 100.60 100.93 100.60 100.93 694800    98.67

Creating new columns using the functions in quantmod is straightforward, eg,

SPY$logRtn <- periodReturn(Ad(SPY),period='daily',subset=NULL,type='log')
IEF$logRtn <- periodReturn(Ad(IEF),period='daily',subset=NULL,type='log')
head(IEF,2)
#              Open   High    Low  Close Volume Adjusted    logRtn
#2013-12-16 100.86 100.87 100.52 100.61 572400    98.36 0.0000000
#2013-12-17 100.60 100.93 100.60 100.93 694800    98.67 0.0031467

but rather that creating a new statement to perform the calculation for each ETF, I want to use a list instead. Here's the general idea:

etfList
#[1] "IEF" "SPY"
etfColName = "logRtn"

for (etfName in etfList) {
    newCol <- paste(etfName, etfColName, sep = "$"
    newcol <- periodReturn(Ad(etfName),period='daily',subset=NULL,type='log')
}

Of course, using strings (obviously) doesn't work, because

typeof(newCol) # is [1] "character"
typeof(logRtn) # is [1] "double"

I've tried everything I can think of (at least twice) to coerce the character string etfName$etfColName into an object that I can assign calculations to.

I've looked at many variations that work with data.frames, eg, mutate() from dplyr, but don't work on xts data files. I could convert datasets back/forth from xts to data.frames, but that's pretty kludgy (to say the least).

So, can anyone suggest an elegant and straightforward solution to this problem (ie, in somewhat less than 25 lines of code)?

I shall be so grateful that, when I make enough to buy my own NFL team, you will always have a place of honor in the owner's box.

This type of task is a lot easier if you store your data in a new environment. Then you can use eapply to loop over all the objects in the environment and apply a function to them.

library(quantmod)
etfList <- c("IEF","SPY")

# new environment to store data
etfEnv <- new.env()
# use env arg to make getSymbols load the data to the new environment
getSymbols(etfList, from="2013-12-15", to="2013-12-31", env=etfEnv)

# function containing stuff you want to do to each instrument
etfTransform <- function(x, ...) {
  # remove instrument name prefix from colnames
  colnames(x) <- gsub(".*\\.", "", colnames(x))
  # add return column
  x$logRtn <- periodReturn(Ad(x), ...)
  x
}
# use eapply to apply your function to each instrument
etfData <- eapply(etfEnv, etfTransform, period='daily', type='log')

(I didn't realize that you had posted a reproducible example.)

See if this is helpful:

 etfColName = "logRtn"
 for ( etfName in etfList ) {
     newCol <- get(etfName)[ ,  etfColName]
     assign(etfName, cbind( get(etfName), 
                            periodReturn( Ad(get(etfName)), 
                                          period='daily', 
                                         subset=NULL,type='log')))
                        }

> names(SPY)
[1] "SPY.Open"      "SPY.High"      "SPY.Low"       "SPY.Close"    
[5] "SPY.Volume"    "SPY.Adjusted"  "logRtn"        "daily.returns"

I'm not an quantmod user and it's only from the behavior I see that I believe the Ad function returns a named vector. (So I did not need to do any naming.)

R is not a macro language, which means you cannot just string together character values and expect them to get executed as though you had typed them at the command line. The get and assign functions allow you to 'pull' and 'push' items from the data object environment on the basis of character values, but you should not use the $ -function in conjunction with them.

I still do not see a connection between the creation of newCol and the actual new column that your code was attempting to create. They have different spellings so would have been different columns ... if I could have figured out what you were attempting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM