在quantstrat包中,我找到了applyRule函数缓慢的主要罪魁祸首之一,并想知道是否有更高效的写入while循环。任何反馈都会有所帮助。任何人都可以将这部分包装成Parallel R.
作为一种选择,申请可以改为吗?或者我应该将此部分重新编写为新函数,例如ruleProc和nextIndex?我也在沉迷于Rcpp,但这可能是一个特殊的问题。非常感谢任何帮助和建设性的建议?
while (curIndex) {
timestamp = Dates[curIndex]
if (isTRUE(hold) & holdtill < timestamp) {
hold = FALSE
holdtill = NULL
}
types <- sort(factor(names(strategy$rules), levels = c("pre",
"risk", "order", "rebalance", "exit", "enter", "entry",
"post")))
for (type in types) {
switch(type, pre = {
if (length(strategy$rules[[type]]) >= 1) {
ruleProc(strategy$rules$pre, timestamp = timestamp,
path.dep = path.dep, mktdata = mktdata, portfolio = portfolio,
symbol = symbol, ruletype = type, mktinstr = mktinstr)
}
}, risk = {
if (length(strategy$rules$risk) >= 1) {
ruleProc(strategy$rules$risk, timestamp = timestamp,
path.dep = path.dep, mktdata = mktdata, portfolio = portfolio,
symbol = symbol, ruletype = type, mktinstr = mktinstr)
}
}, order = {
if (length(strategy$rules[[type]]) >= 1) {
ruleProc(strategy$rules[[type]], timestamp = timestamp,
path.dep = path.dep, mktdata = mktdata, portfolio = portfolio,
symbol = symbol, ruletype = type, mktinstr = mktinstr,)
} else {
if (isTRUE(path.dep)) {
timespan <- paste("::", timestamp, sep = "")
} else timespan = NULL
ruleOrderProc(portfolio = portfolio, symbol = symbol,
mktdata = mktdata, timespan = timespan)
}
}, rebalance = , exit = , enter = , entry = {
if (isTRUE(hold)) next()
if (type == "exit") {
if (getPosQty(Portfolio = portfolio, Symbol = symbol,
Date = timestamp) == 0) next()
}
if (length(strategy$rules[[type]]) >= 1) {
ruleProc(strategy$rules[[type]], timestamp = timestamp,
path.dep = path.dep, mktdata = mktdata, portfolio = portfolio,
symbol = symbol, ruletype = type, mktinstr = mktinstr)
}
if (isTRUE(path.dep) && length(getOrders(portfolio = portfolio,
symbol = symbol, status = "open", timespan = timestamp,
which.i = TRUE))) {
}
}, post = {
if (length(strategy$rules$post) >= 1) {
ruleProc(strategy$rules$post, timestamp = timestamp,
path.dep = path.dep, mktdata = mktdata, portfolio = portfolio,
symbol = symbol, ruletype = type, mktinstr = mktinstr)
}
})
}
if (isTRUE(path.dep))
curIndex <- nextIndex(curIndex)
else curIndex = FALSE
}
答案 0 :(得分:7)
Garrett的回答确实指出了关于R-SIG财务列表的最后一次重要讨论,其中讨论了相关问题。
quantstrat中的applyRules函数绝对是花费大部分时间的地方。
此问题中复制的while循环代码是applyRules执行的路径依赖部分。我相信所有这些都在文档中有所涉及,但我将简要回顾一下后代。
我们在applyRules中构建一个降维索引,这样我们就不必观察每个时间戳并检查它。我们只注意到可以合理地预期该策略会对订单执行的具体时间点,或者可能合理地预期订单将被填补的情况。
这是依赖于状态的和路径相关的代码。在这种背景下,对“矢量化”的闲谈没有任何意义。如果我需要知道市场的当前状态,订单和我的位置,如果我的订单可能会被其他规则以时间依赖的方式修改,我看不出这个代码是如何被矢量化的。
从计算机科学的角度来看,这是一台状态机。我能想到的几乎所有语言的状态机通常都是以while循环编写的。这不是真正可以谈判或改变的。
问题是否使用应用会有所帮助。 R中的apply语句实现为循环,所以不,它没有帮助。即使是并行应用,例如 mclapply 或 foreach 也无济于事,因为这是在代码的状态相关部分内。在不考虑状态的情况下评估不同的时间点没有任何意义。你会注意到quantstrat的非状态相关部分尽可能地被矢量化,并且占用了很少的运行时间。
John的评论建议删除 ruleProc 中的for循环。 for循环所做的就是检查此时与策略关联的每个规则。该循环中唯一的计算密集型部分是 do.call 来调用规则函数。 for循环的其余部分只是为这些函数定位和匹配参数,而从代码分析中,根本不需要花费太多时间。在这里使用并行应用也没有多大意义,因为规则函数以类型顺序应用,因此可以在新的条目指令之前应用取消或风险指令。就像数学有一个操作顺序,或者银行有存款/取款处理订单一样,quantstrat有一个规则类型评估订单,如文档中所示。
为了加快执行速度,可以做四件事:
我可以向您保证,如果对信号生成功能稍加注意,大多数策略可以在每个核心每个核心每分钟的核心分钟上运行。不建议在笔记本电脑上运行大型背景测试。