Cool. Meanwhile now that it's no longer 3 AM and I'm more awake, maybe the ... '1m').ffill(axis=1).bfill(axis=1) isn't doing anything as I understand prices are forward filled. Might want to use 'close', not forward filled and count nans to skip any stock currently above some threshold percentage of nans. If that route, then they do need ffill afterward and before ema and bbands calcs. Since the history call has been moved outside of the loop and is operating on the entire list of stocks instead of one at a time, if it were 'close' instead of 'price', the axis=1 may be required to prevent action on all stocks whenever one stock needs the fill. I would test in the debugger with just a few stocks and small window to find out for sure.
@VHawk, right on. And I'm trying to imagine a way to avoid closing where take profit and stop loss would rule the closings, a universal function that could adopt incoming stocks with new weights and adjust everybody else in some sensible way based on their current weights maybe. Complicated.
Here since numstock in
order_target_percent(stock, 1.0/numstock)
is just an integer with equal weights, it could be replaced with len(set(list(c.stocks) + c.portfolio.positions.keys()))
where c is context, and set makes unique, toward being able to keep on adding positions.