Search code examples
rxtsquantmod

Calling Lag in ifelse with different k based on some other column in another xts object


I lost ideas (with my limited R knowledge) how to tackle following "problem" in a performant (vectorized) way.

I would like to determine days when SPX closed up 3 or more days in a row and, at the same time, is not coming from a 50-day low. I programmed this for fixed look back for three days but do not know how to make it dynamic. Here is the code:

require(quantmod)
getSymbols(c("^GSPC"), adjust=TRUE, from="1990-01-01")
assign("SPX", GSPC, envir=.GlobalEnv)
names(SPX) <- c("SPX.Open", "SPX.High", "SPX.Low", "SPX.Close", "SPX.Volume",     "SPX.Adjusted")

SPX.ClCl.positive <- ifelse(ClCl(SPX) > 0, 1, 0)
SPX.ClCl.positive[is.na(SPX.ClCl.positive)] <- 0
numDaysPositive <- cumsum(SPX.ClCl.positive) - cummax(cumsum(SPX.ClCl.positive)*    (!SPX.ClCl.positive))
numDaysPositiveGreaterThan3 <- ifelse(numDaysPositive >= 3, 1, 0)

SPX.Lo.gt.50day.low <- ifelse(lag.xts(Lo(SPX), k=3) <= runMin(Lo(SPX), n=50), 1, 0)

What I would like be able to do is something like this:

SPX.Lo.gt.50day.low <- ifelse(lag.xts(Lo(SPX), k=numDaysPositive) <= runMin(Lo(SPX), n=50), 1, 0)

EDIT START

I would like to see, if we are up on SPX more than three days in a row (3, 4, 5,...) (kept in variable numDaysPositive) whether this rise came from 50-day low. I would like to look back 3, 4, 5,... days to see if on that particular date (3, 4, 5,...) days ago SPX made a 50-day low. The "logic" or assumption is, that for rallies from 50-day lows being up 3 or more days in a row is not uncommon, but, if we are up 3, 4, 5, ... days in a row and it did not start out of a 50-day low, then, this might be worth considering as one of the "evidences" market may stop or even drop for a while.

For now I am using lag.xts with k=3 in last ifelse but would like to use k=numDaysPositive (dynamic).

EDIT END

So, I would like that k in lag is dynamic based on value in numDaysPositive. I am sure this is easy if only one can see how... I am looking at this for the whole day now and nothing comes to mind.


Solution

  • The code below will allow you to see which series of cumulative up days began on (or near) a 50-day low.

    # load quantmod and pull dada
    library(quantmod)
    SPX <- getSymbols("^GSPC", from="1990-01-01", auto.assign=FALSE)
    names(SPX) <- gsub("GSPC","SPX",names(SPX))
    
    # up (TRUE) and down (FALSE) days
    b <- c(FALSE, ClCl(SPX)[-1] > 0)
    # run length of each stretch of up/down days
    x <- rle(as.vector(b))
    # use rle results to create a vector of zeros (down days) and n
    # where n is the number of consecutive up days
    y <- unlist(lapply(seq_along(x$value), function(i)
      rep(if(x$value[i]) x$lengths[i] else 0,x$lengths[i])))
    # 50-day low
    z <- runMin(Lo(SPX), 50) == Lo(SPX)
    # convert results to xts
    y <- xts(y, index(SPX))
    z <- xts(z, index(SPX))
    # look at results
    tail(merge(SPX,cumUpDays=y,z),50)