[英]While loop in R quantstrat code - how to make it faster?
在quantstrat包中,我找到了applyRule函数缓慢的主要罪魁祸首之一,并想知道是否有更高效的写入while循环。 任何反馈都会有所帮助。 任何人都可以将这部分包装成并行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
}
加勒特的回答确实指出了关于R-SIG财务清单的最后一次重要讨论,其中讨论了相关问题。
quantstrat中的applyRules函数绝对是花费大部分时间的地方。
在这个问题中复制的while循环代码是applyRules执行的路径依赖部分。 我相信所有这些都在文档中有所涉及,但我将简要回顾一下后代。
我们在applyRules中构建一个降维索引,这样我们就不必观察每个时间戳并检查它。 我们只注意到可以合理地预期策略可以在订单簿上执行的特定时间点,或者可以合理地预期订单被填补的特定时间点。
这是依赖于状态和路径的代码。 在这种背景下,对“矢量化”的闲谈没有任何意义。 如果我需要知道市场的当前状态,订单和我的位置,如果我的订单可能会被其他规则以时间依赖的方式修改,我看不出这个代码是如何被矢量化的。
从计算机科学的角度来看,这是一台状态机。 我能想到的几乎所有语言的状态机通常都是以while循环编写的。 这不是真正可以谈判或改变的。
问题是否使用申请会有所帮助。 R中的apply语句实现为循环,所以不,它没有帮助。 即使是mclapply或foreach等并行应用也无济于事,因为这是代码中依赖于状态的部分。 在不考虑状态的情况下评估不同的时间点没有任何意义。 您将注意到,quantstrat的非状态相关部分尽可能地进行矢量化,并且占用的运行时间非常少。
John的评论建议删除ruleProc中的for循环。 for循环所做的就是检查此时与策略关联的每个规则。 该循环中唯一的计算密集型部分是do.call来调用规则函数。 for循环的其余部分只是为这些函数定位和匹配参数,而从代码分析中,根本不需要花费太多时间。 在这里使用并行应用也没有多大意义,因为规则函数以类型顺序应用,因此可以在新的条目指令之前应用取消或风险指令。 就像数学有一个操作顺序,或者银行有存款/取款处理订单一样,quantstrat有一个规则类型评估订单,如文档中所述。
为了加快执行速度,可以做四件事:
我可以向您保证,如果对信号生成功能稍加注意,大多数策略可以在每个符号每个核心每分钟的核心分钟上运行。 不建议在笔记本电脑上运行大型背景测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.