[英]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.