[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