Back to Community
Sending MKT and MOC orders before markets open on daily bars

Hello,

My strategy uses daily bars and enters each trade at the market open and exits at the close. It never holds a position overnight. Signals are calculated after the close of the current day and sent to my broker before the markets open on the next day. In real life with my IB account, I simply have to send the following two orders between today's close and tomorrow's open: "BUY 100 AAPL MKT" and "SELL 100 AAPL MOC".

How can I replicate that in Quantopian? Thank you.

5 responses

Hey Alexis,

Please see the attached algorithm and backtest. You will need to write and execute an algorithm in minute mode (as opposed to daily mode). The algorithm given here will allow you to set the security, position size, and times at which you would like to enter and exit trades.

Ryan

Clone Algorithm
45
Loading...
Backtest from to with initial capital
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
from pytz import timezone
from datetime import datetime, timedelta
from zipline.utils.tradingcalendar import get_early_closes

def initialize(context):
    context.aapl = sid(24)
    context.position_size = 100
    # Initialize start and end dates to check for early closes
    start_date = context.aapl.security_start_date
    end_date = context.aapl.security_end_date 
    context.early_closes = get_early_closes(start_date,end_date).date
 
    context.minutes_after_open = 5 #Minutes after open to buy
    context.minutes_before_close = 5 #Minutes after close to sell
   
def handle_data(context, data):
    #Execute orders for the day
    daily_activity(context,data)

def daily_activity(context,data):
    #Algorithm holds the positoin only during 
    if beginningofday_check(context) == True:
        #Buy at beginning of the day
        order(context.aapl, context.position_size)
    else:
        pass
    if endofday_check(context) == True:
        #Sell at end of day 
        order(context.aapl, -context.position_size)
    else:
        pass
        
def endofday_check(context):
    # Converts all time-zones into US EST 
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))
    date = get_datetime().date()
    
    # Checks for an early close on special dates - market closes at 1:00PM
    if date in context.early_closes:
        # Returns true if it's 1:00PM - minutes so in this case 12:55PM
        if loc_dt.hour == 12 and loc_dt.minute == (60-context.minutes_before_close):
            log.debug(get_datetime())
            return True
        else:
            return False
    # Returns true if it's 4:00PM EST - minutes so in this case at 3:55PM
    # Daylight savings time are accounted for, so it will automatically adjust to DST
    elif loc_dt.hour == 15 and loc_dt.minute == (60-context.minutes_before_close):
        log.debug(get_datetime())
        return True
    else:
        return False

def beginningofday_check(context):
    # Convert all time-zones into US EST
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))
    
    if loc_dt.hour == 9 and loc_dt.minute == (30 + context.minutes_after_open):
        log.debug(get_datetime())
        return True
    else:
        return False
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.
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.

Thank you for your help, Ryan. The market-on-close order seems fine, but I can't replicate the market-on-open order.

To be quite honest, I think it is a major flaw of the backtesting engine as trading on the open is highly important (at least for me!). Would it be possible to add the option to execute the order either on the open or the close of the next bar, instead of currently the close only? Thank you.

Hey Alexis,

Please see the attached code, which adds additional log information to the algorithm previously posted. I see that the algo performs both the buy and sell orders properly - hopefully you will obtain the same results in the log.

If you are looking to buy exactly at the open of the day (i.e. at 9:30 AM sharp), unfortunately Quantopian does not support that level of specificity yet, and you will only be able to place an order at the end of a bar.

Ryan

Here is the backtest.

Clone Algorithm
45
Loading...
Backtest from to with initial capital
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
from pytz import timezone
from datetime import datetime, timedelta
from zipline.utils.tradingcalendar import get_early_closes

def initialize(context):
    context.aapl = sid(24)
    context.position_size = 100 #Set the position size (default is 100 shares)
    # Initialize start and end dates to check for early closes
    start_date = context.aapl.security_start_date
    end_date = context.aapl.security_end_date 
    context.early_closes = get_early_closes(start_date,end_date).date
 
    context.minutes_after_open = 5 #Minutes after open to buy
    context.minutes_before_close = 5 #Minutes after close to sell
   
def handle_data(context, data):
    #Execute orders for the day
    daily_activity(context,data)

def daily_activity(context,data):
    #Algorithm holds the positoin only during
    if beginningofday_check(context) == True:
        #Buy at beginning of the day
        order_id_1 = order(context.aapl, context.position_size)
        curr_order = get_order(order_id_1)
        message = 'Buy {amount} at {time}.'
        order_time = get_datetime()
        message = message.format(amount=curr_order.amount, time = order_time)
        log.info(message)
    else:
        pass
    if endofday_check(context) == True:
        #Sell at end of day 
        order_id_2 = order(context.aapl, -context.position_size)
        curr_order = get_order(order_id_2)
        message = 'Sell {amount} at {time}.'
        order_time = get_datetime()
        message = message.format(amount=curr_order.amount, time = order_time)
        log.info(message)
    else:
        pass   
        
def endofday_check(context):
    # Converts all time-zones into US EST 
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))
    date = get_datetime().date()
    
    # Checks for an early close on special dates - market closes at 1:00PM
    if date in context.early_closes:
        # Returns true if it's 1:00PM - minutes so in this case 12:55PM
        if loc_dt.hour == 12 and loc_dt.minute == (60-context.minutes_before_close):
            return True
        else:
            return False
    # Returns true if it's 4:00PM EST 
    # Daylight savings time are accounted for,
    elif loc_dt.hour == 15 and loc_dt.minute == (60-context.minutes_before_close):
        return True
    else:
        return False

def beginningofday_check(context):
    # Convert all time-zones into US EST
    loc_dt = get_datetime().astimezone(timezone('US/Eastern'))
    
    if loc_dt.hour == 9 and loc_dt.minute == (30 + context.minutes_after_open):
        return True
    else:
        return False
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Sorry Ryan if my message wasn't clear - the code you sent along worked well. Any idea when this feature could be implemented? Really looking forward to it!

Cheers!