Reputation: 311
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
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
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