TrailStop Algo with 200Dma Filter, Simple Question - Thanks

Hi, having issues with integrating a N Day Sma Filter to a Long/Short TrailStop strategy. I have the trails calculated somewhat (via min/max) problem is i want to only take Long trail signals if price > 200dma and only short trail signals when < 200dma. Also the price cross below or above N day sma should override any trail stop thats active at that moment. I think i have the if and else conditions wrongly structured, could someone please look it over.

9
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
from pytz import timezone

lock_dt = get_datetime().astimezone(timezone("US/Eastern"))
if lock_dt.hour == 15 and lock_dt.minute == 55:
return True
else:
return False

def initialize(context):

context.stock = symbol("AAPL")

# stop-loss percent
context.stop_pct = .89

# stops dictionary
context.stop = 11

def handle_data(context, data):

return

price_history = history(200, "1d", "close_price")
timeseries = price_history[context.stock]
maverage = talib.SMA(timeseries, 142)[-1]
price = data[context.stock].price
qty = context.portfolio.positions[context.stock].amount
#cash = context.portfolio.capital_used[context.stock].amount

if qty == 0 and price < maverage:
order_target_percent(context.stock, -1)

# set trailing stop-loss
context.stop = data[context.stock].price * context.stop_pct

# check stop-loss for existing long position
elif qty > 0:

# if price has dropped below stop-loss
if data[context.stock].price < context.stop:

# reverse position (negative amount for short minus existing position)
order_target_percent(context.stock, -1)

# set trailing stop-loss (*above* current price for new short)
context.stop = data[context.stock].price / context.stop_pct

# otherwise price is still above stop-loss
else:
# update trailing stop-loss (*below* current price for existing long)
context.stop = max(data[context.stock].price * context.stop_pct, context.stop)

# check stop-loss for existing short position
elif qty < 0:

# if price has risen above stop-loss
if data[context.stock].price > context.stop:

# reverse position (positive amount for long minus existing position)
order_target_percent(context.stock, 1)

# set trailing stop-loss (*below* current price for new long)
context.stop = data[context.stock].price * context.stop_pct

# otherwise price is still below stop-loss
else:
# update trailing stop-loss (*above* current price for existing short)
context.stop = min(data[context.stock].price / context.stop_pct, context.stop)

record(Price=data[context.stock].price,
Sma=maverage,
Stop=context.stop,
Position=qty)

"""
import talib
from pytz import timezone

# Set trade time at EOD/Close price
lock_dt = get_datetime().astimezone(timezone("US/Eastern"))
if lock_dt.hour == 16 and lock_dt.minute == 0:
return True
else:
return False

def initialize(context):

context.stock = symbol("AAPL")
context.stop_pct = .89 # stop-loss percent
context.stop = {} # set an initial stoploss value, no idea why its needed hre since context.stop is defined in code below

def handle_data(context, data):

# check if new day
return True

price_history = history(200, "1d", "close_price")
timeseries = price_history[context.stock]
maverage = talib.SMA(timeseries, 200)[-1]
price = data[context.stock].price
qty = context.portfolio.positions[context.stock].amount

# Set positions long or short, dont know how to set it to ccording to signal, in this case just tolid it to short if there are no pos.
# I want the algo to trade price/maverage cross, BUT if price above maverage - take only Long signals from context.stop
# if below maverage, take only Short signals from maverage
if qty == 0 and price < maverage:
order_target_percent(context.stock, -1)
# set trailing stop-loss to the created short pos
context.stop = data[context.stock].open_price / context.stop_pct

if qty == 0 and price > maverage:
order_target_percent(context.stock, 1)
# set trailing stop-loss to the created short pos
context.stop = data[context.stock].open_price * context.stop_pct

# check stop-loss for existing long position
elif qty > 0 and price > maverage:
# if price has dropped below stop-loss
if data[context.stock].price < context.stop:
# go flat
order_target_percent(context.stock, 0)
# set the stop for a new buyStop strigger (if price still > maverage)
context.stop = data[context.stock].open_price / context.stop_pct
# otherwise price is still above stop-loss
else:
# update trailing stop-loss for the existing long position (if price still > maverage)
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# check stop-loss for existing short position
elif qty < 0 and price < maverage:
# if price has risen above stop-loss
if data[context.stock].price > context.stop:
# go flat
order_target_percent(context.stock, 0)
# set the stop for a new sellStop strigger (if price still < maverage)
context.stop = data[context.stock].open_price * context.stop_pct
# otherwise price is still below stop-loss
else:
# update trailing stop-loss (*above* current price for existing short)
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)

record(Price=data[context.stock].price,
Sma=maverage,
Stop=context.stop,
Position=qty)
"""
There was a runtime error.
8 responses

Sorry, wrong backtest - here is the new one with code commented properly
Thanks

9
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
from pytz import timezone

# Setting trade time to only EOD/Close price
lock_dt = get_datetime().astimezone(timezone("US/Eastern"))
if lock_dt.hour == 16 and lock_dt.minute == 0:
return True
else:
return False

def initialize(context):
context.stock = symbol("AAPL")
# stop-loss percent
context.stop_pct = .89
# setting initial value for the stop, not sure why i need to do it here since it will be set when trigger occurs
# if i dont set it here then i get code error
context.stop = 11 # Just a generic value - getting it declared here so i dont get code error

def handle_data(context, data):
# Checking if its a new day
return
# Calculating average etc.
price_history = history(200, "1d", "close_price")
timeseries = price_history[context.stock]
maverage = talib.SMA(timeseries, 142)[-1]
price = data[context.stock].price
qty = context.portfolio.positions[context.stock].amount

# START OF TRADE EXECUTION CODE - I need a hand with this, thanks
# If no position, check if price above or below maverage, initiate a trade accordingly
if qty <= 0 and price > maverage:
order_target_percent(context.stock, 1)
# set trailing stop-loss below open price
context.stop = data[context.stock].open_price * context.stop_pct
# if no position and price below maverage, sell
if qty >= 0 and price < maverage:
order_target_percent(context.stock, -1)
# set trailing stop-loss above open price
context.stop = data[context.stock].open_price / context.stop_pct

# check for existing long position
elif qty > 0:
# if price has dropped below stop-loss but price  > maverage
if data[context.stock].price < context.stop and price > maverage:
# go flat
order_target_percent(context.stock, 0)
# set a new buy stop above, if triggered when price > maverage, it should buy
context.stop = data[context.stock].open_price / context.stop_pct

# otherwise price is still above stop-loss
if data[context.stock].price > context.stop:
# update trailing stop-loss below the long position
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# check for existing short position
elif qty < 0:
# if price has rallied above stop-loss but price < maverage
if data[context.stock].price > context.stop and price < maverage:
# go flat
order_target_percent(context.stock, 0)
# set a new buy stop below, if triggered when price < maverage, it should sell
context.stop = data[context.stock].open_price * context.stop_pct

# otherwise price is still below stop-loss
if data[context.stock].price < context.stop:
# update trailing stop-loss above the short position
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)

record(Price=data[context.stock].price,
Sma=maverage,
Stop=context.stop,
Position=qty)
There was a runtime error.

I think you are on the right track, I changed a couple small things. It checks for the sell conditions first and updates the stop price no matter what since you use the min/max trailing stop. I made all the elif statements if statements because they shouldn't interfere with each other. It doesn't process the rest of the bar if it closes its position, it will wait until the next bar for a buy/sell signal. I also have it initializing the stop price with None.

9
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
from pytz import timezone

# Setting trade time to only EOD/Close price
lock_dt = get_datetime().astimezone(timezone("US/Eastern"))
if lock_dt.hour == 16 and lock_dt.minute == 0:
return True
else:
return False

def initialize(context):
context.stock = symbol("AAPL")
set_benchmark(context.stock)
# stop-loss percent
context.stop_pct = .89
# setting initial value for the stop, not sure why i need to do it here since it will be set when trigger occurs
# if i dont set it here then i get code error
context.stop = None # Just a generic value - getting it declared here so i dont get code error

def handle_data(context, data):
# Checking if its a new day
return
# Calculating average etc.
price_history = history(200, "1d", "close_price")
timeseries = price_history[context.stock]
maverage = talib.SMA(timeseries, 142)[-1]
price = data[context.stock].price
qty = context.portfolio.positions[context.stock].amount

# check for existing long position
if qty > 0:
# Update the stoploss no matter what
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# if price has dropped below stop-loss but price  > maverage
if data[context.stock].price < context.stop and price > maverage:
# go flat
order_target(context.stock, 0)
# set a new buy stop above, if triggered when price > maverage, it should buy
context.stop = None#.open_price / context.stop_pct

# Don't do anything else on this bar
return

# check for existing short position
if qty < 0:
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)
# if price has rallied above stop-loss but price < maverage
if data[context.stock].price > context.stop and price < maverage:
# go flat
order_target_percent(context.stock, 0)
# set a new buy stop below, if triggered when price < maverage, it should sell
context.stop = None #data[context.stock].open_price * context.stop_pct
return

# START OF TRADE EXECUTION CODE - I need a hand with this, thanks
# If no position, check if price above or below maverage, initiate a trade accordingly
if qty <= 0 and price > maverage:
order_target_percent(context.stock, 1)
# set trailing stop-loss below open price
context.stop = data[context.stock].open_price * context.stop_pct

# if no position and price below maverage, sell
if qty >= 0 and price < maverage:
order_target_percent(context.stock, -1)
# set trailing stop-loss above open price
context.stop = data[context.stock].open_price / context.stop_pct

record(Price=data[context.stock].price,
Sma=maverage,
Stop=context.stop,
Position=qty)
There was a runtime error.

Hi David and thanks for the mods, its almost quite what i had in mind, need one more alteration, please look at the graph, hope its clear.
I think the code needs one more set of trade conditions (reverse conditions?) that would define beahaviour in respect to the trail stop (setting and obeying the BuyStop/SellStop depending on on what side of maverage the price is)
https://www.dropbox.com/s/u7mcz6ugkk3niqo/Screen%20Shot%202014-08-18%20at%2023.23.52.png

I took a closer look and I think I see your problem, correct me if I'm wrong. When your trailing stop is triggered, it does try to go flat, but because it is still above its moving average, it immediately re-enters the position on the next bar. It's is probably symmetric on the short side too.

If that's the problem, you'll have to come up with some logic to handle when your algo enters that no-mans land after a trailing stop is triggered, but before the price has crossed to the other side of the moving average. You'll need some type of re-entry rule before it can trade on the same side again. Hopefully it's an easy fix, but I think that's what is causing the problem

David, you are correct. I got it so far that it behaves as it should when in long mode (price > maverage) and it even trails the stop down when in short mode (price

3
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
from pytz import timezone

# Setting trade time to only EOD/Close price
lock_dt = get_datetime().astimezone(timezone("US/Eastern"))
if lock_dt.hour == 16 and lock_dt.minute == 0:
return True
else:
return False

def initialize(context):
context.stock = symbol("AAPL")
set_benchmark(context.stock)
# stop-loss percent
context.stop_pct = .89
context.stop = 10 # setting it to a number, so i can get an entry condition
context.longmode = None

def handle_data(context, data):
# Checking if its a new day
return

price_history = history(200, "1d", "close_price")
timeseries = price_history[context.stock]
maverage = talib.SMA(timeseries, 142)[-1]
price = data[context.stock].price
qty = context.portfolio.positions[context.stock].amount

## LONG MODE (PRICE > MAVERAGE)
# check for existing long position
if qty > 0 and price > maverage:
# if price has dropped below stop-loss
if data[context.stock].price < context.stop:
# go flat
order_target(context.stock, 0)
# set a new buy stop above
context.stop = data[context.stock].open_price / context.stop_pct

# otherwise trail the stop up
else:
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# If algo has hit a stop/is flat while price > maverage
if qty == 0 and price > maverage:
# if price has rallied above the Buy Stop
if data[context.stock].price > context.stop:
# go long again
order_target(context.stock, 1)
# set a new buy stop below
context.stop = data[context.stock].open_price * context.stop_pct

# otherwise trail the buy stop down
else:
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)

## SHORT MODE (PRICE < MAVERAGE)
# check for existing short position
if qty < 0 and price < maverage:
# if price has dropped below stop-loss and price < maverage
if data[context.stock].price < context.stop:
# go short
order_target(context.stock, -1)
# set a new buy stop above
context.stop = data[context.stock].open_price / context.stop_pct

# otherwise trail the stop up
else:
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# If algo has hit a stop while in long mode (price > maverage)
if qty == 0 and price < maverage:
# if price has risen above stop-loss and below maverage
if data[context.stock].price > context.stop:
# go short
order_target(context.stock, 0)
# set a new sell stop below
context.stop = data[context.stock].open_price * context.stop_pct

# otherwise trail the buy stop down
else:
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)

record(Price=data[context.stock].price,
Sma=maverage,
Stop=context.stop,
Position=qty)
There was a runtime error.

Damit, it cropped all the text i had, here it is again

Its almost there, in long mode it behaves correct, here are the remaining issues
1. It should go long or short at the price crossing the maverage, no matter what stop is saying at that moment
2. Position sizes dont make sense, it only trades 1-2 shares max at this version
3. Stop behaviour when price below maverage is not correct, that is it trails down well but not when stopped out of short, you can see it on the graph when disabling Position plot

- Tried to add your datetime check for eod trading, but it did not proceed at all, i added this code below handle data

    time = str(get_datetime().astimezone(timezone("US/Eastern")))
if time != '16:00:00': # only trading at this time once a day
return

• Would it be better off using talib.atr ? (less code, as dont have to min/max the stops manually)

Thanks

Darell,
You could certainly use something like atr for your stops, theres no correct answer to that one really. This might be useful, but its pretty math heavy, Optimal Trading Stops and Algorithmic Trading. I'll take a closer look later.

It looks like you were using order_target when you meant to use order_target_percent, I changed that and now it doesn't just get the 1-2 shares.

399
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
import talib
from pytz import timezone

# Setting trade time to only EOD/Close price
lock_dt = get_datetime().astimezone(timezone("US/Eastern"))
if lock_dt.hour == 16 and lock_dt.minute == 0:
return True
else:
return False

def initialize(context):
context.stock = symbol("AAPL")
set_benchmark(context.stock)
# stop-loss percent
context.stop_pct = .89
context.stop = 10 # setting it to a number, so i can get an entry condition
context.longmode = None

def handle_data(context, data):
# Checking if its a new day
return

price_history = history(200, "1d", "close_price")
timeseries = price_history[context.stock]
maverage = talib.SMA(timeseries, 142)[-1]
price = data[context.stock].price
qty = context.portfolio.positions[context.stock].amount

## LONG MODE (PRICE > MAVERAGE)
# check for existing long position
if qty > 0 and price > maverage:
# if price has dropped below stop-loss
if data[context.stock].price < context.stop:
# go flat
order_target(context.stock, 0)
# set a new buy stop above
context.stop = data[context.stock].open_price / context.stop_pct

# otherwise trail the stop up
else:
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# If algo has hit a stop/is flat while price > maverage
if qty == 0 and price > maverage:
# if price has rallied above the Buy Stop
if data[context.stock].price > context.stop:
# go long again
order_target_percent(context.stock, 1)
# set a new buy stop below
context.stop = data[context.stock].open_price * context.stop_pct

# otherwise trail the buy stop down
else:
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)

## SHORT MODE (PRICE < MAVERAGE)
# check for existing short position
if qty < 0 and price < maverage:
# if price has dropped below stop-loss and price < maverage
if data[context.stock].price < context.stop:
# go short
order_target_percent(context.stock, -1)
# set a new buy stop above
context.stop = data[context.stock].open_price / context.stop_pct

# otherwise trail the stop up
else:
context.stop = max(data[context.stock].open_price * context.stop_pct, context.stop)

# If algo has hit a stop while in long mode (price > maverage)
if qty == 0 and price < maverage:
# if price has risen above stop-loss and below maverage
if data[context.stock].price > context.stop:
# go short
order_target(context.stock, 0)
# set a new sell stop below
context.stop = data[context.stock].open_price * context.stop_pct

# otherwise trail the buy stop down
else:
context.stop = min(data[context.stock].open_price / context.stop_pct, context.stop)

record(Price=data[context.stock].price,
Sma=maverage,
Stop=context.stop,
Position=qty)
There was a runtime error.