quantstrat
quantstrat copied to clipboard
Enable WFA across a portfolio of assets
Description
WFA does not work as expected for portfolios with more than one symbol.
Expected behavior
Perform parameter optimization and WFA across a portfolio of assets based on their own unique optimal paramater combinations.
Minimal, reproducible example
require(quantstrat)
suppressWarnings(rm("order_book.macd",pos=.strategy))
suppressWarnings(rm("account.macd","portfolio.macd",pos=.blotter))
suppressWarnings(rm("account.st","portfolio.st","stock.str","stratMACD","startDate","initEq",'start_t','end_t'))
#correct for TZ issues if they crop up
oldtz<-Sys.getenv('TZ')
if(oldtz=='') {
Sys.setenv(TZ="GMT")
}
stock.str=c('AAPL','MSFT') # what are we trying it on
#MA parameters for MACD
fastMA = 12
slowMA = 26
signalMA = 9
maType="EMA"
currency('USD')
stock(stock.str,currency='USD',multiplier=1)
startDate='2006-12-31'
initEq=1000000
portfolio.st='macd'
account.st='macd'
initPortf(portfolio.st,symbols=stock.str)
initAcct(account.st,portfolios=portfolio.st)
initOrders(portfolio=portfolio.st)
strat.st<-portfolio.st
# define the strategy
strategy(strat.st, store=TRUE)
#one indicator
add.indicator(strat.st, name = "MACD",
arguments = list(x=quote(Cl(mktdata)),
nFast=fastMA,
nSlow=slowMA),
label='_'
)
#two signals
add.signal(strat.st,name="sigThreshold",
arguments = list(column="signal._",
relationship="gt",
threshold=0,
cross=TRUE),
label="signal.gt.zero"
)
add.signal(strat.st,name="sigThreshold",
arguments = list(column="signal._",
relationship="lt",
threshold=0,
cross=TRUE),
label="signal.lt.zero"
)
####
# add rules
# entry
add.rule(strat.st,name='ruleSignal',
arguments = list(sigcol="signal.gt.zero",
sigval=TRUE,
orderqty=100,
ordertype='market',
orderside='long',
threshold=NULL),
type='enter',
label='enter',
storefun=FALSE
)
# exit
add.rule(strat.st,name='ruleSignal',
arguments = list(sigcol="signal.lt.zero",
sigval=TRUE,
orderqty='all',
ordertype='market',
orderside='long',
threshold=NULL,
orderset='exit2'),
type='exit',
label='exit'
)
#end rules
####
getSymbols(stock.str,from=startDate, to='2014-06-01', src='yahoo')
start_t<-Sys.time()
out<-applyStrategy(strat.st , portfolios=portfolio.st,parameters=list(nFast=fastMA, nSlow=slowMA, nSig=signalMA,maType=maType),verbose=TRUE)
end_t<-Sys.time()
print(end_t-start_t)
start_t<-Sys.time()
updatePortf(Portfolio=portfolio.st,Dates=paste('::',as.Date(Sys.time()),sep=''))
end_t<-Sys.time()
print("trade blotter portfolio update:")
print(end_t-start_t)
# set tz as it was before the demo
Sys.setenv(TZ=oldtz)
require(foreach,quietly=TRUE)
require(iterators)
require(quantstrat)
#retrieve the strategy from the environment, since the 'macd' strategy uses store=TRUE
strategy.st <- 'macd'
### Set up Parameter Values
.FastMA = (1:10)
.SlowMA = (5:25)
.nsamples = 15 #for random parameter sampling, less important if you're using doParallel or doMC
### MA paramset
add.distribution(strategy.st,
paramset.label = 'MA',
component.type = 'indicator',
component.label = '_', #this is the label given to the indicator in the strat
variable = list(n = .FastMA),
label = 'nFAST'
)
add.distribution(strategy.st,
paramset.label = 'MA',
component.type = 'indicator',
component.label = '_', #this is the label given to the indicator in the strat
variable = list(n = .SlowMA),
label = 'nSLOW'
)
add.distribution.constraint(strategy.st,
paramset.label = 'MA',
distribution.label.1 = 'nFAST',
distribution.label.2 = 'nSLOW',
operator = '<',
label = 'MA'
)
###
wfportfolio <- "wf.macd"
initPortf(wfportfolio,symbols=stock.str)
initOrders(portfolio=wfportfolio)
wf_start <- Sys.time()
registerDoSEQ() # for debugging
wfresults <- walk.forward(strategy.st,
paramset.label = 'MA',
portfolio.st = wfportfolio,
account.st = account.st,
nsamples = .nsamples,
period = 'months',
k.training = 36,
k.testing = 12,
verbose =TRUE,
anchored = TRUE,
include.insamples = TRUE,
savewf = FALSE
)
wf_end <-Sys.time()
cat("\n Running the walk forward search: \n ")
print(wf_end-wf_start)
cat(" Total trials:",.strategy$macd$trials,"\n")
wfa.stats <- wfresults$tradeStats
print(wfa.stats)
chart.forward(wfresults)
# resulting stats are identical for both symbols, AAPL and MSFT
Session Info
R version 4.0.2 (2020-06-22)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.1 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
[4] LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] graphics grDevices utils datasets stats methods base
other attached packages:
[1] iterators_1.0.12 quantstrat_0.16.8 foreach_1.5.0
[4] blotter_0.15.0 PerformanceAnalytics_2.0.4 FinancialInstrument_1.3.1
[7] quantmod_0.4.17 TTR_0.23-6 xts_0.12-0
[10] zoo_1.8-8
loaded via a namespace (and not attached):
[1] quadprog_1.5-8 lattice_0.20-41 codetools_0.2-16 MASS_7.3-51.6 grid_4.0.2
[6] curl_4.3 boot_1.3-25 tools_4.0.2 compiler_4.0.2