Sunday, July 19, 2009

David Varadi's RSI(2) alternative

Here's a quick R implementation of David Varadi's alternative to the RSI(2).  Michael Stokes over at the MarketSci blog has three great posts exploring this indicator:
  1. Varadi’s RSI(2) Alternative: The DV(2)
  2. RSI(2) vs. DV(2)
  3. Last Couple of Notes on DV(2)
Here's the R code:
 DV <- function(HLC, n=2, bounded=FALSE) {
  # "HLC" is an _xts_ object with "High", "Low", and "Close"
  # columns, in that order.
  # This is David Varadi's alternative to the RSI(2).  Calculations
  # taken from the marketsci blog --
  # Author of this implementation: Joshua Ulrich

  # Calculate each day's high/low mean
  hlMean <- rowMeans( HLC[,-3] )
  # Calculate the running Mean of the Close divided by the
  # high/low mean, then subtract 1.
  res <- runMean( HLC[,3] / hlMean, n ) - 1
  # If we want the bounded DV...
  if(bounded) {
    # Set the range to calculated the bounded DV
    rng <- 252:NROW(res)

    # Grab the index of the unbounded results, so we can convert
    # the bounded results back to an xts object.
    indx <- index(res)

    # A simple percent rank function hack
    pctRank <- function(x,i) match(x[i], sort(coredata(x[(i-251):i])))
    # Apply the percent rank function to the coredata of our results
    res <- sapply(rng, function(i) pctRank(res, i) / 252)

    # Convert the bounded results to xts
    res <- xts(c(rep(NA,251),res), indx)

  # Return results


Bear said...

hello josh,
If I want to sell the stock when the RSI retereat from the 90 or buy it when the RSI above 10 again how can I modify the code?

Joshua Ulrich said...

Hi Bear,

You need to use a lagged value of RSI in addition to the current value. The code below shows how to do it.

price <- .xts(20*cumprod(1+rnorm(50)/100),Sys.Date()-50:1)
rsi <- RSI(price,2)
rsiLag <- lag(rsi)
sig <- rep(0,50)
sig <- ifelse(rsiLag > 90 & rsi < 90, -1, sig)
sig <- ifelse(rsiLag < 10 & rsi > 10, 1, sig)

So sig will be '1' if yesterday's RSI (rsiLag) is less than 10 and today's RSI (rsi) is greater than 10.

Hope that helps,

Bear said...

Actually I am testing RSI(price,14), so the indicator may be under 20 or above 80 for a time and I use FOR loop instead of ifelse and lag but FOR is slow in R.

Is there any better solution?

Joshua Ulrich said...

The solution I posted above is better. You just have to change the "n" for the RSI function to "14" and the upper and lower bounds in the ifelse() statements to 80 and 20.

Unknown said...

Hello Joshua,
Is there a reason why the result is sometimes of typeof "list" instead of "doubles" ?

When I load my datas from 1970 with quantmod the result is typeof "list"; and when I start from 1980 the result is typeof "double".

Thank you.

Joshua Ulrich said...


The result should always be an xts object. I'm not sure how you're getting a "list", but the high / low data prior to 1980 is poor for most Yahoo data.