Search code examples
rxts

Correctly apply lapply /apply to an xts object and apply lag.xts - return the results as an xts object


I have some xts data and I want to perform a calculation over each of the columns. Say I have some daily closing prices such as:

           TSLA.Close AMZN.Close MSFT.Close
2017-01-03     216.99     753.67      62.58
2017-01-04     226.99     757.18      62.30
2017-01-05     226.75     780.45      62.30
2017-01-06     229.01     795.99      62.84

I want to apply some function such that if todays close is higher than yesterdays then give a 1 else a 0 and store the results in a new xts object.

I have the following - which converts the xts object to a numeric - if I change apply to lapply I get a list.
However, I would like to just return an xts object similar to that of the daily_close xts object.

Data:

library(xts)
library(quantmod)

start_date <- "2017-01-01"
end_date <- "2020-01-01"
symbols = c("TSLA", "AMZN", "MSFT")

dataEnv <- new.env()
getSymbols(symbols, 
           from = start_date, 
           to = end_date, 
           #src = "yahoo", 
           #adjust = TRUE, 
           #env = dataEnv
           )

daily_close <- do.call(merge, lapply(symbols, function(x) Cl(get(x))))

# todays close greater than yesterdays close
x <- apply(daily_close, 2,  FUN = function(x) ifelse (x > lag.xts(x), 1, 0))

Solution

  • If we do [] while assigning, it will keep the original attributes

    x <- daily_close
    x[] <- apply(daily_close, 2, FUN = function(x) ifelse (x > lag.xts(x), 1, 0))
    str(x)
    #An ‘xts’ object on 2017-01-03/2019-12-31 containing:
    #  Data: num [1:754, 1:3] NA 1 0 1 1 0 0 0 1 0 ...
    # - attr(*, "dimnames")=List of 2
    #  ..$ : NULL
    #  ..$ : chr [1:3] "TSLA.Close" "AMZN.Close" "MSFT.Close"
    #  Indexed by objects of class: [Date] TZ: UTC
    #...
    

    The ifelse is not required

    x[] <- apply(daily_close, 2, FUN = function(x) +(x > lag.xts(x)))