QuantRocket logo
Disclaimer


Pipeline Tutorial › Lesson 7: Combining Filters


Combining Filters¶

Like factors, filters can be combined. Combining filters is done using the & (and) and | (or) operators. For example, let's say we want to screen for securities that are in the top 10% of average dollar volume and have a latest close price above \$20. To start, let's make a high dollar volume filter using an AverageDollarVolume factor and percentile_between:

In [1]:
from zipline.pipeline import Pipeline, EquityPricing
from zipline.research import run_pipeline
from zipline.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
In [2]:
dollar_volume = AverageDollarVolume(window_length=30)
high_dollar_volume = dollar_volume.percentile_between(90, 100)

Note: percentile_between is a Factor method returning a Filter.

Next, let's create a latest_close factor and define a filter for securities that closed above $20:

In [3]:
latest_close = EquityPricing.close.latest
above_20 = latest_close > 20

Now we can combine our high_dollar_volume filter with our above_20 filter using the & operator:

In [4]:
tradeable_filter = high_dollar_volume & above_20

This filter will evaluate to True for securities where both high_dollar_volume and above_20 are True. Otherwise, it will evaluate to False. A similar computation can be made with the | (or) operator.

If we want to use this filter as a screen in our pipeline, we can simply pass tradeable_filter as the screen argument.

In [5]:
def make_pipeline():

    mean_close_10 = SimpleMovingAverage(inputs=EquityPricing.close, window_length=10)
    mean_close_30 = SimpleMovingAverage(inputs=EquityPricing.close, window_length=30)

    percent_difference = (mean_close_10 - mean_close_30) / mean_close_30

    dollar_volume = AverageDollarVolume(window_length=30)
    high_dollar_volume = dollar_volume.percentile_between(90, 100)

    latest_close = EquityPricing.close.latest
    above_20 = latest_close > 20

    tradeable_filter = high_dollar_volume & above_20

    return Pipeline(
        columns={
            'percent_difference': percent_difference
        },
        screen=tradeable_filter
    )

When we run this, our pipeline output now only includes ~600 securities.

In [6]:
result = run_pipeline(make_pipeline(), start_date='2010-01-05', end_date='2010-01-05')
print(f'Number of securities that passed the filter: {len(result)}')
result
Number of securities that passed the filter: 615
Out[6]:
percent_difference
dateasset
2010-01-05Equity(FIBBG000C2V3D6 [A])0.021425
Equity(FIBBG000F7RCJ1 [AAP])0.015388
Equity(FIBBG000B9XRY4 [AAPL])0.030018
Equity(FIBBG000MDCQC2 [COR])0.036454
Equity(FIBBG000B9ZXB4 [ABT])0.003292
......
Equity(FIBBG000BGB482 [XOP])0.051799
Equity(FIBBG000D80VV4 [XRT])0.021822
Equity(FIBBG000BH2VM4 [XTO])0.064755
Equity(FIBBG000BH3GZ2 [YUM])0.003000
Equity(FIBBG000BKPL53 [ZBH])0.010965

615 rows × 1 columns


Next Lesson: Masking