2015-09-14 3 views
1

Mon objectif est de cartographier le rendement journalier de 5 actions (un objet xts) en un écart-type glissant d'une période rétrospective de 90 jours (calcul de l'écart-type du retour des 90 derniers jours) avec la même structure de données et à vitesse rapide. L'approche en utilisant la fonction de base "lapply" fonctionne très bien. Cependant, l'approche parallèle "sfLapply" dans les paquets de neige n'a pas fonctionné pour certaines raisons. Voici illustration:sfLapply & apply.rolling sur un objet xts - Erreur résultante: indice hors limites

Initialiser bibliothèques et simuler un ensemble de données & paramètres:

require(PerformanceAnalytics) 
require(quantmod) 
require(snowfall) 

adjReturns <- replicate(5, rnorm(10000, mean = 0.01, sd = 0.008)) 
colnames(adjReturns) <- c('stock1','stock2','stock3','stock4','stock5') 
timeIndex <- seq.Date(as.Date("2015-01-01", "%Y-%m-%d"), by ="day", length.out = 10000) 
adjReturns <- as.xts(adjReturns, order.by = timeIndex) 

Calcul de roulement SD à l'aide résultant lapply une solution qui fonctionne:

rollingSD <- list() 
rollingSD <- lapply(adjReturns, function(x) apply.rolling(x, width = 90, FUN = "sd")) 
rollingSD <- do.call(cbind, rollingSD) 

est ici la version parallèle n'a pas fonctionné:

sfInit(parallel = TRUE, cpus = 4, type = "SOCK", socketHosts = rep("localhost", 2)) 
sfLibrary(snowfall) 
sfLibrary(PerformanceAnalytics) 
sfLibrary(xts) 
sfLibrary(quantmod) 
sfExportAll() 

rollingSDSnow <- list() 
rollingSDSnow <- sfLapply(adjReturns, function(x) apply.rolling(x, width = 90, FUN = "sd")) 
rollingSDSnow <- do.call(cbind, rollingSDSnow) 

sfStop() 

La morue e retour au-dessus de l'erreur suivante:

Error in `[.xts`(x, i) : subscript out of bounds 

Je ne sais pas pourquoi je recevrais cette erreur que je ne suis pas en train d'écrire même mon propre pour les boucles. S'il vous plaît signaler toutes les erreurs possibles, Toute pensée serait appréciée et merci d'aider!

Environnement: R: 3.2.0/rstudio: 0.99.472/neige: 0.3-13/neige: 1.84-6/XTS: 0.9-7/PerfomanceAnalytics: 1.4.3541

post-scriptum runSD aurait pu être utilisé à la place de apply.rolling, apply.rolling est utilisé car il peut fonctionner avec différentes fonctions.

Répondre

0

Voici le traceback:

> rollingSDSnow <- sfLapply(adjReturns, function(x) apply.rolling(x, 90, FUN = sd)) 
Error in `[.xts`(x, i) : subscript out of bounds 
> traceback() 
13: stop("subscript out of bounds") 
12: `[.xts`(x, i) 
11: x[i] 
10: FUN(X[[i]], ...) 
9: lapply(splitIndices(length(x), ncl), function(i) x[i]) 
8: splitList(x, length(cl)) 
7: staticClusterApply(cl, fun, length(x), argfun) 
6: clusterApply(cl, splitList(x, length(cl)), lapply, fun, ...) 
5: lapply(args, enquote) 
4: do.call("fun", lapply(args, enquote)) 
3: docall(c, clusterApply(cl, splitList(x, length(cl)), lapply, 
     fun, ...)) 
2: parLapply(sfGetCluster(), x, fun, ...) 
1: sfLapply(adjReturns, function(x) apply.rolling(x, 90, FUN = sd)) 

La fonction splitList est ce qui échoue. Il échoue car il attend une liste (le "L" dans sfLapply), mais vous avez passé un objet xts. Le length d'un objet xts est le nombre d'observations, et x[i] tente de retourner la i ème ligne d'un objet xts, où i pourrait être nrow(x)*ncol(x), ce qui est hors limites.


La solution est d'utiliser à la place sfApply (je vais utiliser runSD parce que je ne veux pas attendre apply.rolling pour terminer la course).

rollingSD <- list() 
rollingSD <- lapply(adjReturns, runSD, n=90) 
rollingSD <- do.call(cbind, rollingSD) 

sfInit(parallel = TRUE, cpus = 4, type = "SOCK", socketHosts = rep("localhost", 2)) 
sfLibrary(snowfall) 
sfLibrary(quantmod) 
sfExportAll() 
rollingSDSnow <- list() 
rollingSDSnow <- sfApply(adjReturns, 2, runSD, n=90) 
rollingSDSnow <- xts(rollingSDSnow, index(adjReturns)) 
sfStop() 

all.equal(rollingSDSnow, rollingSD) 
# [1] TRUE 
+0

Merci Joshua d'avoir écrit la fonction runSD super rapide et d'avoir été si utile! (Votera le poste quand j'ai plus de permissions!) – AnthonyLei