sfLapply & apply.rolling для объекта xts — результирующая ошибка: нижний индекс выходит за пределы

Моя цель - сопоставить ежедневную доходность 5 акций (объект xts) со скользящим стандартным отклонением периода ретроспективного анализа в 90 дней (вычисляя SD доходности за последние 90 дней) с той же структурой данных и с высокой скоростью. . Подход с использованием основной функции «lapply» отлично работает. Однако параллельный подход "sfLapply" в пакете snowfall по некоторым причинам не работал. Вот иллюстрация:

Инициализация библиотек и моделирование набора данных и параметров:

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)

Вычисление Rolling SD с использованием алгоритма lapply дает решение, которое работает:

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

Вот параллельная версия, которая не сработала:

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()

Приведенный выше код возвращает следующую ошибку:

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

Я не уверен, почему я получил эту ошибку, поскольку я даже не пишу свои собственные циклы for. Пожалуйста, укажите на любые возможные ошибки, любая мысль будет оценена и спасибо за помощь!

Окружающая среда: R:3.2.0/RStudio:0.99.472/снег:0.3-13/снегопад:1.84-6/xts:0.9-7/PerfomanceAnalytics:1.4.3541

P.S. Вместо apply.rolling можно было бы использовать runSD, применяется apply.rolling, так как он может работать с разными функциями.


person Anthony Lei    schedule 14.09.2015    source источник


Ответы (1)


Вот 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))

Функция splitList - это то, что терпит неудачу. Он терпит неудачу, потому что он ожидает список ("L" в sfLapply), но вы передали объект xts. length объекта xts — это количество наблюдений, а x[i] пытается вернуть i строку объекта xts, где i может быть nrow(x)*ncol(x), что выходит за пределы.


Решение состоит в том, чтобы вместо этого использовать sfApply (я собираюсь использовать runSD, потому что не хочу ждать, пока apply.rolling завершит работу).

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
person Joshua Ulrich    schedule 14.09.2015
comment
Спасибо, Джошуа, за то, что написали супербыструю функцию runSD и очень помогли! (Буду голосовать за пост, когда у меня будет больше разрешений!) - person Anthony Lei; 16.09.2015