Acelerar o cálculo de WMA (Média Móvel Ponderada)
Estou tentando calcular a média móvel exponencial em barras de 15 dias, mas quero ver a "evolução" da EMA da barra de 15 dias em cada (final de) dia / barra. Então, isso significa que eu tenho barras de 15 dias. Quando novos dados são recebidos diariamente, eu gostaria de recalcular a EMA usando novas informações. Na verdade, tenho barras de 15 dias e, depois de cada dia, minha nova barra de 15 dias começa a crescer e cada nova barra que aparece é usada para o cálculo da EMA juntamente com as barras de 15 dias anteriores.
Digamos que iniciemos em 01/01/2012 (temos dados para cada dia do calendário deste exemplo), no final de 15/01/2012 temos a primeira barra completa de 15 dias. Após 4 barras completas de 15 dias concluídas em 01/03/2012, podemos começar a calcular a EMA de 4 barras (EMA (x, n = 4)). No final de 2012-03-02, usamos as informações que temos até o momento e calculamos a EMA em 02/03/2012, fingindo que o OHLC para 02/03/2012 é a barra de 15 dias em andamento. Então, pegamos as 4 barras completas e a barra em 02/03/2012 e calculamos a EMA (x, n = 4). Em seguida, aguardamos outro dia, ver o que aconteceu com a nova barra de 15 dias em andamento (consulte a função to.period.cumulative abaixo para obter detalhes) e calculamos o novo valor para a EMA ... E assim, pelos próximos 15 dias ... Consulte função EMA.cumulative abaixo para obter detalhes ...
Abaixo, por favor, encontre o que eu pude inventar até agora. O desempenho não é aceitável para mim e não posso torná-lo mais rápido com meu conhecimento limitado em R.
library(quantmod)
do.call.rbind <- function(lst) {
while(length(lst) > 1) {
idxlst <- seq(from=1, to=length(lst), by=2)
lst <- lapply(idxlst, function(i) {
if(i==length(lst)) { return(lst[[i]]) }
return(rbind(lst[[i]], lst[[i+1]]))
})
}
lst[[1]]
}
to.period.cumulative <- function(x, name=NULL, period="days", numPeriods=15) {
if(is.null(name))
name <- deparse(substitute(x))
cnames <- c("Open", "High", "Low", "Close")
if (has.Vo(x))
cnames <- c(cnames, "Volume")
cnames <- paste(name, cnames, sep=".")
if (quantmod:::is.OHLCV(x)) {
x <- OHLCV(x)
out <- do.call.rbind(
lapply(split(x, f=period, k=numPeriods),
function(x) cbind(rep(first(x[,1]), NROW(x[,1])),
cummax(x[,2]), cummin(x[,3]), x[,4], cumsum(x[,5]))))
} else if (quantmod:::is.OHLC(x)) {
x <- OHLC(x)
out <- do.call.rbind(
lapply(split(x, f=period, k=numPeriods),
function(x) cbind(rep(first(x[,1]), NROW(x[,1])),
cummax(x[,2]), cummin(x[,3]), x[,4])))
} else {
stop("Object does not have OHLC(V).")
}
colnames(out) <- cnames
return(out)
}
EMA.cumulative<-function(cumulativeBars, nEMA = 4, period="days", numPeriods=15) {
barsEndptCl <- Cl(cumulativeBars[endpoints(cumulativeBars, on=period, k=numPeriods)])
# TODO: This is sloooooooooooooooooow...
outEMA <- do.call.rbind(
lapply(split(Cl(cumulativeBars), period),
function(x) {
previousFullBars <- barsEndptCl[index(barsEndptCl) < last(index(x)), ]
if (NROW(previousFullBars) >= (nEMA - 1)) {
last(EMA(last(rbind(previousFullBars, x), n=(nEMA + 1)), n=nEMA))
} else {
xts(NA, order.by=index(x))
}
}))
colnames(outEMA) <- paste("EMA", nEMA, sep="")
return(outEMA)
}
getSymbols("SPY", from="2010-01-01")
SPY.cumulative <- to.period.cumulative(SPY, , name="SPY")
system.time(
SPY.EMA <- EMA.cumulative(SPY.cumulative)
)
No meu sistema, leva
user system elapsed
4.708 0.000 4.410
O tempo de execução aceitável seria inferior a um segundo ... É possível conseguir isso usando R pur
Esta publicação está vinculada aOtimizar o cálculo de médias móveis - é possível? onde não recebi respostas. Agora eu era capaz de criar um exemplo reproduzível com uma explicação mais detalhada do que eu quero acelerar. Espero que a pergunta faça mais sentido agor
Todas as idéias sobre como acelerar isso são muito apreciada