The momentum indicator and Cerebro both look good. The problem is in Strategy. @tianjixuetu is correct when he said that you need to test the target_data and not the first data.
More specifically, what's happening is that in rebalance_profolio this section of code:
for i, d in enumerate(self.rankings):
if self.getposition(self.data).size > 0:
if (i > num_stocks * 0.05 or d < self.inds[d]["mav"]) and self.savedPositions.get(d._name, None) != None:
self.order = self.close(d, exectype=bt.Order.Close)
is iterating over a list of stocks (in ranked order) but it's determining the position size from just the first data set that it finds. You need something like the following (note lined 2):
for i, d in enumerate(self.rankings):
if self.getposition(d.data).size > 0:
if (i > num_stocks * 0.05 or d < self.inds[d]["mav"]) and self.savedPositions.get(d._name, None) != None:
self.order = self.close(d, exectype=bt.Order.Close)
There appears to be a similar problem with the buy loop also.