2

我正在使用吸墨纸包来运行回测,并使用 foreach 来加快速度。我遇到了一个错误,即即使它们应该在函数开始时被删除,blotter 也会找到具有相同名称的投资组合。这是重现错误的示例代码

require('foreach')
require('doSNOW')
require('xts')
require('blotter')

backtestFunction <- function() {

  currency("USD")
  stock("AAPL", currency="USD", multiplier=1)
  Sys.setenv(TZ="US/Eastern")
  verbose = FALSE

  try(rm("account.Snazzy","portfolio.Snazzy",pos=.blotter),silent=TRUE)
  initPortf("Snazzy", "AAPL", initDate="2014-01-01", currency="USD")
  initAcct("Snazzy", portfolios="Snazzy", initDate="2014-01-01", initEq=1000, currency="USD")

  return (TRUE)
}

cl <- snow::makeCluster(8, type = "SOCK")
registerDoSNOW(cl)

results <- foreach(i=1:100, .combine=rbind, .packages=c('xts','blotter')) %dopar% {
  return (backtestFunction())
}
snow::stopCluster(cl)

这是错误

Error in { : 
  task 9 failed - "Portfolio Snazzy already exists, use updatePortf() or addPortfInstr() to update it."

我了解投资组合和帐户对象存储在 .blotter 环境中,但是

  1. foreach 不会在新的 R 会话中生成每个工人,这样就不会有冲突吗?
  2. 为什么没有try(rm("account.Snazzy","portfolio.Snazzy",pos=.blotter),silent=TRUE)工作?
  3. 我怎样才能让 foreach 在这里使用吸墨纸?

如果重要的话,我使用的是 R 3.0.2,在 Windows 上运行 RStudio。我在标签中包含了 quantstrat,因为它们通常一起使用,因此有经验的 quantstrat 用户可能会知道修复方法。谢谢

4

1 回答 1

2

问题是“.blotter”被自动导出到工作人员,但到 doSNOW 的“导出”环境,而不是全局环境。这不会混淆吸墨纸包,但它确实会阻止您的“rm”命令从真实的“.blotter”环境中删除“account.Snazzy”和“portfolio.Snazzy”。

一种解决方案是添加.noexport=".blotter"到 foreach。另一种解决方案是在执行“rm”时更明确地指定环境:

try(rm("account.Snazzy","portfolio.Snazzy",pos=.GlobalEnv$.blotter),
    silent=TRUE)

doSNOW 不会为每个任务生成一个工人,因为这可能会很慢。即使对于本地工作人员,启动 R 会话的时间与执行任务的时间相比也可能很重要,尤其是在使用 ssh 的集群上。更重要的是,如果工作人员执行多个任务,您可以一次将大型数据集发送给他们,然后将这些数据重用于许多任务,从而分摊通信成本。

于 2014-03-12T19:25:54.437 回答