Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Why does this code purchase the same stock twice?

Hi I wrote a method that places an order for a stock based off a fundamental screen that looks like this:

def buy_stock(context, data):  
    for stock in context.fundamental_df:  
        if stock.sid in context.portfolio.positions:  
            pass  
        else:  
            order_value(stock, 1000)  
            context.buy_dates[stock] = get_datetime()  
            break  

It buys one stock making sure that the stock is not already held in the portfolio and records the date the order was placed.

I decided I wanted to buy two different stocks instead of one so I scheduled this method to run twice (ten minutes apart) thinking that the if stock.sid in context.portfolio.positions: line would prevent it from buying the same stock as the first run. The result was that I bought the exact same stock on each scheduled run.

 schedule_function(buy_stock,  
                      date_rules.month_start(),  
                      time_rules.market_open(minutes = 30))  
 schedule_function(buy_stock,  
                      date_rules.month_start(),  
                      time_rules.market_open(minutes = 40))  

Does this occur because the order from the first run of the buy_stock() method has not been filled by the time the second scheduled run occurs?

4 responses

Does this occur because the order from the first run of the
buy_stock() method has not been filled by the time the second
scheduled run occurs?

Yes. The easy fix is to do something like:

if stock.sid in context.portfolio.positions or get_open_orders(stock.sid):  
    pass  

So simple! Thanks mate your a genius :)

I think you will get different behaviors based on whether you are running in Daily or Minutely mode.

From my understanding of how the backtester works, if running in Daily mode, the 2nd schedule_function() call 10mins later will placing another buy order for the same stock without Shagam's fix because the first order is queued to be executed at the close of the NEXT daily bar.

HOWEVER, if running in Minutely mode, the first buy order is executed at the close of the next minutely bar so when the 2nd schedule_function() call is placed 10mins later, buy_stock() will see that there is already a position and not place that second order.

Another fix to get consistent behaviour across both Daily/Minutely mode would be to use order_target_percent().