This may help. On needs a custom factor (though a simple one) to get the lows. Something like this.
class Low(CustomFactor):
# Define inputs
inputs = [USEquityPricing.low]
# Set window_length to whatever number of days to lookback as a default
# in the case where no window_length is given when instantiated.
# This can also be set/over-ridden as shown below:
# my_low_10 = Low(window_length = 10)
window_length = 20
def compute(self, today, assets, out, lows):
# The input 'lows' is a Numpy array with low prices as axis 0 (total rows = window length)
# and axis 1 are all the assets (ie stocks and securities).
# Here we use the built in Numpy method to return the low in each row.
# The nanmax method is used because it excludes nans unlike the standard max
out[:] = np.nanmin(lows, axis=0)
Make a filter to find securities within x percent of the low like this
# Create the low factor.
low_20 = Low()
# Create close factor. This is easier because we can use the 'latest' method.
close = USEquityPricing.close.latest
# Make a filter for just the securities priced less than 10% over the low
PERCENT_OVER_LOW = .1
low_within_10pct_filter = close < (low_20 * (1.0 + PERCENT_OVER_LOW)
Attached is a notebook with it in action.