Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Best practice for dealing with limit orders

Hi all,

As you know, Q cancels any open orders every night. There are times, however, when one might want to have limit orders persist for longer.
Take for example a stock that is subject to wild swings, up and down. You might want to take profits if the stock unexpectedly hits a given high, say at 2 levels of divergence above the norm. Pipeline apps do not run intra day. Typically, you might have a given function running once a day, but rarely more frequently than that. At whatever time of day you are running your "daily" routine, the trigger point may not have been reached. But it might reach it temporarily during the day, then fall back below it, so it would not trigger it on the next daily routine either. Obviously, that's where a limit order makes sense

I am confused about their treatment in live IB run applications: it is not clear to me how Q handles the non-fulfillment of limit orders.
If you've ordered to buy 100 shares of XYZ stock and 62 filled at days end, doesn't IB continue trying to fill the remaining 38 regardless of Q?
Or does Q see that only 62 were filled out of 100, and therefore send an order to cancel the limit order to IB, so it will never fill remaining 38?

If my understanding is correct, in pipeline based apps, one would have to take the following approach:

1) set up your pipelines, with their daily /weekly/monthly routines as usual
but regardless run your algo every minute, using a timer to examine the market in whatever intervals make sense (5 minutes/15 minutes/ hourly, etc)
use context variables to store your symbol/ limit combinations that can persist overnight.
run an app every day before market opens to reinstate your limit orders

But if my understanding is incorrect, this would cause a doubling of limit orders, and unwanted buys/sells and probable margin calls.

I appreciate any input or thoughts from others on this.

4 responses

You are correct that any unfilled orders, OR orders that have been partially filled, get canceled at market close. This is true of any type of order. This behavior actually makes things very predictable. You shouldn't ever 'double' your orders (as you were concerned). There will only ever be orders on a given day which were explicitly placed on that day.

If you want a limit order hanging out there (which isn't a bad idea by the way) then simply place all those orders again at market open. One BIG word of caution. DON'T do what you stated use context variables to store your symbol/ limit combinations that can persist overnight . Never store any price or volume related data overnight. It will not be split adjusted. Always re-run any of the logic you had to place the orders and use the current days pricing.

Also, you can't technically run an app every day before market opens to reinstate your limit orders as you stated. Orders can only be placed during market hours. Place that logic into a scheduled function set to run at market open.

A few other minor points about your post...

You stated set up your pipelines . There can only be a single pipeline defined in an algorithm.
You stated run your algo every minute, using a timer to examine the market in whatever intervals make sense (5 minutes/15 minutes/ hourly, etc. If you want to run code every minute then place it in the pre-defined 'handle_data' method. If you want to run code at a certain interval then schedule it to run at those intervals using the 'schedule' function. Generally don't use timers as you suggested.

Hi Dan,

Thanks for those clarifications. Yes I understand there is only 1 pipeline, so that's a bad choice of words I used.

So if I want to run a file every 5 minutes I should schedule it 54 times ? (270 / 5) . Will that break on shortened trading days?

Is this really better (on the server, more efficient) than to set up a function in handle_data that triggers on intervals of 5 minutes?

Thanks
Serge

The 'schedule' function is the way to go. If you don't like the idea of A LOT of separate lines of code (one for each function call) you can do this.

 for minutes_offset in range(1, 390, 5):  
    # 390 minutes in a full trading day (6.5 x 60)  
    schedule_function(  
            my_rebalance,  
            date_rules.every_day(),  
            time_rules.market_open(minutes=minutes_offset),  
            half_days = True)  

This will work on shortened trading days. If for some reason you don't want to trade on those days you can set 'half_days = False'.

Attached is a backtest showing the schedule function at work. Look at the logs to see each time the 'my_rebalance' function was called.