0

I have this example data, where I load some tickers

libs <- c('quantmod')
lapply(libs, require, character.only = T)
tickers<-c('T','AMD','AA','AMAT','BAC')
getSymbols(tickers,from="2013-01-01")

Then I created function like

FUNtest<-function (x,y){
  data<-x
  close<-data[,y]
  return(tail(close))
}

which works like for example

FUNtest(AMD,4)

and the result is tail of closing prices of AMD

           AMD.Close
2014-07-16      4.66
2014-07-17      4.57
2014-07-18      3.83
2014-07-21      3.78
2014-07-22      3.80
2014-07-23      3.76

But, for later usage, I need to be able to use function this way

FUNtest(tickers[2],4)

but it doesn't work. If I call

tickers[2]

it shows

> tickers[2]
[1] "AMD"

but it is not able to work in function. And advices how to fix it? Thanks

3 Answers 3

1

There's a big difference between

FUNtest(AMD,4)

and

FUNtest("AMD",4)

With the former, you are passing a name which points to an xts object. In the latter, you are simply passing a character string. This string is in no way directly connected to the object of the same name.

If you want a function that works if you pass a character or an xts object, you can do

FUNtest<-function (x,y){
  if(is(x, "xts")) {
      data <- x
  } else if (is(x, "character")) {
      data <- get(x)
  } else {
    stop(paste("invalid x class:", class(x)))
  }
  close <- data[,y]
  return(tail(close))
}

then both

FUNtest(AMD, 4)
FUNtest(tickers[2], 4)

will work.

But even better is not to use the behavior of quantmod where it adds variables to your global environment. This is the default that's being phased out because it encourages bad behavior. It's better to store them all in a list like

symb<-lapply(setNames(tickers, tickers), function(x) 
    getSymbols(x,from="2013-01-01",  auto.assign=F))

Then you can have symb$AMAT or symb[["AMAT"]] depending on how you want to extract the data. The latter form is more flexible because you can specify a variable with a particular value or you can perform an action to all the data.sets by lapply-ing over the list.

Sign up to request clarification or add additional context in comments.

Comments

1

You could try using get in the function.

get("AMD") finds AMD in the evaluation frame (or not) and returns the value attached to it.

> FUNtest<-function (x,y){
     data<-get(x)
     close<-data[,y]
     return(tail(close))
 }
> FUNtest(tickers[2], 4)
#            AMD.Close
# 2014-07-16      4.66
# 2014-07-17      4.57
# 2014-07-18      3.83
# 2014-07-21      3.78
# 2014-07-22      3.80
# 2014-07-23      3.76

Also, there isn't really a need to use return here. This function might be better for you

> f <- function(x, y){ x <- get(x); tail(x[, y], 3) }
## on the entire tickers vector, get column 4 and bind them
> do.call(cbind, lapply(tickers, f, y = 4))
#            T.Close AMD.Close AA.Close AMAT.Close BAC.Close
# 2014-07-16   36.45      4.66    16.60      22.85     15.51
# 2014-07-17   36.03      4.57    16.33      22.77     15.20
# 2014-07-18   36.17      3.83    16.49      23.00     15.49

eval can also be quite useful for unquoted arguments

> f <- function(x){ eval(x) }
> head(f(AMD), 3)
#            AMD.Open AMD.High AMD.Low AMD.Close AMD.Volume AMD.Adjusted
# 2013-01-02     2.55     2.57    2.45      2.53   27214800         2.53
# 2013-01-03     2.52     2.59    2.46      2.49   24966900         2.49
# 2013-01-04     2.51     2.59    2.49      2.59   22054200         2.59

Comments

0

In the first case you're passing a dataframe called AMD; in the second you're just passing a character value "AMD".

I'm guessing that the dataframe AMD is already loaded into your work space so that's why FUNtest works in the first case.

if you want the function to work try either passing the data frame you want to the function, or tell the function where to find the data frame you want.

3 Comments

“One way is via the deparse(substitute(x)) trick.” – that would give you tickers[2] here; not what OP wants.
Thanks, can you specifiy the format of usage? I am trying FUNtest(deparse(substitute(tickers[2])),4) and it still doesn't work
ah, whoops you're right Konrad. the get() function is the proper choice here, but it assumes that whatever tickers[2] is calling exists somewhere in the workspace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.