Cyber Student
Cyber Student

Reputation: 311

R: Whats the most efficient way to code this formula in R?

I am trying to figure out the most efficient way to code this formula in R. I can implement this using a loop. But thats not the most efficient.

Formula for the Efficiency Ratio Indicator :

ER = Direction / Volatility 
Direction = ABS (Close – Close[n])
Volatility = n ∑ (ABS(Close – Close[1])) 

volatility is the sum of the absolute value of the last n price changes (Close – Prior Close)

n = look back period.Example: n=10

R code:

library(quantmod)
getSymbols("SPY")
prices <- Ad(SPY)

ER <- function(prices, n=10)
{
   direction <- abs((prices - lag(prices,n)))
   volatility <- 
   efficiencyRatio <- direction/volatility
   return(efficiencyRatio)
}

I am looking for help to fill in "volatility" variable inside the ER function.

Thanks.

Upvotes: 0

Views: 112

Answers (2)

lmo
lmo

Reputation: 38510

I think you could calculate volatility as follows:

# silly example
y <- 1:10

volatility <- length(y) * sum(sapply(2:(length(y)), 
                                     function(i) abs(y[i]-y[i-1])))

You can break apart the function to see that sapply(2:10, function(i) abs(y[i]-y[i-1])) calculates 9 1s, which makes sense given the vector. Sum those up and multiple by the number of days.

If you want to extend this to a vector that is longer than n, to get a moving average, you can use

volatility <- function(y, n) {
                sapply((n+1):length(y), 
                  function(rollSpot) {
                     n * sum(sapply((rollSpot-(n-1)):rollSpot, 
                                    function(i) abs(y[i]-y[i-1])))
                  })
              }

The rollSpot variable indexes the moving average: how many periods are you looking back. The current implementation includes the current period and the previous n-1 periods. If you want to include the previous n periods, you can decrement (rollSpot-(n-1)):rollSpot to (rollSpot-n):(rollSpot-1).

Upvotes: 0

eipi10
eipi10

Reputation: 93851

You could use rollapply from the zoo package to apply your function in a rolling window of length n.

Below is an example using just the direction portion of your code. You can, of course, expand the direction function in the code below to include the rest of your calculations.

library(zoo)

roll.direction = function(dat, n) {

  # The function to apply
  direction = function(x) {
    abs(x[length(x)] - x[1])
  }

  # Apply the function to dat in a rolling window of length n
  rollapply(dat, width=n, FUN=direction)
}

Now run the function on your data:

roll.direction(as.numeric(prices[,1]), 10)

Upvotes: 1

Related Questions