You can run something every minute like this. Instead of handle_data:
for i in range(1, 391, 1): # start, end + 1, every i
schedule_function(limits, date_rules.every_day(), time_rules.market_open(minutes=i))
Then it's helpful to distinguish between opening and closing orders. Comes in handy a lot, cls_opn_crs(). Don't want to set a limit on a stock that is already in the process of closing for example, doubling up on closing orders would cause long to go short instead of zero. Aiming for universality, lots of stocks and including when there are partial fills, these are some of the essentials:
def cls_opn_crs(c, o): # Identify the state of an order
# c = context, o is the order object
# https://www.quantopian.com/posts/order-state-on-partial-fills-close-open-or-crossover
if o.stop or o.limit: return 0 # assumes no stop or limit being used to open orders
if c.portfolio.positions[o.sid].amount * o.amount < 0: # close or crossover (x)
if abs(c.portfolio.positions[o.sid].amount) < abs(o.amount - o.filled):
if abs(c.portfolio.positions[s].amount) - abs(o.filled) < 0:
return 3 # crossed 0 (closed now opening portion of crossover)
else: return 2 # crossover closing
else: return 0 # close, not x
else: return 1 # open, not x
def limits(context, data):
oos = get_open_orders() # oos = open orders
for s in context.portfolio.positions:
if not data.can_trade(s): continue
limit_order = None; open_order = 0; opening = 0; do_limit = 0
for o in oos[s]:
open_order = 1
if o.limit:
limit_order = o # previous limit
elif cls_opn_crs(context, o) in [1, 3]: # opening
opening = 1 # partial fill underway
if not open_order and not limit_order: # filled completely, needs limit
do_limit = 1
if opening and limit_order: # busy opening
cancel_order(limit_order.id) # cancel previous limit
if opening or not limit_order:
do_limit = 1
if do_limit:
cb = context.portfolio.positions[s].cost_basis
amt = context.portfolio.positions[s].amount
limit = float('%.2f' % (cb * (1 + (abs(amt) / amt) * .05))) # long or short
order_target(s, 0, style=LimitOrder(limit))
Needs to be streamlined, I cobbled together limits() on the fly for you as a start, untested. Recommend vetting with debugger by clicking in margin on line numbers, high calorie code food even though it's about as fun as eating cardboard.
I'm not sure why you would have additional buys. You're surely already doing get_open_orders(security) from Luca's code and checking to only order if not already held. Another thing that can be useful is to wait after a position is closed, not reopening it right away or that would just waste some commission fees.
My code that includes both limits and trailing stops (not to get you down) is over 80 lines, part of a set of an integrated set of versatile tools that took too much effort for me to give away for altruism or 0.0 though. Over 1000 lines altogether, it does something like 30 things with options including the order tracking above. By the way I've seen people talk about investing a small amount of money around here, a small amount, and then they add, $1 million. If one of you would like to click on my name and ping me, feel free.