To find the slowdown, try https://www.quantopian.com/posts/timing-code
By the way returns on amount invested are 100 percentage points higher than shown due to unfilled orders and not using all available cash, maybe filter out a percentile of low-volume stocks to see how much difference that makes in speed, for fewer unfilled orders. Consider data.current(stock, 'price') instead of history(), and stock.last_sale_price and context.portfolio.positions[stock].cost_basis. Fundamentals query can just be query(), empty, because that populates the dataframe values and they are unused, although that one can help with speed yet not to the degree we're talking here. Even though it runs every day, give pipeline a whirl and see if it resolves the problem if timing() doesn't find the issue.