[R-SIG-Finance] refining trailing stop loss in simple trend following strategy
Rodger Dodger
dodgerdodger12 @end|ng |rom gm@||@com
Mon Mar 11 23:13:39 CET 2019
Dear All,
Im after some help with the trailing stop loss functionality in quanstrat.
I have written a simple script that uses EMAs as a trend filter, enters
positions based on breakouts from Donchian Channels and rides the position
with a trailing stop loss based on ATR.
The script runs ok but Ive run into the following problems trying to refine
this strategy in quantstrat.
1. When specifying the ATR lookback period, anything above n=1 generates an
error "Error in if (threshold > 0) threshold = -threshold :
missing value where TRUE/FALSE needed"
Can anyone explain whats going on here? I'd like to set the look back
window much further.
Also - is the ATR stop loss working as it should? This seems to hinge on
the threshold part of the 'ruleSignal' function. Could anyone explain how
this part works? I could not find any documentation.
2. Ideally, I want the ATR stop loss to only move in the direction of the
winning position. E.g. if we are long and the position moves in our favour
then the stop moves up with the Close - 2*ATR band. However, if the price
moves down I want the ATR to remain fixed at the last highest value,
rapidly closing out the winning position. This what I currently do manually
but would love to have a way of automating it. Im struggling to think of a
way to do this within the quantstrat framework.
Below I copy a reproducible version of the script.
Any guidance would be gratefully received.
Rodg
# packages
require(IKTrading)
require(knitr)
# settings
currency('USD')
Sys.setenv(TZ="UTC")
# variables
start_date <- Sys.Date() -365
end_date <- Sys.Date()
init_equity <- 1e6
tradesize <- 100
adjustment <- TRUE
# stock data
symbols <- c("MSFT", "IBM") #symbols used in our backtest
getSymbols(Symbols = symbols, src = "yahoo", from= start_date, to= end_date,
adjust = TRUE) #receive data
stock(symbols, currency = "USD", multiplier = 1) #tells quanstrat what
instruments present and what currency to use
#### STRATEGY
strategy.st <- portfolio.st <- account.st <- "firststrat" #naming strategy,
portfolio and account
#removes old portfolio and strategy from environment
rm.strat(portfolio.st)
rm.strat(strategy.st)
#initialize portfolio, account, orders and strategy objects
initPortf(portfolio.st, symbols = symbols, currency = "USD")
initAcct(account.st, portfolios = portfolio.st, currency = "USD", initEq =
init_equity)
initOrders(portfolio.st)
strategy(strategy.st, store=TRUE)
#Plots
candleChart(MSFT, up.col = "green", dn.col = "red", theme = "white")
addEMA(n = c(26,12), on = 1, col = c("red", "blue"))
DCH <- DonchianChannel(MSFT[,2:3], n=20, include.lag = TRUE)
plot(addTA(DCH$high, on=1, col='red'))
plot(addTA(DCH$low, on=1, col='blue'))
candleChart(IBM, up.col = "black", dn.col = "red", theme = "white")
addEMA(n = c(26,12), on = 1, col = c("red", "blue"))
DCH <- DonchianChannel(IBM[,2:3], n=20, include.lag = TRUE)
plot(addTA(DCH$high, on=1, col='red'))
plot(addTA(DCH$low, on=1, col='blue'))
## INDICATORS
# 26 EMA
add.indicator(strategy = strategy.st,
name = 'EMA',
arguments = list(x = quote(Cl(mktdata)), n=26),
label = 'EMA26')
# 12 EMA
add.indicator(strategy = strategy.st,
name = 'EMA',
arguments = list(x = quote(Cl(mktdata)), n=12),
label = 'EMA12')
# Add the Donchian indicator
add.indicator(strategy = strategy.st,
# correct name of function:
name = "DonchianChannel",
arguments = list(HL = quote(HLC(mktdata)[, 2:3]), n = 20,
include.lag = TRUE),
label = "Donchian")
### SIGNALS
## Long
#1: sigComparison specifying when 12-period EMA above 26-period EMA
add.signal(strategy.st,
name = 'sigComparison',
arguments = list(columns=c("EMA12", "EMA26"), relationship = "gt"
),
label = "longfilter")
#2: Price over the Donchian
add.signal(strategy.st,
name="sigComparison",
arguments=list(columns=c("Close","high.Donchian"),relationship=
"gt"),
label="Hi.gt.Donchian")
#Enter long when DC break out plus EMAs crossed
add.signal(strategy.st,
name = "sigFormula",
arguments = list(formula = "longfilter & Hi.gt.Donchian",
cross = TRUE),
label = "longentry")
## Short
#1: sigComparison specifying when 12-period EMA below 26-period EMA
add.signal(strategy.st,
name = 'sigComparison',
arguments = list(columns=c("EMA12", "EMA26"), relationship = "lt"
),
label = "shortfilter")
#2: crosses under the Donchian
add.signal(strategy.st,
name="sigComparison",
arguments=list(columns=c("Close","low.Donchian"), relationship=
"lt"),
label="Lo.lt.Donchian")
#Enter short when DC break down plus EMAs crossed
add.signal(strategy.st,
name = "sigFormula",
arguments = list(formula = "shortfilter & Lo.lt.Donchian",
cross = TRUE),
label = "shortentry")
## ATR Stops
stopATR <- function(HLC, n, maType, noATR){
stop.atr <- noATR * ATR(HLC=HLC, n=n, maType=maType)
return(stop.atr)
}
add.indicator(strategy = strategy.st,
name = "stopATR",
arguments = list(HLC=quote(HLC(mktdata)[, 2:4]), n=1, maType="EMA", noATR=
2))
## RULES
## Exits
# exit longs
add.rule(strategy.st,
name='ruleSignal',
arguments = list(sigcol="longentry",
sigval=TRUE,
orderqty='all',
ordertype='stoptrailing',
orderside='long',
threshold='atr.stopATR.ind',
tmult=FALSE,
replace=FALSE,
orderset='long'
),
type='chain',
parent='EnterLONG',
label='ExitLong')
# exit shorts
add.rule(strategy.st,
name='ruleSignal',
arguments = list(sigcol="shortentry",
sigval=TRUE,
orderqty='all',
ordertype='stoptrailing',
orderside='short',
threshold='atr.stopATR.ind',
tmult=FALSE,
replace=FALSE,
orderset='short'
),
type='chain',
parent='EnterSHORT',
label='ExitShort')
## Entries
# Enter long
add.rule(strategy.st, name='ruleSignal',
arguments=list(sigcol='longentry' , sigval=TRUE,
orderside='long' ,
ordertype='market', prefer='High',
orderqty= tradesize,
osFUN=osMaxPos,
replace=FALSE,
orderset='long'
),
type='enter',
label='EnterLONG'
)
# Enter short
add.rule(strategy.st, name='ruleSignal',
arguments=list(sigcol='shortentry', sigval=TRUE,
orderside='short',
ordertype='market', prefer='Low',
orderqty=-tradesize,
osFUN=osMaxPos,
replace=FALSE,
orderset='short'
),
type='enter',
label='EnterSHORT'
)
# restrict to 1 entry per side.
for(symbol in symbols){
addPosLimit(portfolio = portfolio.st,
symbol = symbol,
timestamp = start_date,
maxpos = tradesize)
}
## PERFORMANCE ANALYTICS
out <- applyStrategy(strategy = strategy.st, portfolios = portfolio.st)
updatePortf(portfolio.st)
daterange <- time(getPortfolio(portfolio.st)$summary)[-1]
updateAcct(account.st, daterange)
updateEndEq(account.st)
# look at orderbook
ob <- getOrderBook(portfolio.st)
# orderbook for each symbol
ob_MSFT <- data.frame(ob$firststrat$MSFT)
ob_IBM <- data.frame(ob$firststrat$IBM)
# plot trades
myTheme<-chart_theme()
myTheme$col$dn.col<-'lightblue'
myTheme$col$dn.border <- 'lightgray'
myTheme$col$up.border <- 'lightgray'
chart.Posn(Portfolio = portfolio.st, theme=myTheme, Symbol = "MSFT",
TA= c("add_EMA(n=12, col='blue')", "add_EMA(n=26, col='red')"))
chart.Posn(Portfolio = portfolio.st, theme=myTheme, Symbol = "IBM",
TA= c("add_EMA(n=12, col='blue')", "add_EMA(n=26, col='red')"))
# get trad stats
tstats <- tradeStats(portfolio.st)
kable(t(tstats))
[[alternative HTML version deleted]]
More information about the R-SIG-Finance
mailing list