2011-10-10 63 views
5

在quantstrat包中,我找到了applyRule函數緩慢的主要元兇之一,並想知道是否有更高效的編寫while循環。任何反饋都會有幫助。對於任何經驗包裝這部分並行R.雖然循環R量子代碼 - 如何使其更快?

作爲一個選項申請將工作,而不是?還是應該將這部分重新寫入新的函數,如ruleProc和nextIndex?我也在研究Rcpp,但這可能是一個streach。任何幫助和建設性的意見非常感謝?

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

我懷疑問題是固有的'while',但'while'內無論發生什麼情況。你的代碼似乎沒有做任何事情 - 沒有賦值或返回值。所以你必須運行這個,因爲'ruleProc'的副作用。如果其中一個副作用是你在其他地方賦值,我會從重構開始。根據我的經驗,在結果列表中使用'lapply'和'do.call'通常比使用'[<-''選擇性分配更快。 – Andrie

+0

如果您發佈了每個提供的每個基礎數據結構的玩具示例,那麼我認爲'for'可以是矢量化的。而且,像nextIndex和ruleProc這樣的函數也需要被顯示。只有在這之後,有人才能對「while」循環做出很好的評估。 – John

+0

好的,只是查找了這個代碼...嘗試先獲得ruleProc矢量化。事實上,如果'ruleProc'是這個代碼非常慢的例子,那麼你可以輕鬆地進行大幅加速,幾乎沒有任何想法。通過'ruleProc'並把所有的東西都從包含整個函數的巨大'for'循環中移出。很多。如果你不能自己做那部分,然後張貼它進行矢量化。但先行動吧。 – John

回答

7

加勒特的回答確實指向了R-SIG金融名單上最後一次討論相關問題的主要討論。

quantstrat中的applyRules函數絕對是大部分時間都花在哪裏的地方。

在此問題中複製的while循環代碼是applyRules執行的路徑依賴部分。我相信所有這些都包含在文檔中,但我將簡要回顧一下SO的後代。

我們構建內部applyRules降維的索引,這樣我們就不必遵守每一個時間戳和檢查。我們只注意策略可能合理預期在訂單簿上執行的具體時間點,或者可合理預期訂單被填充的時間點。

這是狀態依賴路徑依賴代碼。在這種情況下,閒談「矢量化」並沒有任何意義。如果我需要了解市場的當前狀態,訂單和我的位置,並且如果我的訂單可能會按照其他規則以時間依賴方式進行修改,那麼我不會看到如何將此代碼進行矢量化。

從計算機科學的角度來看,這是一臺狀態機。幾乎所有我能想到的語言中的狀態機通常寫成while循環。這不是真的談判或改變。

的問題詢問是否使用適用會有所幫助。 R中的應用語句被實現爲循環,所以不,它不會幫助。即使是並行應用,例如mclapply的foreach不能幫助,因爲這是代碼的狀態相關的部分內。評估不同的時間點而不考慮狀態沒有任何意義。您會注意到quantstrat的非狀態依賴部分在任何可能的情況下都是矢量化的,並且只佔運行時間的很少部分。

John發表的評論建議刪除中的for循環ruleProc。 for循環所做的就是在此時檢查與策略相關的每個規則。該循環中唯一的計算密集型部分是調用規則函數的do.call。 for循環的其餘部分僅僅是爲這些函數定位和匹配參數,而從代碼剖析來看,並不需要太多時間。在這裏使用並行應用也沒什麼意義,因爲規則函數按類型順序應用,因此可以在新條目指令之前應用取消或風險指令。就像數學有一個操作訂單一樣,或者銀行有一個存款/提款處理訂單,Quantstrat有一個規則類型評估訂單,如文檔中所述。

要加快執行速度,也有可以做的四個主要方面:

  1. 寫一個非路徑依賴的戰略:這是由代碼的支持,簡單的策略,可以模擬這種方式。在這個模型中,你會寫一個自定義規則函數,當你認爲你應該得到你的填充時直接調用addTxn。它可能是一個矢量化的功能,可以根據您的指標/信號進行操作,並且速度應該非常快。
  2. 預處理您的信號:如果狀態機需要評估訂單簿/規則/組合的狀態以查看它是否需要執行某些操作的位置較少,那麼速度增加幾乎與減少信號。這是大多數用戶忽視的領域,寫信號功能並不真正評估何時可能需要修改位置或訂單簿的操作。
  3. 顯式並行您的分析問題的部分:我一般寫顯式並行包裝分離出不同的參數評估或符號的評價,看到applyParameter使用的foreach一個例子
  4. 改寫狀態機內applyRules在C/C++:修補程序歡迎,但看到鏈接Garrett張貼的其他細節。

我可以向您保證,如果對信號生成函數採取一些小心的措施,大多數策略可以在每個核心每個符號每分鐘核心分鐘的時間內運行。不建議在筆記本電腦上運行大型備用測試。

編號:quantstrat - applyRules