user1234440
user1234440

Reputation: 23607

Apply function to xts object

I have let say a xts object (data) with following values...

           SPY.Adjusted     SMA
2012-08-02       136.64 137.115
2012-08-03       139.35 137.995
2012-08-06       139.62 139.485
2012-08-07       140.32 139.970
2012-08-08       140.49 140.405
2012-08-09       140.61 140.550
2012-08-10       140.84 140.725

I'm trying to use apply function to append to it the signals if some conditions are met... in this case when the close > SMA. My function:

signal<-function(x,y,z)
  {
    z$signals<-ifelse(x>y,1,0)
  }

and I try to...

apply(data,1,FUN=signal(data$SPY.Adjusted,data$SMA,data))

with returned error:

Error in match.fun(FUN) : 'signal(data$SPY.Adjusted, data$SMA, data)'
  is not a function, character or symbol

What is possibly going wrong? I passed in to it a function which reaches in to the data objected passed into it to create a new column if certain condition is met.

Upvotes: 2

Views: 3470

Answers (2)

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193687

@GSee's answer addresses your actual question, but I find this to be much more direct:

dat$signal = (dat[,1] > dat[,2]) + 0

The part (dat[,1] > dat[,2]) creates a vector of TRUE and FALSE, which, when you add "0" to it, converts it to 0 for FALSE and 1 for TRUE.

(dat, in this example, is the same as @GSee's dat.)

Of course, you can use this to also match more than one condition:

set.seed(1)
dat$SAMPLE = sample(as.vector(c(dat$SPY.Adjusted, dat$SMA)), nrow(dat))
dat$signal = (dat$SPY.Adjusted > dat$SMA & dat$SPY.Adjusted > dat$SAMPLE) + 0
tail(dat, 15)
#            SPY.Adjusted     SMA  SAMPLE signal
# 2011-12-09       124.07 122.421 125.990      0
# 2011-12-12       122.26 122.864 124.260      0
# 2011-12-13       121.11 123.159 128.350      0
# 2011-12-14       119.82 122.839 114.966      0
# 2011-12-15       120.26 122.565 128.490      0
# 2011-12-16       120.44 122.320 126.486      0
# 2011-12-19       119.15 121.812 128.598      0
# 2011-12-20       122.75 121.660 127.605      0
# 2011-12-21       122.99 121.485 119.150      1
# 2011-12-22       124.08 121.693 116.030      1
# 2011-12-23       125.19 121.805 104.870      1
# 2011-12-27       125.29 122.108 116.460      1
# 2011-12-28       123.64 122.361 126.127      0
# 2011-12-29       124.92 122.871 119.750      1
# 2011-12-30       124.31 123.276 104.110      1

Upvotes: 2

GSee
GSee

Reputation: 49830

When you call apply with MARGIN=1, it's like passing each row to FUN. Your function is already vectorized, so you don't need to use apply. However, your function does not return anything. Try this:

library(quantmod)
getSymbols("SPY", src='yahoo', from='2010-01-01', to='2012-01-01')
dat <- cbind(Ad(SPY), SMA=SMA(Ad(SPY)))
signal<-function(x,y,z)
{
     z$signals<-ifelse(x>y,1,0)
     z
}

tail(signal(dat[, 1], dat[, 2], dat))
#           SPY.Adjusted     SMA signals
#2011-12-22       124.08 121.693       1
#2011-12-23       125.19 121.805       1
#2011-12-27       125.29 122.108       1
#2011-12-28       123.64 122.361       1
#2011-12-29       124.92 122.871       1
#2011-12-30       124.31 123.276       1

Actually, I try to avoid ifelse in situations like these because it is slower than doing this

signal<-function(x,y,z)
{
  z$signals <- 0
  z$signals[x > y] <- 1
  z
}

Upvotes: 4

Related Questions