Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Initiating order at Open which initiates other orders when filled

"Stole" some other code from the community to test Market Open and Closes, trying to have my script initiate a biased position at open price which then initiates other orders if filled.

For this example, I put in an order to short at the open. If filled, it should then add to the short or cover some based on price moves, but no other orders should be placed until the original order is filled. init_order should contain the initial order object which gets created at Open. If filled, it should be set to None.

I have it logging to show me my open initial order, as well as my current position, which should signal when filled and then launch other orders. Somehow, my position changes while leaving the original order open. Any suggestions as to what I'm doing wrong?

import pytz  
import zipline.finance.blotter as blotter

# Initialize the timezone:  
EST = pytz.timezone('US/Eastern')

def initialize(context):  
  # In this example, I'm looking at AAPL (24).  
  context.UTCprev = None  
  context.stock = sid(24)  #AAPL

  context.max_notional = 0  
  context.min_notional = -3000  
  context.init_notional = -100  
  context.trade_notional = -50  
  context.init_order = None  
  context.init_order_id = 0  
  context.old_price = 0

def handle_data(context, data):

    # timestamp of previous event (or None)  
    UTCprev = context.UTCprev

    # timestamp of current event  
    UTCdate = get_datetime()  
    ESTdate = get_datetime().astimezone(EST)  
    price = data[context.stock].price

    # day changed  
    if UTCprev and UTCprev.day <> UTCdate.day:  
        loginfo = '\n"prev" UTC: {} EST: {}'.format( UTCprev, UTCprev.astimezone(EST) )  
        loginfo +='\n"date" UTC: {} EST: {}'.format( UTCdate, ESTdate )  
        log.info( loginfo )  
    context.UTCprev = UTCdate

    # test for market open by timestamp  
    if ESTdate.hour == 9 and ESTdate.minute == 31:  
        loginfo ='\n"Market Open" EST: {}'.format( ESTdate )  
        loginfo +='\ndaily opening pos of ' + str(context.portfolio.positions[context.stock].amount)  
        log.info( loginfo )  
        price = data[context.stock].open_price  
        context.old_price = price  
        loginfo = '\nplacing initial daily order to go short ' + str(context.init_notional) + ' shares at price ' + str(price)  
        log.info( loginfo )  
        # Placing initial order for day  
        context.init_order_id = order(context.stock, context.init_notional, limit_price=price)  
        context.init_order = get_order(context.init_order_id)  
    # Checking if initial order exists  
    if context.init_order is not None:  
        if context.init_order.status == blotter.ORDER_STATUS.OPEN:  
            log.info("Order {0} - Order amount: {1}, Fill amount: {2}".format(  
            context.init_order.sid,  
            context.init_order.amount,  
            context.init_order.filled))  
            log.info("Open order on {0} - Order amount: {1}, Fill amount: {2}".format(  
            context.init_order.sid,  
            context.init_order.amount,  
            context.init_order.filled))  
            log.info('\ncurrent pos of ' + str(context.portfolio.positions[context.stock].amount))

        # This is where it should trigger subsequent orders when init order filled  
        elif context.init_order.status == blotter.ORDER_STATUS.FILLED:  
            log.info("Filled Order on {0} - Order amount: {1}, Fill amount: {2}".format(  
            context.init_order.sid,  
            context.init_order.amount,  
            context.init_order.filled))  
            loginfo = 'Placing an order of ' + str(context.trade_notional) + ' shares @ approx ' + str(price-.25)  
            loginfo += '\nand an order of ' + -str(context.trade_notional) + ' shares @ approx ' + str(price+.25)  
            order(context.stock, context.trade_notional, limit_price=price-.25)  
            order(context.stock, -context.trade_notional, limit_price=price+.25)  
            context.init_order = None  
    if context.init_order is None:  
        if price >= context.old_price +.25 and context.portfolio.positions[context.stock].amount < context.max_notional and context.portfolio.positions[context.stock].amount > context.min_notional:  
            log.info('placing limit order to increase short pos by 50 shares at price ' + str(price+.25))  
            order(context.stock, context.trade_notional, limit_price=price+.25)  
            log.info('placing limit order to cover 50 shares at price ' + str(price-.25))  
            order(context.stock, -context.trade_notional, limit_price=price-.25)  
            log.info('current pos of ' + str(context.portfolio.positions[context.stock].amount))  
            context.old_price = price  
        elif price <= context.old_price -.25 and context.portfolio.positions[context.stock].amount < context.max_notional and context.portfolio.positions[context.stock].amount > context.min_notional:  
            log.info('placing limit order to increase short pos by 50 shares at price ' + str(price+.25))  
            order(context.stock, context.trade_notional, limit_price=price+.25)  
            log.info('placing limit order to cover 50 shares at price ' + str(price-.25))  
            order(context.stock, -context.trade_notional, limit_price=price-.25)  
            log.info('current pos of ' + str(context.portfolio.positions[context.stock].amount))  
            context.old_price = price  
1 response

Hello Joseph,

I think the root of your problem was that you were making a copy of the order object and stashing it in context. When you were doing your checks on the order, you were checking the copy, not the latest status. You had:

        context.init_order = get_order(context.init_order_id)  

I deleted that line, modified the test for whether or not the order has been placed, and then got the order status.

    if context.init_order_id != 0:  
        # getting current order status  
        init_order = get_order(context.init_order_id)  

I didn't try to unravel the rest of your algo because I wasn't sure what you were trying to do. But attached is a backtest that uses your code and doesn't place any additional orders until the first one fills.

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.