[英]How do I replace Quantstrat 'for loop' with mclapply [parallelized]?
I'd like to parallelize quantstrat.我想并行化 quantstrat。 My code isn't exactly like this, but this showcases the issue.我的代码不完全是这样,但这说明了这个问题。 The problem I believe is the.blotter env is initialized to a pointer memory address and i am unable to initialize an array/matrix of new.env().我认为的问题是.blotter env 被初始化为指针 memory 地址,我无法初始化 new.env() 的数组/矩阵。
What I would like to do is replace the for loop with an mclapply so I can run multiple applyStrategies with varying dates/symbols (only varying symbols is shown here).我想做的是用 mclapply 替换 for 循环,这样我就可以运行具有不同日期/符号的多个 applyStrategies(此处仅显示不同的符号)。 My end goal is a beowulf cluster (makeCluster) and plan on running these in parallel using up to 252 trading days (rolling window) with varying symbols per iteration (but I don't need all that. I simply am asking if there is a way to work with assigning portfolio and the subsequent.blotter memory object in such a way where I can use mclapply)我的最终目标是一个 beowulf 集群(makeCluster),并计划使用最多 252 个交易日(滚动窗口)并行运行这些集群,每次迭代使用不同的符号(但我不需要所有这些。我只是问是否有分配投资组合和后续.blotter memory object 的方式,我可以使用 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)
}
)
But an error is thrown Error in get(symbol, envir = envir): object 'QQQ' not found但是会抛出错误 get(symbol, envir = envir): object 'QQQ' not found
Specifically the problem is FinancialInstrument:::.instrument is pointing to a memory address that isn't updated with my encapsulated variable calls (symbolstring)具体来说,问题是 FinancialInstrument:::.instrument 指向的 memory 地址未使用我封装的变量调用(符号字符串)进行更新
apply.paramset
in quantstrat
already uses a foreach
construct to parallelize execution of applyStrategy
. apply.paramset
中的quantstrat
已经使用foreach
构造来并行执行applyStrategy
。
apply.paramset
needs to do a fair amount of work to make sure that the environments are available in the workers to do the work, and to collect the proper results to send them back to the calling process. apply.paramset
需要做大量的工作,以确保工作人员可以使用环境来完成工作,并收集正确的结果以将它们发送回调用进程。
The simplest thing for you to do would probably be to use apply.paramset
.您要做的最简单的事情可能是使用apply.paramset
。 Make your dates and symbols parameters, and have the function run normally.使您的日期和符号参数,并让 function 正常运行。
Alternately, I suggest you look at the steps required to use a parallel foreach
construction in apply.paramset
to modify it to your suggested case.或者,我建议您查看在apply.paramset
中使用并行foreach
构造以将其修改为您建议的情况所需的步骤。
Also note that your question asks about using a Beowulf cluster and mclapply
.另请注意,您的问题询问有关使用 Beowulf 集群和mclapply
的问题。 This won't work.这行不通。 mclapply
only works in a single memory space. mclapply
仅适用于单个 memory 空间。 Beowulf clusters don't normally share a single memory and process space. Beowulf 集群通常不共享单个 memory 和进程空间。 They typically distribute jobs via parallel libraries such as MPI.他们通常通过并行库(例如 MPI)分发作业。 apply.paramset
could already distribute on a Beowulf cluster by using a doMPI
backend to foreach
.通过使用doMPI
后端到foreach
, apply.paramset
已经可以分布在 Beowulf 集群上。 That is one of the reasons we used foreach
: the multitude of different parallel backends that are available.这就是我们使用foreach
的原因之一:有大量不同的并行后端可用。 The doMC
backend for foreach
actually uses mclapply
behind the scenes. foreach
的doMC
后端实际上在幕后使用了mclapply
。
I believe this parallelizes the code.我相信这会使代码并行化。 I've swapped the indicators out as well as as symbols, but the logic of using different symbols and dates is in there我已经换掉了指标和符号,但是使用不同符号和日期的逻辑就在那里
Basically I added基本上我加了
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()
}
)
it appears to be parallized but it doesn't update init_equity correctly它似乎是并行化的,但它没有正确更新 init_equity
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.