Reputation: 765
My data is currently an xts or zoo object of daily stock prices per row and each column is a different company.
library(quantmod)
getSymbols("AAPL;MSFT;YHOO")
closePrices <- merge(Cl(AAPL),Cl(MSFT),Cl(YHOO))
I am still new to R and need some assistance reproducing this Excel function. My first thought was to split the function into numerator and denominator, and then compute the index:
dailyDiff <- abs(diff(closePrices,1))
numerJ <- diff(closePrices,10)
denomJ <- as.xts(rollapply(dailyDiff,11, sum))
idx <- abs(numerJ/denomJ)
This was great because the values for each portion were accurate, but are aligned by incorrect dates for denomJ. For example, the tail of numerJ goes to 6/21/2012, while the tail of denomJ goes to 6/14/2012.
The output that I am looking for is:
Upvotes: 2
Views: 386
Reputation: 49830
You can use a combination of diff
and either runSum
or rollapplyr
#Get the data
library(quantmod)
getSymbols("AAPL")
I think this is what you're trying to do (note the use of the lag
argument to diff.xts
, and the n
argument to runSum
)
out <- diff(Cl(AAPL), lag=10) / runSum(abs(diff(Cl(AAPL))), n=11)
tail(out['/2012-06-21'])
# AAPL.Close
#2012-06-14 -0.1047297
#2012-06-15 0.2176938
#2012-06-18 0.3888185
#2012-06-19 0.4585821
#2012-06-20 0.2653782
#2012-06-21 0.1117371
Edit
Upon closer review of your question, I do not understand why rollapplyr
is not the answer you're looking for. If I take your code, exactly as is, except I change rollapply
to rollapplyr
, it looks to me like it's exactly the output you're looking for.
dailyDiff <- abs(diff(closePrices,1))
numerJ <- diff(closePrices,10)
denomJ <- as.xts(rollapplyr(dailyDiff,11, sum))
idx <- abs(numerJ/denomJ)
# AAPL.Close MSFT.Close YHOO.Close
#2012-06-14 0.1047297 0.03826531 0.06936416
#2012-06-15 0.2176938 0.35280899 0.25581395
#2012-06-18 0.3888185 0.33161954 0.31372549
#2012-06-19 0.4585821 0.47096774 0.34375000
#2012-06-20 0.2653782 0.32644628 0.23750000
#2012-06-21 0.1117371 0.18997912 0.10256410
Also, note that both numerJ
and denomJ
both end on the same date if you use rollapplyr
(which is the same as using rollapply
with align="right"
)
end(numerJ); end(denomJ)
#[1] "2012-07-20"
#[1] "2012-07-20"
Yahoo Bug
Maybe the problem you're seeing is the yahoo bug where sometimes -- for example, right now -- yahoo duplicates the last (chronologically speaking) row of data. If so, try deleting the duplicated row before attempting to use the data for your calculations.
tidx <- tail(index(closePrices), 2)
if(tidx[1] == tidx[2]) {
closePrices <- closePrices[-NROW(closePrices), ]
}
Upvotes: 2
Reputation: 856
It's hard to tell exactly what your problem is without exact data, but the problem appears to be with rollapply
. rollapply
will only apply the function to whole intervals unless the argument partial
is set to TRUE
. Consider the following example
require(zoo)
#make up some data
mat <- matrix(1:100,ncol=2)
colnames(mat) <- c("x1","x2")
dates <- seq.Date(from=as.Date("2010-01-01"),length.out=50,by="1 day")
zoo.obj <- zoo(mat,dates)
#apply the funcitons
numerJ <- diff(zoo.obj,10) #dates okay
denomJ <- rollapply(zoo.obj,11, sum,partial=TRUE) #right dates
denomJ2 <- rollapply(zoo.obj,11,sum) #wrong dates
index <- abs(numerJ/denomJ) #right dates
Upvotes: 2