Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Can I Use A Buy-Stop Order?

If I short a stock I would like to place a Buy-Stop order so that I cover the position if the price goes up by a specified amount. Can I do this with the available order types in Quantopian?

I assume I'm doing something wrong as this

order(Sid,  1, limit_price=data[Sid].close_price * 1000)       # 1000 chosen for emphasis only!  

executes at the next bar irrespective of price i.e.

Code (plus some code not shown to print the order the next day):

print data[Sid].close_price  
orderid = order(Sid,  1, limit_price=data[Sid].close_price * 1000)  
print get_order(orderid)  

Log:

2003-01-08PRINT26.99

2003-01-08PRINTEvent({'status': 0, 'created': datetime.datetime(2003, 1, 8, 0, 0,  
tzinfo=<UTC>), 'limit_reached': False, 'stop': None, 'stop_reached': False,  
'amount': 1, 'limit': 26990.0, 'sid': Security(122, symbol=u'ADI',
security_name=u'ANALOG DEVICES INC', start_date=datetime.datetime(1993, 1, 4, 5, 0,  
tzinfo=<UTC>), end_date=datetime.datetime(2013, 10, 14, 5, 0,  
tzinfo=<UTC>), first_traded=None), 'dt': datetime.datetime(2003, 1, 8, 0, 0,  
tzinfo=<UTC>), 'id': '1490d0770614414dbec8ab0c5063d3a4', 'filled': 0})

2003-01-09PRINTEvent({'status': 1, 'created': datetime.datetime(2003, 1, 8, 0, 0,  
tzinfo=<UTC>), 'limit_reached': True, 'stop': None, 'stop_reached': False, 'amount': 1,  
'limit': 26990.0, 'sid': Security(122, symbol=u'ADI',
security_name=u'ANALOG DEVICES INC', start_date=datetime.datetime(1993, 1, 4, 5, 0,  
tzinfo=<UTC>), end_date=datetime.datetime(2013, 10, 14, 5, 0,  
tzinfo=<UTC>), first_traded=None), 'dt': datetime.datetime(2003, 1, 9, 0, 0,  
tzinfo=<UTC>), 'id': '1490d0770614414dbec8ab0c5063d3a4', 'filled': 1})  

Transaction:

2003-01-09 00:00:00     ADI     BUY     1   $28.37  $28.37  

P.

10 responses

Hi Peter,

Our backtester gives you four order type options, including stop and stop limit orders. See the docs here:
https://www.quantopian.com/help#ide-ordering

NB: The initial live trading integration with Interactive Brokers will only support market and limit orders. So if you are concerned with near-term portability to tradeable code I would suggest creating explicit stop-loss logic in your algo.

-Jess

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Hello Jess,

Thanks - that was what I was thinking.

I have sent feedback but does the example above look right to you? It says 'limit_reached': True whch I don't understand.

P.

I have to assume no one on Quantopian is using anything other than market orders. Here's a zipline issue raised a month ago:

https://github.com/quantopian/zipline/issues/217

The simple test David Q. wrote is attached.

P.

By using a simple zipline algo and then amending my local zipline I have confirmed this is the zipline issue first found by another user and reported here: https://github.com/quantopian/zipline/issues/217

If anyone wants to get started with a very simple zipline algo I used this:

from datetime import datetime  
import pytz

from zipline.algorithm import TradingAlgorithm  
from zipline.utils.factory import load_from_yahoo


class BuyApple(TradingAlgorithm):

    def initialize(self):  
        self.firstOrderplaced = False

    def handle_data(self, data):  
        print data['AAPL'].price  
        print self.portfolio.cash  
        if not self.firstOrderplaced:  
            self.order('AAPL', -100,)  
            self.order('AAPL', 100, limit_price=131.00)  
            self.firstOrderplaced = True  


if __name__ == '__main__':  
    start = datetime(2008, 1, 25, 0, 0, 0, 0, pytz.utc)  
    end = datetime(2008, 4, 1, 0, 0, 0, 0, pytz.utc)  
    data = load_from_yahoo(stocks=['AAPL'], indexes={}, start=start,  
                           end=end)  
    simple_algo = BuyApple()  
    results = simple_algo.run(data)  

Stop and limit orders are handled correctly if C:\Python27\Lib\site-packages\zipline\finance\slippage.py is amended as follows:

    if order.triggered:  
        return (order.stop_reached, order.limit_reached)

    stop_reached = False  
    limit_reached = False  
    # if the stop price is reached, simply set stop_reached  
    if order.stop is not None:  
        if (order.direction * (order.stop - event.price) <= 0):  
            # convert stop -> limit or market  
            stop_reached = True

    # if the limit price is reached, we execute this order at  
    # (event.price + simulated_impact)  
    # we skip this order with a continue when the limit is not reached  
    if order.limit is not None:  
        # if limit conditions not met, then continue  
        if (order.direction * (order.limit - event.price) <= 0):  
            limit_reached = True

    return (stop_reached, limit_reached)  

If you are trying to understand the zipline code you need to know that order.direction is -1 for a stop order and 1 for a limit order i.e.

Current price = 100.01, Limit = 100.00 then 1 * (100.00 - 100.01) = -0.01 so the limit has been reached

and

Current price = 99.99, Stop = 100.00 then -1 * (100.00 - 99.99) = -0.01 so the stop has been reached.

P.

The problem with stop orders got caught up in our work on getting live algos out, and I hadn't pushed the changes out to backtesting yet.

Currently we're not supporting stop orders in live trading - only market and limit orders. At this point I'm planning on making that change for backtesting, too. I'll move it up the list and get it done sooner.

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Hello Dan,

Limit orders don't work either. My Buy-Stop order in the original post is a Limit order. It's a Buy-Stop because it is used to flatten a short position. This is an issue in zipline 0.5.10.

P.

Peter, you're talking about this line, yes?

order(Sid,  1, limit_price=data[Sid].close_price * 1000)       # 1000 chosen for emphasis only!  

So I interpret that limit order as "Please buy a share of this stock as soon as it dips below this really high price." Since it's already below that really high price, the limit executes immediately.

Check out this backtest. As it opens, it places two orders:

        order(sid(24), 100, 126)  
        order(sid(24), -100, 250)  

The first is to go long if the price dips to 126; the second is to go short (or close) if the price hits 250. That executes the way I'd expect to.

Hello Dan,

Slowly the story emerges....

Your example above should read:


        order(sid(24), 100, limit_price=126)  
        order(sid(24), -100, limit_price=250)  

in which case the first is a Buy Limit order and the second is a Sell Limit order. Not the most useful of order types, I suspect. And today is the first I have heard that you do not at present support the more useful

        order(sid(24), -100, stop_price=126)  
        order(sid(24), 100, stop_price=250)  

which are a Sell Stop and a Buy Stop. As these are used to exit losing long and short positions respectively I suspect they are of more immediate use.

So your API page is a little wrong. And I think

  • limit order: Use order(sid, amount, limit_price=price) to place a
    limit order. A limit order executes at the specified price or better,
    if the price is reached.

would better read

  • limit order: Use order(sid, amount, limit_price=price) to place a
    limit order. A buy limit order is placed at a price below the current
    market price and the order executes at the specified price or lower,
    if the price is reached. A sell limit order is placed at a price
    above the current market price and the order executes at the
    specified price or higher, if the price is reached.

My zipline 'fix' implements the two more useful order types. But then I would say that!

P.

Your sample code is more specific than mine, thank you. But they should have the exact same result. I used your orders in my backtest, below.

I think that Buy Limit and Sell Limits are useful for some people in some situations. Sometimes a market order can fill at a price you don't like, or sometimes a stock can touch a low point briefly - limit orders manage both those problems well.

The stop_price problems I definitely apologize for. There is a bug, and we haven't resolved it as quickly as I'd like.

I think that our API page (for limit orders) is correct, but again, you've improved it with more specificity. I'll make that change and push it out with a future code push.

Hello Dan,

Thank you. At least there's a useful zipline starter algo in the above!

P.