The slowest action is typically fetching data. It's always fastest to get data in one big chunk rather than one at a time in small chucks. The biggest increase in speed would be to change your '.get_history' method. Take the following code out from the loop.
price_history = data.history(security, 'price', 2, '1m')
Instead, get all prices at once with logic something like this (also note that since you're just concerned about the current price then don't use '.history')
active_positions_set = set(context.portfolio.positions) - set(get_open_orders())
active_positions = data.current(list(active_positions_set), 'price')
This will return a Pandas series of current prices indexed by the stock. Using sets in the first statement is a quick way to get only those stocks currently held but that do NOT have any open orders.
Also, it's generally faster to do calculations within the pipeline. One other thing to do to increase the speed of the pipeline is to use the 'mask' option wherever appropriate to keep from fetching more data than needed. This is especially true for fundamental data. Using the 'Latest' factor rather than the '.latest' method allows for using the mask option.
# These two do the same except the later allows for a mask option and speeds up the fetch in most cases
pe_ratio = morningstar.valuation_ratios.pe_ratio.latest
pe_ratio = Latest([morningstar.valuation_ratios.pe_ratio], mask = base_universe)
Attached is an algorithm with these and a few other changes