Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Feedback Request: Moving Average Crossover with Trailing Stop

This is my first go at creating my own algorithm and I would like some feedback.

This algorithm purchases a stock when:

  1. 50-day Moving Average is Up-Trending
  2. 8-day Exponential Moving Average has crossed-over the 13-day Moving Average

and sells shares with a Trailing-Stop.

5 responses

The trailing stop is not implemented correctly; if there is a split, the stop_price you store in context will be in error.

After much consideration of share splits, I'm not so sure that my implementation of a trailing stop is incorrect.

It is my understanding that the entire price data history of a stock is adjusted to the current split, as a means of preventing misleading gaps in the price history of a stock. If this is true for Quantopian's data.history, then my trailing stop implementation should be correct.

From http://www.investopedia.com/ask/answers/05/splitleadgapping.asp:
"The reason gaps are not seen in stock charts after a stock split is because all of the past price data is adjusted to the current split."

Day 1 - Stock price == 100, context.stop_price == 90, context.stop_price = max(90,75) == 90
--overnight, stock splits 10:1--
Day 2 - Stock price == 10, context.stop_price == 90, context.stop_price = max(90,7.5) == 90
Day 2 (cont) - stock is immediately sold.

EDIT: To be clear, the issue is not that quantopian doesn't split-adjust their data, it's that you are storing a price (or price-derived-value) overnight in the context without split-adjusting it too. You need to do that by hand.

Edit: There is error in my logic here which doesn't account for order that did not get filled overnight. Working on a fix.

I see the issue, and I believe I have come up with a solution:

Before trading starts, I check to see if my position in a stock has been split overnight. If the stock was split, I determine the split ratio and apply this ratio to my stop price:

> def initialize(context):  
>      ...  
>      context.position_amount = 0  
>      ...  
>  
> def before_trading_start(context, data):  
>     if context.portfolio.positions[context.stock].amount != 0:  
>  
>         # If the stock split overnight, adjust the context.stop_price  
>         if context.portfolio.positions[context.stock].amount != context.position_amount:  
>             shares_ratio = context.position_amount / context.portfolio.positions[context.stock].amount  
>             context.stop_price_old = context.stop_price  
>             context.stop_price = context.stop_price * shares_ratio  
>             log.info(context.stop_price_old, context.stop_price)

Thankyou @Simon Thornington for the insightful feedback.

Quantopian...if you are listening, It would be nice to incorporate a 'Trailing Stop' (that can account for stock splits) into the available 'Order types'.

Yeah that makes sense. You might also want to consider what your stop price should do if a dividend is paid out. Typically dividends are not economically meaningful events, so the stop should be adjusted downward for those too.