quantStrat won't recognize column names - r

I wrote the following codes and got an error message when apply the strategy:
Error in eval(expr, envir, enclos) : object 'Close' not found
sounds like the strategy can not find column "Close" price,
while the last line of code "head(mktdata)" clearly gives XLB.Close as column name of Close.
by the way, I intentionally left out the add.indicator() function which is not needed.
could anyone help? thanks
last line of code output has XLB.Close as column name:
head(mktdata)
XLB.Open XLB.High XLB.Low XLB.Close XLB.Volume XLB.Adjusted
2010-01-04 30.66197 31.06374 30.54327 31.06374 8287681 30.31
the strategy codes using quantstrat:
------------------------------------------------------------------------
library(quantstrat)
startDate <- '2010-01-01' # start of data
endDate <- '2013-07-31' # end of data
symbols = c("XLF", "XLP", "XLE", "XLY", "XLV", "XLI", "XLB", "XLK", "XLU")
Sys.setenv(TZ="UTC") # set time zone
getSymbols(symbols, src='yahoo', index.class=c("POSIXt","POSIXct"),
from=startDate, to=endDate, adjust=TRUE)
initDate <- '2009-12-31'
initEq <- 1e6
currency("USD")
stock(symbols, currency="USD",multiplier=1)
head(XLB)
Lowcut1<-1.001
Lowcut2<-1.002
rm.strat("multiINTRO") # remove portfolio, account, orderbook if re-run
initPortf(name="multiINTRO", symbols, initDate=initDate)
initAcct(name="multiINTRO", portfolios="multiINTRO",
initDate=initDate, initEq=initEq)
initOrders(portfolio="multiINTRO", initDate=initDate)
strategy("multiINTRO", store=TRUE)
summary(getStrategy("multiINTRO"))
add.signal("multiINTRO", name="sigFormula",
arguments=list(columns=c("Close","Low"),
formula="(Close > Lowcut1*Low) & (Close< Lowcut2*Low)",
cross=FALSE),store=TRUE,env=globalenv(),
label="longLowenter") ##Long entry
add.rule("multiINTRO", name="ruleSignal",
arguments=list(sigcol="longLowenter", sigval=TRUE, orderqty=100,
ordertype="market", orderside="long"), type="enter") ## Long enter
out<-try(applyStrategy("multiINTRO",portfolios="multiINTRO"))
head(mktdata)

head(mktdata) clearly gives "XLB.Close" as column name, and "XLB.Close" != "Close". Use quantmod's Cl and Lo column extractors on market data to get the columns you want.
Also, your formula argument is wrong because it's character string, not a formula. Your strategy runs for me if I change your add.signal call to:
add.signal("multiINTRO", name="sigFormula",
arguments=list(formula=longLowenter ~ Cl(mktdata) > Lowcut1*Lo(mktdata) & Cl(mktdata)< Lowcut2*Lo(mktdata), cross=FALSE), store=TRUE, env=globalenv(),
label="longLowenter") ##Long entry

Related

Generating indicators of different periodicity in quantstrat

I would like to use indicators of timeframes different to the data I am using. I have seen this asked a few time but no solutions as of yet (at least for me anyway).
The below example uses daily stock data however the actual project uses intraday currency data. I have an easy work around for importing the intraday csv data now so the example and real-world should be interchangeable enough.
library(quantstrat)
initDate="2000-01-01"
from="2003-01-01"
to="2016-12-31"
#set account currency and system timezone
currency('USD')
Sys.setenv(TZ="UTC")
#get data
symbols <- "SPY"
getSymbols(symbols, from=from, to=to, src="yahoo", adjust=TRUE)
stock(symbols, "USD")
#trade sizing and initial equity settings
tradeSize <- 100000
initEq <- tradeSize*length(symbols)
#set up the portfolio, account and strategy
strategy.st <- portfolio.st <- account.st <- "mtf.strat"
rm.strat(strategy.st)
initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD')
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD',initEq=initEq)
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)
#SMA length
nSMA <- 14
Adding the SMA as, in this case a daily indicator works a treat
add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=nSMA, maType = "SMA"),
label="SMA")
test <- applyIndicators(strategy.st, mktdata=OHLC(SPY))
Yet trying to add, in this case a weekly SMA
add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(to.period(Cl(mktdata), period = "weeks", k = 1, indexAt = "startof")), n=nSMA, maType = "SMA"),
label="SMAw1")
## Or this
add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(to.weekly(Cl(mktdata))), n=nSMA, maType = "SMA"),
label="SMAw1")
test <- applyIndicators(strategy.st, mktdata=OHLC(SPY))
# Error in runSum(x, n) : ncol(x) > 1. runSum only supports univariate 'x'
Calling the Close column directly without Cl(x) results in the same error. I did this as TTR:::runSum will throw the above error if given more than one column of data.
I'm not entirely sure what the problem is so some assistance would be great.
The problem is that to.period (and therefore to.weekly) return OHLC objects, not a univariate series like TTR::SMA expects. So you need to wrap the output of to.period in Cl.
add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(Cl(to.weekly(Cl(mktdata)))), n=nSMA, maType = "SMA"),
label="SMAw1")
test <- applyIndicators(strategy.st, mktdata=OHLC(SPY))
Now that code runs, but it may still be a problem for your strategy. There will be a lot of NA when that indicator is merged with the daily mktdata.
R> tail(merge(SPY, test$SMA))
SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted SMA.SMAw1
2016-11-25 221.10 221.56 221.01 221.52 37861800 221.52 215.0720
2016-11-28 221.16 221.48 220.36 220.48 70284100 220.48 NA
2016-11-29 220.52 221.44 220.17 220.91 67079400 220.91 NA
2016-11-30 221.63 221.82 220.31 220.38 99783700 220.38 NA
2016-12-01 220.73 220.73 219.15 219.57 77230500 219.57 NA
2016-12-02 219.67 220.25 219.26 219.68 70863400 219.68 215.3207
So it's a good idea to create your own SMA wrapper function to handle all these steps. Then call add.indicator using your wrapper function.
mySMA <- function(x, on = "days", k = 1, n = 10) {
agg <- x[endpoints(x, on, k)]
sma <- SMA(agg, n)
# merge with zero-width xts object w/original index, filling NA
result <- merge(sma, xts(,index(x)), fill = na.locf)
return(result)
}
add.indicator(strategy.st, name = "mySMA",
arguments = list(x = quote(Cl(mktdata)),
on = "weeks",
n = nSMA),
label = "SMAw1")
test <- applyIndicators(strategy.st, mktdata = OHLC(SPY))
Now the indicator will have a value for every observation in mktdata when it's merged.
> tail(merge(SPY, test$SMA))
SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted SMA.SMAw1
2016-11-25 221.10 221.56 221.01 221.52 37861800 221.52 215.0720
2016-11-28 221.16 221.48 220.36 220.48 70284100 220.48 215.0720
2016-11-29 220.52 221.44 220.17 220.91 67079400 220.91 215.0720
2016-11-30 221.63 221.82 220.31 220.38 99783700 220.38 215.0720
2016-12-01 220.73 220.73 219.15 219.57 77230500 219.57 215.0720
2016-12-02 219.67 220.25 219.26 219.68 70863400 219.68 215.3207

quantstrat signal referencing other signals

What is the correct method to have signals reference other signals? Is it not intended functionality? I cant seem to find a way to do it in my code.
library(PerformanceAnalytics)
library(quantmod)
library(lattice)
startDate <- '2010-01-01' # start of data
endDate <- '2015-05-01' # end of data
.blotter<-new.env()
.strategy<-new.env()
Sys.setenv(TZ="EST") # set time zone
symbols<-c("GOOG")
data<-getSymbols(symbols, from=startDate, to=endDate, index.class="POSIXct",env=NULL)
library(quantstrat)
initDate <- '2009-12-31'
initEq <- 1e6
currency("USD")
stock(symbols, currency="USD", multiplier=1)
rm.strat("multiAsset.bb1") # remove portfolio, account, orderbook if re-run
initPortf(name="multiAsset.bb1", symbols, initDate=initDate)
initAcct(name="multiAsset.bb1", portfolios="multiAsset.bb1",initDate=initDate, initEq=initEq)
initOrders(portfolio="multiAsset.bb1", initDate=initDate)
strategy("bbands", store=TRUE)
#Indicators are applied before signals and rules, and the output of indicators may be used as inputs to construct signals or fire rules
#mktdata is the time series object that holds the current symbols data during evaluation (pg 55)
add.indicator("bbands", name = "BBands",arguments = list(HLC = quote(HLC(mktdata)), maType='SMA'), label='bbInd')
test <- applyIndicators("bbands", mktdata=data)
head(test, 10)
add.signal("bbands", name="sigThreshold", arguments=list(columns=c("pctB.bbInd",".77"),relationship="gt"),label="H.gt.UpperBand")
add.signal("bbands", name="sigThreshold", arguments=list(columns=c("H.gt.UpperBand","0"),relationship="gt"),label="true.upper.band")
test <- applySignals("bbands", mktdata=test)
head(test, 10)
Error
Error in match.names(column, colnames(data)) :
argument "column" is missing, with no default
Note that this is a generalized example. It would be trivial to make the first signal an indicator and avoid this problem in this specific case.
You've passed the wrong arguments to sigThreshold. This corrected code works as expected, with the second signal using the H.gt.UpperBand column (singular) from the first signal. The missing arguments in your code for the sigThreshold function are column (singular) and threshold.
library(quantstrat)
startDate <- '2010-01-01' # start of data
endDate <- '2015-05-01' # end of data
Sys.setenv(TZ="EST") # set time zone
symbols<-c("GOOG")
data<-getSymbols.yahoo(symbols, from=startDate, to=endDate, index.class="POSIXct",auto.assign=FALSE)
initDate <- '2009-12-31'
initEq <- 1e6
currency("USD")
stock(symbols, currency="USD", multiplier=1)
rm.strat("multiAsset.bb1") # remove portfolio, account, orderbook if re-run
initPortf(name="multiAsset.bb1", symbols, initDate=initDate)
initAcct(name="multiAsset.bb1", portfolios="multiAsset.bb1",initDate=initDate, initEq=initEq)
initOrders(portfolio="multiAsset.bb1", initDate=initDate)
strategy("bbands", store=TRUE)
#Indicators are applied before signals and rules, and the output of indicators may be used as inputs to construct signals or fire rules
#mktdata is the time series object that holds the current symbols data during evaluation (pg 55)
add.indicator("bbands"
, name = "BBands"
, arguments = list(HLC = quote(HLC(mktdata))
, maType='SMA')
, label='bbInd')
test <- applyIndicators("bbands", mktdata=data)
head(test, 10)
add.signal("bbands"
, name="sigThreshold"
, arguments=list(column="pctB.bbInd"
, threshold=.77
, relationship="gt")
, label="H.gt.UpperBand")
add.signal("bbands"
, name="sigThreshold"
, arguments=list(column="H.gt.UpperBand"
, threshold=0
, relationship="gt")
,label="true.upper.band")
test <- applySignals("bbands", mktdata=test)
head(test, 10)

checking if value is greater or less then specified value

I am trying to tell whether a specific column value is greater than .77, but this code returns 1 if the value is greater then 0. Is there any way to use a known function (not a custom one) to do a simple greater then check?
library(PerformanceAnalytics)
library(quantmod)
library(lattice)
startDate <- '2010-01-01' # start of data
endDate <- '2015-05-01' # end of data
.blotter<-new.env()
.strategy<-new.env()
Sys.setenv(TZ="EST") # set time zone
symbols<-c("GOOG")
data<-getSymbols(symbols, from=startDate, to=endDate, index.class="POSIXct",env=NULL)
library(quantstrat)
initDate <- '2009-12-31'
initEq <- 1e6
currency("USD")
stock(symbols, currency="USD", multiplier=1)
rm.strat("multiAsset.bb1") # remove portfolio, account, orderbook if re-run
initPortf(name="multiAsset.bb1", symbols, initDate=initDate)
initAcct(name="multiAsset.bb1", portfolios="multiAsset.bb1",initDate=initDate, initEq=initEq)
initOrders(portfolio="multiAsset.bb1", initDate=initDate)
strategy("bbands", store=TRUE)
#Indicators are applied before signals and rules, and the output of indicators may be used as inputs to construct signals or fire rules
#mktdata is the time series object that holds the current symbols data during evaluation (pg 55)
add.indicator("bbands", name = "BBands",arguments = list(HLC = quote(HLC(mktdata)), maType='SMA'), label='bbInd')
test <- applyIndicators("bbands", mktdata=data)
head(test, 10)
add.signal("bbands", name="sigThreshold", arguments=list(columns=c("pctB.bbInd",".77"),relationship="gt"),label="H.gt.UpperBand")
test <- applySignals("bbands", mktdata=test) #DOESNT WORK
head(test, 10)
Error:
Error in match.names(column, colnames(data)) :
argument "column" is missing, with no default
My solution was to change:
add.signal("bbands", name="sigThreshold", arguments=list(columns=c("pctB.bbInd",".77"),relationship="gt"),label="H.gt.UpperBand")
to:
add.signal("bbands", name="sigThreshold", arguments=list(threshold=.77,column="pctB.bbInd",relationship="gt"),label="H.gt.UpperBand")

Error when adding a signal in quantstrat package

I am new to R and am trying to create a very simple trading strategy (Buy the VIX when it's up by 2%, sell it when it's down by 2%). I am getting an error with the add.signal command: "Error in match.names(column, colnames(data)) :
argument "column" is missing, with no default."
I've searched everywhere and I can't seem to find the fix or understand what R is trying to tell me. Any input would be appreciated.
require(quantstrat)
options("getSymbols.warning4.0"=FALSE) #suppress warnings
rm(list=ls(.blotter), envir=.blotter) #house cleaning, clears blotter
rm(list=ls(.strategy), envir=.strategy)#clears strategy
rm.strat(qs.portfolio)#clear the portfolio environment
rm.strat(qs.strategy)#clear the strategy environment
rm.strat(qs.account)#clear the account environment
currency("USD")
stock("VIX",currency="USD",multiplier=1)
# system settings
initDate <- '2013-12-31'
startDate <- '2014-01-01'
endDate <- '2016-04-07'
initEq <- 100000
Sys.setenv(TZ="UTC") #Timezone
getSymbols('^VIX', from=startDate, to=endDate, index.class="POSIXct", adjust=TRUE)
VIX$lagROC <- lag(round(ROC(Cl(VIX)), 4), n=1, type="discrete")
VIX$lagROC[is.na(VIX$lagROC)] <- 0
# initialize portfolio, account, orders
qs.strategy <- "qsJones"
initPortf(qs.strategy,'VIX')
initAcct(qs.strategy,portfolios=qs.strategy, initEq=initEq)
initOrders(portfolio=qs.strategy)
#create a new strategy object
strategy(qs.strategy,store=TRUE)
strat <- getStrategy(qs.strategy)
thresh1 <- (.02*-1)
thresh2 <- .02
add.indicator(strategy = qs.strategy, name = "ROC",
arguments = list(x = quote(Cl(mktdata)), n=1), label="lagROC")
test <- applyIndicators(qs.strategy, VIX)
add.signal(qs.strategy, name="sigThreshold",
arguments=list(column="lagROC", threshold=thresh1, relationship="lte", cross=FALSE),
label="lt.ROCThresh1")
add.signal(qs.strategy, name="sigThreshold",
arguments=list(column="lagROC", threshold=thresh2, relationship="gte", cross=FALSE),
label="gt.ROCThresh2")
test <- applySignals(qs.strategy, test)
# exit when lagROC < .02
add.rule(qs.strategy, name='ruleSignal',
arguments=list(sigcol="Cl.lt.lagROC", sigval=TRUE, replace=FALSE, orderqty='all',
ordertype='market', orderside='long'),
type='exit', path.dep=TRUE)
# go long when lagROC > .02
add.rule(qs.strategy, name='ruleSignal',
arguments=list(sigcol="Cl.gt.lagROC", sigval=TRUE, replace=FALSE, orderqty=1500,
ordertype='market', orderside='long'),
type='enter', path.dep=TRUE)
applyStrategy(strategy=qs.strategy , portfolios=qs.strategy)
tail(mktdata)
mktdata["2014"]
getTxns(Portfolio=qs.strategy, Symbol="VIX")
Your add.signal calls create two columns: "lt.ROCThresh1" and "gt.ROCThresh2", while your add.rule calls reference columns "Cl.lt.lagROC" and "Cl.gt.lagROC" (which don't exist).
You need to either:
Change the label= argument in your add.signal calls from "lt.ROCThresh1" and "gt.ROCThresh2" to "Cl.lt.lagROC" and "Cl.gt.lagROC", respectively, or
Change the sigcol= argument in your add.rule calls from "Cl.lt.lagROC" and "Cl.gt.lagROC" to "lt.ROCThresh1" and "gt.ROCThresh2", respectively.

Quantstrat logical error while running applySignals - missing value where TRUE/FALSE needed

I am having this error while running a strategy back-testing in the R, using Quantstrat package. Whenever, I try to use applySignals function to test the signals, it shows the logical error. I tried to remove the NAs by na.omit(FB) command, but when you calculate Simple Moving Average, you will have the NAS in the beginning. Can somebody suggest me the solution?
Thanks,
require(PerformanceAnalytics)
require(quantstrat)
require(quantmod)
require(blotter)
initDate="2015-01-01"
from="2015-01-02"
to="2015-06-30"
options(width=100)
currency('USD')
Sys.setenv(TZ="UTC")
symbols = c("SPY", "FB", "TWTR")
getSymbols(symbols, from=from, to=to, src="yahoo", adjust=TRUE)
stock(symbols, currency="USD", multiplier=1)
suppressWarnings(rm("account.MAC","portfolio.MAC",pos=.blotter))
suppressWarnings(rm("order_book.MAC",pos=.strategy))
tradeSize <- 1000
initEq <- tradeSize
strategy.st <- portfolio.st <- account.st <- "MAC"
rm.strat(strategy.st)
initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD')
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD', initEq=initEq)
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)
#parameters
nFast = 10
nSlow = 30
#indicators
add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)[,1]), n=nFast),
label="nFast")
add.indicator(strategy.st, name="SMA",
arguments=list(x=quote(Cl(mktdata)[,1]), n=nSlow),
label="nSlow")
test <- applyIndicators(strategy.st, mktdata=Cl(FB))
head(test, 5)
#signals
add.signal(strategy.st, name="sigCrossover",
arguments=list(columns=c("nFast", "nSlow"), relationship="gt"),
label="longEntry")
add.signal(strategy.st, name="sigCrossover",
arguments=list(columns=c("nFast", "nSlow"), relationship="lt"),
label="longExit")
test2 <- applySignals(strategy.st, mktdata=Cl(FB))
Error: Error in if (length(j) == 0 || (length(j) == 1 && j == 0)) { :
missing value where TRUE/FALSE needed
I was able to solve the issue with my code.
So, if I only use mktdata object instead of mktdata = Cl(FB), Quantstrat is working fine. I am not able to understand fully why it is working that way, but somehow it worked fine.
test2 <- applySignals(strategy.st, mktdata)

Resources