I have continued to work on this problem and have made some progress
although I am still stuck. As well as cleaning up the reproducible
code because it is quite long. I am able to run this sequentially and
see some output however still with errors to the combine function.
Although I think its deeper then that.
I receive this error after every iteration.
<simpleError in if (inherits(sret$indicators, "xts") & nrow(mktdata)
== nrow(sret$indicators)) { mktdata <- sret$indicators
sret$indicators <- NULL}: argument is of length zero>
this error after completion
error calling combine function:
<simpleError in fun(result.1, result.2, result.3, result.4, result.5,
result.6, result.7, result.8, result.9, result.10, result.11,
result.12, result.13, result.14, result.15): attempt to select
less than one element>
numValues: 15, numResults: 15, stopped: TRUE
Error in walk.forward(pairStrat, paramset.label = "BBOPT",
portfolio.st = portfolio1.st, :
obj.func() returned empty result
In addition: Warning message:
In max(x$tradeStats$Net.Trading.PL) :
no non-missing arguments to max; returning -Inf
I looked into the walk.forward function and found nothing that
required this , but using the debugger it seems to be coming from
apply.paramset. Since the apply.paramset fails we do not return
anything to the obj.func which then throws another error. However when
i run apply.paramset sequentially on my strategy, I do not get any
errors and see correct results. I am really confused as to the origin
of this error or how to rectify it especially since i am doing
everything sequentially. Which should prevent the previous problem of
calcRatio not getting pushed to nodes.
require(quantstrat)
suppressWarnings(rm("order_book.pair1",pos=.strategy))
suppressWarnings(rm("account.pairs", "portfolio.pair1", pos=.blotter))
suppressWarnings(rm("initDate", "endDate", "startDate", "initEq", "SD", "N",
"symb1", "symb2", "portfolio1.st", "account.st",
"pairStrat", "out1"))
initDate <- '2009-01-01'
endDate <- '2011-05-01'
startDate <- '2009-01-02'
initEq <- 100000
SD <- 2
N <- 20
MaxPos <- 1500 #max position in stockA;
# max position in stock B will be max * ratio, i.e. no hard position limit in
# Stock B
lvls <- 3 #how many times to fade; Each order's qty will = MaxPos/lvls
symb1 <- 'SPY' #change these to try other pairs
symb2 <- 'DIA' #if you change them, make sure position limits still make sense
portfolio1.st <- 'pair1'
account.st <- 'pairs'
getSymbols(c(symb1, symb2), from=startDate, to=endDate, adjust=TRUE)
# The following function is used to make sure the timestamps of all symbols are
# the same deletes rows where one of the stocks is missing data
alignSymbols <- function(symbols, env=.GlobalEnv) {
# This is a simplified version of qmao::alignSymbols()
if (length(symbols) < 2)
stop("Must provide at least 2 symbols")
if (any(!is.character(symbols)))
stop("Symbols must be vector of character strings.")
ff <- get(symbols[1],env=env)
for (sym in symbols[-1]) {
tmp.sym <- get(sym,env=env)
ff <- merge(ff, tmp.sym, all=FALSE)
}
for (sym in symbols) {
assign(sym,ff[,grep(sym, colnames(ff))], env=env)
}
symbols
}
alignSymbols(c(symb1, symb2))
# Define Instruments
currency("USD")
stock(symb1, currency="USD", multiplier=1)
stock(symb2, currency="USD", multiplier=1)
# Initialize Portfolio, Account, and Orders
initPortf(name=portfolio1.st, c(symb1,symb2), initDate=initDate)
initAcct(account.st, portfolios=portfolio1.st, initDate=initDate, initEq=initEq)
initOrders(portfolio=portfolio1.st, initDate=initDate)
# osFUN will need to know which symbol is leg 1 and which is leg 2 as well as
# what the values are for MaxPos and lvls. So, create a slot in portfolio to
# hold this info.
pair <- c(1, 2, MaxPos, lvls)
names(pair) <- c(symb1, symb2, "MaxPos", "lvls")
.blotter[[paste('portfolio', portfolio1.st, sep='.')]]$pair <- pair
# Create initial position limits and levels by symbol
# allow 3 entries for long and short if lvls=3.
addPosLimit(portfolio=portfolio1.st, timestamp=initDate, symbol=symb1,
maxpos=MaxPos, longlevels=lvls, minpos=-MaxPos, shortlevels=lvls)
addPosLimit(portfolio=portfolio1.st, timestamp=initDate, symbol=symb2,
maxpos=MaxPos, longlevels=lvls, minpos=-MaxPos, shortlevels=lvls)
# Create a strategy object
pairStrat <- strategy('pairStrat')
# Indicator function
calcRatio <- function(x) {
#returns the ratio of notional close prices for 2 symbols
x1 <- get(x[1])
x2 <- get(x[2])
mult1 <- getInstrument(x[1])$multiplier
mult2 <- getInstrument(x[2])$multiplier
rat <- (mult1 * Cl(x1)) / (mult2 * Cl(x2))
colnames(rat) <- 'Ratio'
rat
}
# Indicator used for determining entry/exits
Ratio <- calcRatio(c(symb1[1], symb2[1]))
# Ratio indicator.
.blotter[[paste('portfolio',portfolio1.st,sep='.')]]$HedgeRatio <- Ratio
getHedgeRatio <- function(portfolio, timestamp) {
portf <- getPortfolio(portfolio)
timestamp <- format(timestamp,"%Y-%m-%d %H:%M:%S")
toDate <- paste("::", timestamp, sep="")
Ratio <- last(portf$HedgeRatio[toDate])
as.numeric(Ratio)
}
# Create an indicator - BBands on the Ratio
pairStrat <- add.indicator(strategy=pairStrat, name = "calcRatio",
arguments=list(x=c(symb1,symb2)))
pairStrat <- add.indicator(strategy=pairStrat, name = "BBands",
arguments=list(HLC=quote(Ratio), sd=SD, n=N,
maType='SMA'),
label = "BBands")
#applyIndicators(strategy=pairStrat,mktdata=get(symb1[1])) #for debugging
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","up"),
relationship="lt"),
label="cross.up")
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","dn"),
relationship="gt"),
label="cross.dn")
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","mavg"),
relationship="lt"),
label="cross.mid.fa")
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","mavg"),
relationship="gt"),
label="cross.mid.fb")
# make an order sizing function
#######################_ORDER SIZING FUNCTION_##################################
# check to see which stock it is. If it's the second stock, reverse orderqty and
# orderside
osSpreadMaxPos <- function (data, timestamp, orderqty, ordertype, orderside,
portfolio, symbol, ruletype, ..., orderprice) {
portf <- getPortfolio(portfolio)
#check to make sure pair slot has the things needed for this function
if (!any(portf$pair == 1) && !(any(portf$pair == 2)))
stop('pair must contain both values 1 and 2')
if (!any(names(portf$pair) == "MaxPos") || !any(names(portf$pair) == "lvls"))
stop('pair must contain MaxPos and lvls')
if (portf$pair[symbol] == 1) legside <- "long"
if (portf$pair[symbol] == 2) legside <- "short"
MaxPos <- portf$pair["MaxPos"]
lvls <- portf$pair["lvls"]
ratio <- getHedgeRatio(portfolio, timestamp)
pos <- getPosQty(portfolio, symbol, timestamp)
PosLimit <- getPosLimit(portfolio, symbol, timestamp)
qty <- orderqty
if (legside == "short") {#symbol is 2nd leg
## Comment out next line to use equal ordersizes for each stock.
addPosLimit(portfolio=portfolio, timestamp=timestamp, symbol=symbol,
maxpos=round(MaxPos*ratio,0), longlevels=lvls,
minpos=round(-MaxPos*ratio,0), shortlevels=lvls)
##
qty <- -orderqty #switch orderqty for Stock B
}
if (qty > 0) orderside = 'long'
if (qty < 0) orderside = 'short'
orderqty <- osMaxPos(data=data,timestamp=timestamp, orderqty=qty,
ordertype=ordertype, orderside=orderside,
portfolio=portfolio, symbol=symbol, ruletype=ruletype,
...)
#Add the order here instead of in the ruleSignal function
if (!is.null(orderqty) & !orderqty == 0 & !is.null(orderprice)) {
addOrder(portfolio=portfolio, symbol=symbol,
timestamp=timestamp, qty=orderqty, price=as.numeric(orderprice),
ordertype=ordertype, side=orderside, replace=FALSE,
status="open", ...=...)
}
return(0) #so that ruleSignal function doesn't also try to place an order
}
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.dn", sigval=TRUE,
orderqty=1e6, ordertype='market',
orderside=NULL, osFUN='osSpreadMaxPos'),
type='enter')
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.up", sigval=TRUE,
orderqty=-1e6, ordertype='market',
orderside=NULL, osFUN='osSpreadMaxPos'),
type='enter')
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.mid.fb", sigval=TRUE,
orderqty='all', ordertype='market',
orderside=NULL),
type='exit')
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.mid.fa", sigval=TRUE,
orderqty='all', ordertype='market',
orderside=NULL),
type='exit')
## for debugging
# applySignals(strategy=pairStrat,
# mktdata=applyIndicators(strategy=pairStrat, mktdata=get(symb1)))
##
out1<-applyStrategy(strategy=pairStrat, portfolios=portfolio1.st)
updatePortf(Portfolio=portfolio1.st,
Dates=paste("::", as.Date(Sys.time()), sep=''))
updateAcct(account.st, Dates=paste(startDate, endDate, sep="::"))
updateEndEq(account.st, Dates=paste(startDate, endDate, sep="::"))
getEndEq(account.st, Sys.time())
#Distribution Initialization
pairStrat <- add.distribution(strategy = pairStrat,
paramset.label ="BBOPT",
component.type = "indicator",
component.label = "BBands",
variable = list(n = seq(10,30, by = 5)),
label = "n")
pairStrat <- add.distribution(strategy = pairStrat,
paramset.label ="BBOPT",
component.type = "indicator",
component.label = "BBands",
variable = list(sd = seq(1,3,by = 1)),
label = "sd")
# apply.paramset(stratBBands, "BBOPT", portfolio.st,account.st)
# Objective Function
my.obj.func <- function(x)
{
return(max(x$tradeStats$Net.Trading.PL) == x$tradeStats$Net.Trading.PL)
}
#WFA - sequential
require(foreach)
require(iterators)
registerDoSEQ()
result <- walk.forward(pairStrat,
paramset.label = "BBOPT",
portfolio.st = portfolio1.st,
account.st = account.st,
period = "months",
k.training = 6,
k.testing = 3,
obj.func = my.obj.func,
obj.args = list(x=quote(result$apply.paramset)),
audit.prefix = "wfa",
anchored = FALSE,
verbose = TRUE)
thanks again for your help as always,
Derek
On Tue, Sep 30, 2014 at 9:55 PM, Derek Wong <treydog999 at gmail.com> wrote:
Hi Josh, Sorry about the HTML mistake, I am new to using something like r-sig-finance mailing list, I didn't realize I was posting incorrectly. In regards to the personal correspondence, I didnt full understand that it was operating system independent, I thought that because windows has problems with MC solutions that could have been the issue. I have tried doing using the doRedis package and it just runs for hours on end., but never showing a result. I am guessing it should not take 4+ hours to run this, but i can not see and additional output in R so i am not sure how far along it got.. Although the server console does show 10 changes in 300 seconds. Saving... fork operation complete Background saving terminated success. I have also tried using registerdoSEQ() think that was a guaranteed way of seeing the results however i recieve an error. here is the output. I have checked if i had the iterators package installed and loaded which I do. So i do not know where it is trying to call this function. I did a search for help on iter assuming it was a built in function but did not find anything.
registerDoSEQ() result <- walk.forward(pairStrat,
+ paramset.label = "BBOPT",
+ portfolio.st = portfolio1.st,
+ account.st = account.st,
+ period = "months",
+ k.training = 6,
+ k.testing = 3,
+ obj.func = my.obj.func,
+ obj.args = list(x=quote(result$apply.paramset)),
+ audit.prefix = "wfa",
+ anchored = FALSE,
+ verbose = TRUE)
[1] "=== training BBOPT on 2009-01-02/2009-06-30"
Error in eval(expr, envir, enclos) : could not find function "iter"
All Code with appended doRedis and doSEQ -------- (hopefully this
posts correctly)
#Kindly contributed to quantstrat by Garrett See
#code borrowed heavily from existing quantstrat demos
# This is a simple pairs trading example intended to illustrate how you can
# extend existing quantstrat functionality. It uses addPosLimits to specify
# levels and position limits, and shows how to pass a custom order sizing
# function to osFUN
# Note that it would be easier to build a spread first and treat it as a single
# instrument instead of dealing with a portfolio of stocks.
## given 2 stocks, calculate the ratio of their notional values. If the ratio
# falls below it's 2 stdev band, then when it crosses back above it, buy stock 1
# and sell stock 2. If the ratio rises above it's 2 stdev band, then when it
# crosses back below it, sell stock 1 and buy stock 2. If the ratio crosses
# its moving average, then flatten any open positions.
# The Qty of Stock A that it buys (sells) = MaxPos / lvls
# The Qty of Stock B that is sells (buys) = MaxPos * Ratio / lvls
require(quantstrat)
suppressWarnings(rm("order_book.pair1",pos=.strategy))
suppressWarnings(rm("account.pairs", "portfolio.pair1", pos=.blotter))
suppressWarnings(rm("initDate", "endDate", "startDate", "initEq", "SD", "N",
"symb1", "symb2", "portfolio1.st", "account.st",
"pairStrat", "out1"))
##### PLACE DEMO AND TEST DATES HERE #################
#
#if(isTRUE(options('in_test')$in_test))
# # use test dates
# {initDate="2011-01-01"
# endDate="2012-12-31"
# } else
# # use demo defaults
# {initDate="1999-12-31"
# endDate=Sys.Date()}
initDate <- '2009-01-01'
endDate <- '2011-05-01'
startDate <- '2009-01-02'
initEq <- 100000
SD <- 2
N <- 20
MaxPos <- 1500 #max position in stockA;
# max position in stock B will be max * ratio, i.e. no hard position limit in
# Stock B
lvls <- 3 #how many times to fade; Each order's qty will = MaxPos/lvls
symb1 <- 'SPY' #change these to try other pairs
symb2 <- 'DIA' #if you change them, make sure position limits still make sense
portfolio1.st <- 'pair1'
account.st <- 'pairs'
getSymbols(c(symb1, symb2), from=startDate, to=endDate, adjust=TRUE)
# The following function is used to make sure the timestamps of all symbols are
# the same deletes rows where one of the stocks is missing data
alignSymbols <- function(symbols, env=.GlobalEnv) {
# This is a simplified version of qmao::alignSymbols()
if (length(symbols) < 2)
stop("Must provide at least 2 symbols")
if (any(!is.character(symbols)))
stop("Symbols must be vector of character strings.")
ff <- get(symbols[1],env=env)
for (sym in symbols[-1]) {
tmp.sym <- get(sym,env=env)
ff <- merge(ff, tmp.sym, all=FALSE)
}
for (sym in symbols) {
assign(sym,ff[,grep(sym, colnames(ff))], env=env)
}
symbols
}
alignSymbols(c(symb1, symb2))
# Define Instruments
currency("USD")
stock(symb1, currency="USD", multiplier=1)
stock(symb2, currency="USD", multiplier=1)
# Initialize Portfolio, Account, and Orders
initPortf(name=portfolio1.st, c(symb1,symb2), initDate=initDate)
initAcct(account.st, portfolios=portfolio1.st, initDate=initDate, initEq=initEq)
initOrders(portfolio=portfolio1.st, initDate=initDate)
# osFUN will need to know which symbol is leg 1 and which is leg 2 as well as
# what the values are for MaxPos and lvls. So, create a slot in portfolio to
# hold this info.
pair <- c(1, 2, MaxPos, lvls)
names(pair) <- c(symb1, symb2, "MaxPos", "lvls")
.blotter[[paste('portfolio', portfolio1.st, sep='.')]]$pair <- pair
# Create initial position limits and levels by symbol
# allow 3 entries for long and short if lvls=3.
addPosLimit(portfolio=portfolio1.st, timestamp=initDate, symbol=symb1,
maxpos=MaxPos, longlevels=lvls, minpos=-MaxPos, shortlevels=lvls)
addPosLimit(portfolio=portfolio1.st, timestamp=initDate, symbol=symb2,
maxpos=MaxPos, longlevels=lvls, minpos=-MaxPos, shortlevels=lvls)
# Create a strategy object
pairStrat <- strategy('pairStrat')
# Indicator function
calcRatio <- function(x) {
#returns the ratio of notional close prices for 2 symbols
x1 <- get(x[1])
x2 <- get(x[2])
mult1 <- getInstrument(x[1])$multiplier
mult2 <- getInstrument(x[2])$multiplier
rat <- (mult1 * Cl(x1)) / (mult2 * Cl(x2))
colnames(rat) <- 'Ratio'
rat
}
# Indicator used for determining entry/exits
Ratio <- calcRatio(c(symb1[1], symb2[1]))
# Store hedge ratio in portfolio so that it's available for order sizing
# function. In this example, the hedge ratio happens to be the same as the
# Ratio indicator.
.blotter[[paste('portfolio',portfolio1.st,sep='.')]]$HedgeRatio <- Ratio
#and make a function to get the most recent HedgeRatio
getHedgeRatio <- function(portfolio, timestamp) {
portf <- getPortfolio(portfolio)
timestamp <- format(timestamp,"%Y-%m-%d %H:%M:%S")
# above line ensures you don't get last value of next day if using intraday
# data and timestamp=midnight
toDate <- paste("::", timestamp, sep="")
Ratio <- last(portf$HedgeRatio[toDate])
as.numeric(Ratio)
}
# Create an indicator - BBands on the Ratio
pairStrat <- add.indicator(strategy=pairStrat, name = "calcRatio",
arguments=list(x=c(symb1,symb2)))
pairStrat <- add.indicator(strategy=pairStrat, name = "BBands",
arguments=list(HLC=quote(Ratio), sd=SD, n=N,
maType='SMA'),
label = "BBands")
#applyIndicators(strategy=pairStrat,mktdata=get(symb1[1])) #for debugging
# Create signals - buy when crossing lower band from below, sell when crossing
# upper band from above, flatten when crossing mavg from above or from below
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","up"),
relationship="lt"),
label="cross.up")
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","dn"),
relationship="gt"),
label="cross.dn")
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","mavg"),
relationship="lt"),
label="cross.mid.fa")
pairStrat <- add.signal(strategy=pairStrat, name="sigCrossover",
arguments=list(columns=c("Ratio","mavg"),
relationship="gt"),
label="cross.mid.fb")
# make an order sizing function
#######################_ORDER SIZING FUNCTION_##################################
# check to see which stock it is. If it's the second stock, reverse orderqty and
# orderside
osSpreadMaxPos <- function (data, timestamp, orderqty, ordertype, orderside,
portfolio, symbol, ruletype, ..., orderprice) {
portf <- getPortfolio(portfolio)
#check to make sure pair slot has the things needed for this function
if (!any(portf$pair == 1) && !(any(portf$pair == 2)))
stop('pair must contain both values 1 and 2')
if (!any(names(portf$pair) == "MaxPos") || !any(names(portf$pair) == "lvls"))
stop('pair must contain MaxPos and lvls')
if (portf$pair[symbol] == 1) legside <- "long"
if (portf$pair[symbol] == 2) legside <- "short"
MaxPos <- portf$pair["MaxPos"]
lvls <- portf$pair["lvls"]
ratio <- getHedgeRatio(portfolio, timestamp)
pos <- getPosQty(portfolio, symbol, timestamp)
PosLimit <- getPosLimit(portfolio, symbol, timestamp)
qty <- orderqty
if (legside == "short") {#symbol is 2nd leg
## Comment out next line to use equal ordersizes for each stock.
addPosLimit(portfolio=portfolio, timestamp=timestamp, symbol=symbol,
maxpos=round(MaxPos*ratio,0), longlevels=lvls,
minpos=round(-MaxPos*ratio,0), shortlevels=lvls)
##
qty <- -orderqty #switch orderqty for Stock B
}
if (qty > 0) orderside = 'long'
if (qty < 0) orderside = 'short'
orderqty <- osMaxPos(data=data,timestamp=timestamp, orderqty=qty,
ordertype=ordertype, orderside=orderside,
portfolio=portfolio, symbol=symbol, ruletype=ruletype,
...)
#Add the order here instead of in the ruleSignal function
if (!is.null(orderqty) & !orderqty == 0 & !is.null(orderprice)) {
addOrder(portfolio=portfolio, symbol=symbol,
timestamp=timestamp, qty=orderqty, price=as.numeric(orderprice),
ordertype=ordertype, side=orderside, replace=FALSE,
status="open", ...=...)
}
return(0) #so that ruleSignal function doesn't also try to place an order
}
################################################################################
# Create entry and exit rules for longs and for shorts. Both symbols will get
# the same buy/sell signals, but osMaxPos will reverse those for the second
# symbol.
# orderqty's are bigger than PosLimits allow. osMaxPos will adjust the orderqty
# down to 1/3 the max allowed. (1/3 is because we are using 3 levels in
# PosLimit)
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.dn", sigval=TRUE,
orderqty=1e6, ordertype='market',
orderside=NULL, osFUN='osSpreadMaxPos'),
type='enter')
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.up", sigval=TRUE,
orderqty=-1e6, ordertype='market',
orderside=NULL, osFUN='osSpreadMaxPos'),
type='enter')
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.mid.fb", sigval=TRUE,
orderqty='all', ordertype='market',
orderside=NULL),
type='exit')
pairStrat <- add.rule(strategy=pairStrat, name='ruleSignal',
arguments=list(sigcol="cross.mid.fa", sigval=TRUE,
orderqty='all', ordertype='market',
orderside=NULL),
type='exit')
## for debugging
# applySignals(strategy=pairStrat,
# mktdata=applyIndicators(strategy=pairStrat, mktdata=get(symb1)))
##
out1<-applyStrategy(strategy=pairStrat, portfolios=portfolio1.st)
updatePortf(Portfolio=portfolio1.st,
Dates=paste("::", as.Date(Sys.time()), sep=''))
updateAcct(account.st, Dates=paste(startDate, endDate, sep="::"))
updateEndEq(account.st, Dates=paste(startDate, endDate, sep="::"))
getEndEq(account.st, Sys.time())
dev.new()
chart.Posn(Portfolio=portfolio1.st, Symbol=symb1)
dev.new()
chart.Posn(Portfolio=portfolio1.st, Symbol=symb2)
dev.new()
chartSeries(Cl(get(symb1))/Cl(get(symb2)), TA="addBBands(n=N,sd=SD)")
ret1 <- PortfReturns(account.st)
ret1$total <- rowSums(ret1)
#ret1
if("package:PerformanceAnalytics" %in% search() ||
require("PerformanceAnalytics",quietly=TRUE)) {
# getSymbols("SPY", from='1999-01-01')
# SPY.ret <- Return.calculate(SPY$SPY.Close)
# tmp <- merge(SPY.ret,ret1$total,all=FALSE)
dev.new()
charts.PerformanceSummary(ret1$total, geometric=FALSE, wealth.index=TRUE)
}
###############################################################################
# R (http://r-project.org/) Quantitative Strategy Model Framework
#
# Package Copyright (c) 2009-2012
# Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and
Joshua Ulrich
#
# This library is distributed under the terms of the GNU Public License (GPL)
# for full details see the file COPYING
#
# $Id$
#
###############################################################################
##### PLACE THIS BLOCK AT END OF DEMO SCRIPT ###################
# book = getOrderBook(port)
# stats = tradeStats(port)
# rets = PortfReturns(acct)
################################################################
#Distribution Initialization
pairStrat <- add.distribution(strategy = pairStrat,
paramset.label ="BBOPT",
component.type = "indicator",
component.label = "BBands",
variable = list(n = seq(10,200, by = 10)),
label = "n")
pairStrat <- add.distribution(strategy = pairStrat,
paramset.label ="BBOPT",
component.type = "indicator",
component.label = "BBands",
variable = list(sd = seq(1,5,by = 0.5)),
label = "sd")
# Objective Function
my.obj.func <- function(x)
{
# pick one of the following objective functions (uncomment)
#return(max(x$tradeStats$Max.Drawdown) == x$tradeStats$Max.Drawdown)
return(max(x$tradeStats$Net.Trading.PL) == x$tradeStats$Net.Trading.PL)
}
#WFA - Comment out selected method
# require(doParallel)
# cl <- makePSOCKcluster(2)
# registerDoParallel(cl)
#
# require(doRedis)
# registerDoRedis('jobs')
# startLocalWorkers(n=2, queue='jobs')
# print(getDoParWorkers())
registerDoSEQ()
result <- walk.forward(pairStrat,
paramset.label = "BBOPT",
portfolio.st = portfolio1.st,
account.st = account.st,
period = "months",
k.training = 6,
k.testing = 3,
obj.func = my.obj.func,
obj.args = list(x=quote(result$apply.paramset)),
audit.prefix = "wfa",
anchored = FALSE,
verbose = TRUE)
I
On Tue, Sep 30, 2014 at 10:34 AM, Joshua Ulrich <josh.m.ulrich at gmail.com> wrote:
Tue, Sep 30, 2014 at 10:25 AM, Derek Wong <treydog999 at gmail.com> wrote:
Mark, Thank you for the reply. I really appreciate you taking the time to look at it. However in my previous email/post and my current code I do not see a line that shows portfolio1.st <- 'pair1'account.st <- 'pairs'
You're posting in HTML, which the posting guild tells you not to do. The list server must convert your HTML into plain text, which often mangles your original message. For example, look at how your message was received at Nabble: http://r.789695.n4.nabble.com/quantstrat-help-simple-combine-error-using-windows-and-walk-forward-td4697468.html
they should be two separate lines. Either way I have run the entire code and will show the area I am focusing on. Which is the end using the walk.forward() function, as everything else in the code runs perfectly for me using R 3.1.1 in windows or ubuntu.
As I said in our personal correspondence, "the problem is that the calcRatio function is not being exported to the nodes. This is probably related to bug #5814 (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5814&group_id=316&atid=1269)." This is going to be a problem with a socket cluster on any operating system. It will work if you don't run in parallel, or if you run on almost anything other than a socket cluster (e.g. redis, fork [multicore], etc). Best, Josh
Code I am focusing on:
# Objective Function
my.obj.func <- function(x)
{
# pick one of the following objective functions (uncomment)
#return(max(x$tradeStats$Max.Drawdown) == x$tradeStats$Max.Drawdown)
return(max(x$tradeStats$Net.Trading.PL) == x$tradeStats$Net.Trading.PL)
}
#WFA
require(doParallel)
cl <- makePSOCKcluster(2)
registerDoParallel(cl)
result <- walk.forward(pairStrat,
paramset.label = "BBOPT",
portfolio.st = portfolio1.st,
account.st = account.st,
period = "months",
k.training = 6,
k.testing = 3,
obj.func = my.obj.func,
obj.args = list(x=quote(result$apply.paramset)),
audit.prefix = "wfa",
anchored = FALSE,
verbose = TRUE)
Output below:
# Objective Function my.obj.func <- function(x)
+ {
+ # pick one of the following objective functions (uncomment)
+
+ #return(max(x$tradeStats$Max.Drawdown) == x$tradeStats$Max.Drawdown)
+
+ return(max(x$tradeStats$Net.Trading.PL) == x$tradeStats$Net.Trading.PL)
+
+ }
#WFA require(doParallel) cl <- makePSOCKcluster(2) registerDoParallel(cl) result <- walk.forward(pairStrat,
+ paramset.label = "BBOPT",
+ portfolio.st = portfolio1.st,
+ account.st = account.st,
+ period = "months",
+ k.training = 6,
+ k.testing = 3,
+ obj.func = my.obj.func,
+ obj.args = list(x=quote(result$apply.paramset)),
+ audit.prefix = "wfa",
+ anchored = FALSE,
+ verbose = TRUE)
[1] "=== training BBOPT on 2009-01-02/2009-06-30"
automatically exporting the following variables from the local environment:
account, account.st, calc, env.instrument, mktdata, orderbook,
paramset.label, portfolio, portfolio.st, strategy, user.args, user.func
explicitly exporting variables(s): clone.portfolio, clone.orderbook,
install.param.combo
numValues: 180, numResults: 0, stopped: TRUE
got results for task 1
numValues: 180, numResults: 1, stopped: TRUE
returning status FALSE
got results for task 2
<SNIP>
got results for task 180
numValues: 180, numResults: 180, stopped: TRUE
first call to combine function
evaluating call object to combine results:
fun(result.1, result.2, result.3, result.4, result.5, result.6,
<SNIP>
result.177, result.178, result.179, result.180)
error calling combine function:
<simpleError in fun(result.1, result.2, result.3, result.4, result.5,
result.6, result.7, result.8, result.9, result.10, result.11,
result.12, result.13, result.14, result.15, result.16, result.17,
result.18, result.19, result.20, result.21, result.22,
<SNIP>
result.171, result.172, result.173, result.174, result.175, result.176,
result.177, result.178, result.179, result.180): attempt to select less
than one element>
Error in walk.forward(pairStrat, paramset.label = "BBOPT", portfolio.st =
portfolio1.st, :
obj.func() returned empty result
In addition: Warning messages:
1: In e$fun(obj, substitute(ex), parent.frame(), e$data) :
already exporting variable(s): env.instrument
2: In max(x$tradeStats$Net.Trading.PL) :
no non-missing arguments to max; returning -Inf
Thanks again
Derek
On Tue, Sep 30, 2014 at 8:20 AM, Mark Knecht <markknecht at gmail.com> wrote:
On Tue, Sep 30, 2014 at 12:34 AM, Derek Wong <treydog999 at gmail.com> wrote:
Hello, I have been able to reproduce this error in Ubuntu based system as well
not
just on windows. I was wondering if anyone had any insights or ways to to solve this or create a work around. If there is any additional
information
you require let me know. Please I would really appreciate help on this.
It
is totally out of my depth and I am hoping that this fine community can help.
Derek, I have no time to do any debugging of this but the first error on my Gentoo system running RStudio and R-3.1.1 is actually this line: portfolio1.st <- 'pair1'account.st <- 'pairs' which does look like bad code to me. One 'problem' with a number of demos that are out there is that the demo author may be using the development version of a specific package which then results in end user types (like me) having problems. I suggest you run this code line-by-line and then post back a few lines preceding the breakdown. Maybe someone can give better input than I can. Also, please edit/snip your responses to add focus to the exact issue. Good luck, Mark
On Wed, Sep 24, 2014 at 9:36 PM, Derek Wong <treydog999 at gmail.com>
wrote:
Hello, I am having a lot of trouble with using walk.forward.in windows. i get the following error. This may be related to bug #5814. If someone could please help me i would really appreciate it. The reproducible code
below is
based on the pair_trade example. Thanks. error calling combine function: <simpleError in fun(result.1, result.2, result.3, result.4, result.5, result.6, result.7, result.8, result.9, result.10, result.11,
<SNIP>
result.172, result.173, result.174, result.175, result.176,
result.177,
result.178, result.179, result.180): attempt to select less than one element> Error in walk.forward(pairStrat, paramset.label = "BBOPT", portfolio.st
=
[[alternative HTML version deleted]]
_______________________________________________ R-SIG-Finance at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-sig-finance -- Subscriber-posting only. If you want to post, subscribe first. -- Also note that this is not the r-help list where general R questions should go.
-- Joshua Ulrich | about.me/joshuaulrich FOSS Trading | www.fosstrading.com