Làm cách nào để thay thế Quantstrat 'for loop' bằng mclapply [được song song hóa]?

Aug 16 2020

Tôi muốn song song hóa lượng tử. Mã của tôi không chính xác như thế này, nhưng điều này cho thấy vấn đề. Vấn đề mà tôi tin là .blotter env được khởi tạo thành địa chỉ bộ nhớ con trỏ và tôi không thể khởi tạo mảng / ma trận new.env ().

Những gì tôi muốn làm là thay thế vòng lặp for bằng một mclapply để tôi có thể chạy nhiều applyStrategies với các ngày / ký hiệu khác nhau (chỉ các ký hiệu khác nhau được hiển thị ở đây). Mục tiêu cuối cùng của tôi là một cụm beowulf (makeCluster) và dự định chạy chúng song song trong tối đa 252 ngày giao dịch (cửa sổ luân phiên) với các ký hiệu khác nhau cho mỗi lần lặp (nhưng tôi không cần tất cả những điều đó. Tôi chỉ đơn giản hỏi nếu có cách làm việc với việc gán danh mục đầu tư và đối tượng bộ nhớ .blotter tiếp theo theo cách mà tôi có thể sử dụng mclapply)

#Load quantstrat in your R environment.

rm(list = ls())

local()

library(quantstrat) 
library(parallel)

# The search command lists all attached packages.
search()

symbolstring1 <- c('QQQ','GOOG')
#symbolstring <- c('QQQ','GOOG')

#for(i in 1:length(symbolstring1))
  mlapply(symbolstring1, function(symbolstring)
{
  #local()
  #i=2
  #symbolstring=as.character(symbolstring1[i])
  
  .blotter <- new.env()
  .strategy <- new.env()
  
  try(rm.strat(strategyName),silent=TRUE)
  try(rm(envir=FinancialInstrument:::.instrument),silent=TRUE)
  for (name in ls(FinancialInstrument:::.instrument)){rm_instruments(name,keep.currencies = FALSE)}
  print(symbolstring)

currency('USD')

stock(symbolstring,currency='USD',multiplier=1)

# Currency and trading instrument objects stored in the 
# .instrument environment

print("FI")
ls(envir=FinancialInstrument:::.instrument)

# blotter functions used for instrument initialization 
# quantstrat creates a private storage area called .strategy

ls(all=T)

# The initDate should be lower than the startDate. The initDate will be used later while initializing the strategy.

initDate <- '2010-01-01'

startDate <- '2011-01-01'

endDate <- '2019-08-10'

init_equity <- 50000

# Set UTC TIME

Sys.setenv(TZ="UTC")

getSymbols(symbolstring,from=startDate,to=endDate,adjust=TRUE,src='yahoo')

# Define names for portfolio, account and strategy. 

#portfolioName <- accountName <- strategyName <- "FirstPortfolio"
portfolioName <- accountName <- strategyName <- paste0("FirstPortfolio",symbolstring)

print(portfolioName)
# The function rm.strat removes any strategy, portfolio, account, or order book object with the given name. This is important

#rm.strat(strategyName)

print("port")
initPortf(name = portfolioName,
          symbols = symbolstring,
          initDate = initDate)

initAcct(name = accountName,
         portfolios = portfolioName,
         initDate = initDate,
         initEq = init_equity)

initOrders(portfolio = portfolioName,
           symbols = symbolstring,
           initDate = initDate)



# name: the string name of the strategy

# assets: optional list of assets to apply the strategy to.  

# Normally these are defined in the portfolio object

# contstrains: optional portfolio constraints

# store: can be True or False. If True store the strategy in the environment. Default is False
print("strat")
strategy(strategyName, store = TRUE)

ls(all=T)

# .blotter holds the portfolio and account object 

ls(.blotter)

# .strategy holds the orderbook and strategy object

print(ls(.strategy))

print("ind")
add.indicator(strategy = strategyName, 
              name = "EMA", 
              arguments = list(x = quote(Cl(mktdata)), 
                               n = 10), label = "nFast")

add.indicator(strategy = strategyName, 
              name = "EMA", 
              arguments = list(x = quote(Cl(mktdata)), 
                               n = 30), 
              label = "nSlow")

# Add long signal when the fast EMA crosses over slow EMA.

print("sig")
add.signal(strategy = strategyName,
           name="sigCrossover",
           arguments = list(columns = c("nFast", "nSlow"),
                            relationship = "gte"),
           label = "longSignal")

# Add short signal when the fast EMA goes below slow EMA.

add.signal(strategy = strategyName, 
           name = "sigCrossover",
           arguments = list(columns = c("nFast", "nSlow"),
                            relationship = "lt"),
           label = "shortSignal")

# go long when 10-period EMA (nFast) >= 30-period EMA (nSlow)

print("rul")
add.rule(strategyName,
         name= "ruleSignal",
         arguments=list(sigcol="longSignal",
                        sigval=TRUE,
                        orderqty=100,
                        ordertype="market",
                        orderside="long",
                        replace = TRUE, 
                        TxnFees = -10),
         type="enter",
         label="EnterLong") 

# go short when 10-period EMA (nFast) < 30-period EMA (nSlow)

add.rule(strategyName, 
         name = "ruleSignal", 
         arguments = list(sigcol = "shortSignal", 
                          sigval = TRUE, 
                          orderside = "short", 
                          ordertype = "market", 
                          orderqty = -100, 
                          TxnFees = -10,                     
                          replace = TRUE), 
         type = "enter", 
         label = "EnterShort")

# Close long positions when the shortSignal column is True

add.rule(strategyName, 
         name = "ruleSignal", 
         arguments = list(sigcol = "shortSignal", 
                          sigval = TRUE, 
                          orderside = "long", 
                          ordertype = "market", 
                          orderqty = "all", 
                          TxnFees = -10, 
                          replace = TRUE), 
         type = "exit", 
         label = "ExitLong")

# Close Short positions when the longSignal column is True

add.rule(strategyName, 
         name = "ruleSignal", 
         arguments = list(sigcol = "longSignal", 
                          sigval = TRUE, 
                          orderside = "short", 
                          ordertype = "market", 
                          orderqty = "all", 
                          TxnFees = -10, 
                          replace = TRUE), 
         type = "exit", 
         label = "ExitShort")

print("summary")
summary(getStrategy(strategyName))

# Summary results are produced below

print("results")
results <- applyStrategy(strategy= strategyName, portfolios = portfolioName,symbols=symbolstring)

# The applyStrategy() outputs all transactions(from the oldest to recent transactions)that the strategy sends. The first few rows of the applyStrategy() output are shown below

getTxns(Portfolio=portfolioName, Symbol=symbolstring)

mktdata

updatePortf(portfolioName)

dateRange <- time(getPortfolio(portfolioName)$summary)[-1] updateAcct(portfolioName,dateRange) updateEndEq(accountName) print(plot(tail(getAccount(portfolioName)$summary$End.Eq,-1), main = "Portfolio Equity"))

#cleanup
for (name in symbolstring) rm(list = name)
#rm(.blotter)
rm(.stoploss)
rm(.txnfees)
#rm(.strategy)
rm(symbols)

}
)

Nhưng một lỗi được đưa ra Lỗi trong get (biểu tượng, envir = envir): không tìm thấy đối tượng 'QQQ'

Cụ thể, vấn đề là công cụ FinancialInticment :::. Đang trỏ đến một địa chỉ bộ nhớ không được cập nhật với các lệnh gọi biến đóng gói của tôi (chuỗi biểu tượng)

Trả lời

3 BrianG.Peterson Aug 17 2020 at 20:37

apply.paramsettrong quantstratđã sử dụng một foreachcấu trúc để song song hóa việc thực thi applyStrategy.

apply.paramset cần phải thực hiện một lượng công việc hợp lý để đảm bảo rằng các môi trường có sẵn cho người lao động để thực hiện công việc và thu thập các kết quả thích hợp để gửi họ trở lại quy trình kêu gọi.

Điều đơn giản nhất để bạn có thể làm là sử dụng apply.paramset. Tạo các thông số ngày tháng và ký hiệu của bạn và để chức năng chạy bình thường.

Ngoài ra, tôi khuyên bạn nên xem các bước cần thiết để sử dụng foreachcấu trúc song song apply.paramsetđể sửa đổi nó cho phù hợp với trường hợp bạn đề xuất.

Cũng lưu ý rằng câu hỏi của bạn hỏi về việc sử dụng cụm Beowulf và mclapply. Điều này sẽ không hoạt động. mclapplychỉ hoạt động trong một không gian bộ nhớ duy nhất. Các cụm Beowulf thường không chia sẻ một bộ nhớ và không gian xử lý. Họ thường phân phối công việc thông qua các thư viện song song như MPI. apply.paramsetđã có thể phân phối trên một cụm Beowulf bằng cách sử dụng chương trình doMPIphụ trợ cho foreach. Đó là một trong những lý do chúng tôi sử dụng foreach: vô số các phụ trợ song song khác nhau có sẵn. Phần doMCphụ trợ foreachthực sự sử dụng mclapplyđằng sau hậu trường.

1 thistleknot Aug 19 2020 at 20:43

Tôi tin rằng điều này song song với mã. Tôi đã hoán đổi các chỉ báo cũng như các ký hiệu, nhưng logic của việc sử dụng các ký hiệu và ngày tháng khác nhau là ở đó

Về cơ bản tôi đã thêm

Dates=paste0(startDate,"::",endDate)

rm(list = ls())

library(lubridate)
library(parallel)

autoregressor1  = function(x){
  if(NROW(x)<12){ result = NA} else{
    y = Vo(x)*Ad(x)
    #y = ROC(Ad(x))
    y = ROC(y)
    y = na.omit(y)
    step1 = ar.yw(y)
    step2 = predict(step1,newdata=y,n.ahead=1)
    step3 = step2$pred[1]+1 step4 = (step3*last(Ad(x))) - last(Ad(x)) result = step4 } return(result) } autoregressor = function(x){ ans = rollapply(x,26,FUN = autoregressor1,by.column=FALSE) return (ans)} ########################indicators############################# library(quantstrat) library(future.apply) library(scorecard) reset_quantstrat <- function() { if (! exists(".strategy")) .strategy <<- new.env(parent = .GlobalEnv) if (! exists(".blotter")) .blotter <<- new.env(parent = .GlobalEnv) if (! exists(".audit")) .audit <<- new.env(parent = .GlobalEnv) suppressWarnings(rm(list = ls(.strategy), pos = .strategy)) suppressWarnings(rm(list = ls(.blotter), pos = .blotter)) suppressWarnings(rm(list = ls(.audit), pos = .audit)) FinancialInstrument::currency("USD") } reset_quantstrat() initDate <- '2010-01-01' endDate <- as.Date(Sys.Date()) startDate <- endDate %m-% years(3) symbolstring1 <- c('SSO','GOLD') getSymbols(symbolstring1,from=startDate,to=endDate,adjust=TRUE,src='yahoo') #symbolstring1 <- c('SP500TR','GOOG') .orderqty <- 1 .txnfees <- 0 #random <- sample(1:2, 2, replace=FALSE) random <- (1:2) equity <- lapply(random, function(x) {#x=1 try(rm("account.Snazzy","portfolio.Snazzy",pos=.GlobalEnv$.blotter),silent=TRUE)
  rm(.blotter)
  rm(.strategy)
  portfolioName <- accountName <- strategyName <- paste0("FirstPortfolio",x+2)
  #endDate <- as.Date(Sys.Date())
  startDate <- endDate %m-% years(1+x)
 
  #Load quantstrat in your R environment.
  reset_quantstrat()
  
  # The search command lists all attached packages.
  search()

  symbolstring=as.character(symbolstring1[x])
  print(symbolstring)
  
  try(rm.strat(strategyName),silent=TRUE)
  try(rm(envir=FinancialInstrument:::.instrument),silent=TRUE)
  for (name in ls(FinancialInstrument:::.instrument)){rm_instruments(name,keep.currencies = FALSE)}
  print(symbolstring)
  
  currency('USD')
  
  stock(symbolstring,currency='USD',multiplier=1)
  
  # Currency and trading instrument objects stored in the 
  # .instrument environment
  
  print("FI")
  ls(envir=FinancialInstrument:::.instrument)
  
  # blotter functions used for instrument initialization 
  # quantstrat creates a private storage area called .strategy
  
  ls(all=T)
  
  init_equity <- 10000
  
  Sys.setenv(TZ="UTC")
  
  print(portfolioName)
 
  print("port")

  try(initPortf(name = portfolioName,
            symbols = symbolstring,
            initDate = initDate))
  
 
  try(initAcct(name = accountName,
           portfolios = portfolioName,
           initDate = initDate,
           initEq = init_equity))
  
  try(initOrders(portfolio = portfolioName,
             symbols = symbolstring,
             initDate = initDate))
  
  # name: the string name of the strategy
  
  # assets: optional list of assets to apply the strategy to.  
  
  # Normally these are defined in the portfolio object
  
  # contstrains: optional portfolio constraints
  
  # store: can be True or False. If True store the strategy in the environment. Default is False
  print("strat")
  strategy(strategyName, store = TRUE)
  
  ls(all=T)
  
  # .blotter holds the portfolio and account object 
  
  ls(.blotter)
  
  # .strategy holds the orderbook and strategy object
  
  print(ls(.strategy))
  
  print("ind")
  #ARIMA
    
    add.indicator(
      strategy  =   strategyName, 
      name      =   "autoregressor", 
      arguments =   list(
        x       =   quote(mktdata)),
      label     =   "arspread")
    
    ################################################ Signals #############################
    
    add.signal(
      strategy          = strategyName,
      name              = "sigThreshold",
      arguments         = list(
        threshold       = 0.25,
        column          = "arspread",
        relationship    = "gte",
        cross           = TRUE),
      label             = "Selltime")
    
    add.signal(
      strategy          = strategyName,
      name              = "sigThreshold",
      arguments         = list(
        threshold       = 0.1,
        column          = "arspread",
        relationship    = "lt",
        cross           = TRUE),
      label             = "cashtime")
    
    add.signal(
      strategy          = strategyName,
      name              = "sigThreshold",
      arguments         = list(
        threshold       = -0.1,
        column          = "arspread",
        relationship    = "gt",
        cross           = TRUE),
      label             = "cashtime")
    
    add.signal(
      strategy          = strategyName,
      name              = "sigThreshold",
      arguments         = list(
        threshold       = -0.25,
        column          = "arspread",
        relationship    = "lte",
        cross           = TRUE),
      label             = "Buytime")
    
    ######################################## Rules #################################################
    
    #Entry Rule Long
    add.rule(strategyName,
             name               =   "ruleSignal",
             arguments          =   list(
               sigcol           =   "Buytime",
               sigval           =   TRUE,
               orderqty     =   .orderqty,
               ordertype        =   "market",
               orderside        =   "long",
               pricemethod      =   "market",
               replace          =   TRUE,
               TxnFees              =   -.txnfees
               #,
               #osFUN               =   osMaxPos
             ), 
             type               =   "enter",
             path.dep           =   TRUE,
             label              =   "Entry")
    
    #Entry Rule Short
    
    add.rule(strategyName,
             name           =   "ruleSignal",
             arguments          =   list(
               sigcol           =   "Selltime",
               sigval           =   TRUE,
               orderqty     =   .orderqty,
               ordertype        =   "market",
               orderside        =   "short",
               pricemethod      =   "market",
               replace          =   TRUE,
               TxnFees              =   -.txnfees
               #,
               #osFUN               =   osMaxPos
             ), 
             type               =   "enter",
             path.dep           =   TRUE,
             label              =   "Entry")
    
    #Exit Rules
    
  print("summary")
  summary(getStrategy(strategyName))
  
  # Summary results are produced below
  
  print("results")
  
  results <- applyStrategy(strategy= strategyName, portfolios = portfolioName)
  
  # The applyStrategy() outputs all transactions(from the oldest to recent transactions)that the strategy sends. The first few rows of the applyStrategy() output are shown below
  
  getTxns(Portfolio=portfolioName, Symbol=symbolstring)
  
  mktdata
  
  updatePortf(portfolioName,Dates=paste0(startDate,"::",endDate))
  
  dateRange <- time(getPortfolio(portfolioName)$summary) updateAcct(portfolioName,dateRange[which(dateRange >= startDate & dateRange <= endDate)]) updateEndEq(accountName, Dates=paste0(startDate,"::",endDate)) print(plot(tail(getAccount(portfolioName)$summary$End.Eq,-1), main = symbolstring)) tStats <- tradeStats(Portfolios = portfolioName, use="trades", inclZeroDays=FALSE,Dates=paste0(startDate,"::",endDate)) final_acct <- getAccount(portfolioName) #final_acct #View(final_acct) options(width=70) print(plot(tail(final_acct$summary$End.Eq,-1), main = symbolstring)) #dev.off() tail(final_acct$summary$End.Eq) rets <- PortfReturns(Account = accountName) #rownames(rets) <- NULL tab.perf <- table.Arbitrary(rets, metrics=c( "Return.cumulative", "Return.annualized", "SharpeRatio.annualized", "CalmarRatio"), metricsNames=c( "Cumulative Return", "Annualized Return", "Annualized Sharpe Ratio", "Calmar Ratio")) tab.perf tab.risk <- table.Arbitrary(rets, metrics=c( "StdDev.annualized", "maxDrawdown" ), metricsNames=c( "Annualized StdDev", "Max DrawDown")) tab.risk return (as.numeric(tail(final_acct$summary$End.Eq,1))-init_equity)

  #reset_quantstrat()
  
}
)

nó dường như được song song nhưng nó không cập nhật init_equity một cách chính xác