The algorithm allows you to become seriously overdrawn, it took me a while to understand that the order method will cheerfully succeed even if you don't have enough cash. Solution is to check that you have enough cash before placing an order:
order_value = price * shares
# short circuit if portfolio cash insufficient
if context.portfolio.cash < order_value:
return
Then it took me a while to realise that order raises an event and that processing this event is deferred until after running handle_data, thus does not immediately update the portfolio. Solution is to track your current cash position in a given handle_data event:
context.cash = context.portfolio.cash
...
# short circuit if calculated cash position indicates not enough cash
if context.cash < order_value:
return
order(security, shares)
# update available cash
context.cash = context.cash - order_value
I still find a problem when I test against minute ticks (running a strategy with with multiple stocks). At what point is portfolio.cash updated? Is it end of day?