In [1]:
from quantopian.pipeline import Pipeline
from quantopian.research import run_pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage

Filters

A Filter is a function from an asset and a moment in time to a boolean:

F(asset, timestamp) -> boolean

In Pipeline, Filters are used for narrowing down the set of securities included in a computation or in the final output of a pipeline. There are two common ways to create a Filter: comparison operators and Factor/Classifier methods.

Comparison Operators

Comparison operators on Factors and Classifiers produce Filters. Since we haven't looked at Classifiers yet, let's stick to examples using Factors. The following example produces a filter that returns True whenever the latest close price is above $20.


In [2]:
last_close_price = USEquityPricing.close.latest
close_price_filter = last_close_price > 20

And this example produces a filter that returns True whenever the 10-day mean is below the 30-day mean.


In [3]:
mean_close_10 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10)
mean_close_30 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=30)
mean_crossover_filter = mean_close_10 < mean_close_30

Remember, each security will get its own True or False value each day.

Factor/Classifier Methods

Various methods of the Factor and Classifier classes return Filters. Again, since we haven't yet looked at Classifiers, let's stick to Factor methods for now (we'll look at Classifier methods later). The Factor.top(n) method produces a Filter that returns True for the top n securities of a given Factor. The following example produces a filter that returns True for exactly 200 securities every day, indicating that those securities were in the top 200 by last close price across all known securities.


In [4]:
last_close_price = USEquityPricing.close.latest
top_close_price_filter = last_close_price.top(200)

For a full list of Factor methods that return Filters, see this link.

For a full list of Classifier methods that return Filters, see this link.

Dollar Volume Filter

As a starting example, let's create a filter that returns True if a security's 30-day average dollar volume is above $10,000,000. To do this, we'll first need to create an AverageDollarVolume factor to compute the 30-day average dollar volume. Let's include the built-in AverageDollarVolume factor in our imports:


In [5]:
from quantopian.pipeline.factors import AverageDollarVolume

And then, let's instantiate our average dollar volume factor.


In [6]:
dollar_volume = AverageDollarVolume(window_length=30)

By default, AverageDollarVolume uses USEquityPricing.close and USEquityPricing.volume as its inputs, so we don't specify them.

Now that we have a dollar volume factor, we can create a filter with a boolean expression. The following line creates a filter returning True for securities with a dollar_volume greater than 10,000,000:


In [7]:
high_dollar_volume = (dollar_volume > 10000000)

To see what this filter looks like, let's can add it as a column to the pipeline we defined in the previous lesson.


In [8]:
def make_pipeline():

    mean_close_10 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10)
    mean_close_30 = SimpleMovingAverage(inputs=[USEquityPricing.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 > 10000000)

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

If we make and run our pipeline, we now have a column high_dollar_volume with a boolean value corresponding to the result of the expression for each security.


In [9]:
result = run_pipeline(make_pipeline(), '2015-05-05', '2015-05-05')
result


Out[9]:
high_dollar_volume percent_difference
2015-05-05 00:00:00+00:00 Equity(2 [AA]) True 0.017975
Equity(21 [AAME]) False -0.002325
Equity(24 [AAPL]) True 0.016905
Equity(25 [AA_PR]) False 0.021544
Equity(31 [ABAX]) False -0.019639
Equity(39 [DDC]) False 0.074730
Equity(41 [ARCB]) False 0.007067
Equity(52 [ABM]) False 0.003340
Equity(53 [ABMD]) True -0.024682
Equity(62 [ABT]) True 0.014385
Equity(64 [ABX]) True 0.046963
Equity(66 [AB]) False 0.013488
Equity(67 [ADSK]) True -0.003921
Equity(69 [ACAT]) False -0.007079
Equity(70 [VBF]) False 0.005507
Equity(76 [TAP]) True -0.008759
Equity(84 [ACET]) False -0.056139
Equity(86 [ACG]) False 0.010096
Equity(88 [ACI]) False -0.022089
Equity(100 [IEP]) False 0.011293
Equity(106 [ACU]) False 0.003306
Equity(110 [ACXM]) False -0.029551
Equity(112 [ACY]) False -0.057763
Equity(114 [ADBE]) True 0.009499
Equity(117 [AEY]) False 0.012543
Equity(122 [ADI]) True 0.009271
Equity(128 [ADM]) True 0.015760
Equity(134 [SXCL]) False NaN
Equity(149 [ADX]) False 0.007232
Equity(153 [AE]) False -0.112999
... ... ...
Equity(48961 [NYMT_O]) False NaN
Equity(48962 [CSAL]) True 0.000000
Equity(48963 [PAK]) False 0.000000
Equity(48969 [NSA]) True 0.000000
Equity(48971 [BSM]) True 0.000000
Equity(48972 [EVA]) True 0.000000
Equity(48981 [APIC]) False 0.000000
Equity(48989 [UK]) False 0.000000
Equity(48990 [ACWF]) False 0.000000
Equity(48991 [ISCF]) False 0.000000
Equity(48992 [INTF]) False 0.000000
Equity(48993 [JETS]) False 0.000000
Equity(48994 [ACTX]) False 0.000000
Equity(48995 [LRGF]) False 0.000000
Equity(48996 [SMLF]) False 0.000000
Equity(48997 [VKTX]) False 0.000000
Equity(48998 [OPGN]) False NaN
Equity(48999 [AAPC]) False 0.000000
Equity(49000 [BPMC]) False 0.000000
Equity(49001 [CLCD]) False NaN
Equity(49004 [TNP_PRD]) False 0.000000
Equity(49005 [ARWA_U]) False NaN
Equity(49006 [BVXV]) False NaN
Equity(49007 [BVXV_W]) False NaN
Equity(49008 [OPGN_W]) False NaN
Equity(49009 [PRKU]) False NaN
Equity(49010 [TBRA]) False NaN
Equity(49131 [OESX]) False NaN
Equity(49259 [ITUS]) False NaN
Equity(49523 [TLGT]) False NaN

8236 rows × 2 columns

Applying a Screen

By default, a pipeline produces computed values each day for every asset in the Quantopian database. Very often however, we only care about a subset of securities that meet specific criteria (for example, we might only care about securities that have enough daily trading volume to fill our orders quickly). We can tell our Pipeline to ignore securities for which a filter produces False by passing that filter to our Pipeline via the screen keyword.

To screen our pipeline output for securities with a 30-day average dollar volume greater than $10,000,000, we can simply pass our high_dollar_volume filter as the screen argument. This is what our make_pipeline function now looks like:


In [10]:
def make_pipeline():

    mean_close_10 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10)
    mean_close_30 = SimpleMovingAverage(inputs=[USEquityPricing.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 > 10000000

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

When we run this, the pipeline output only includes securities that pass the high_dollar_volume filter on a given day. For example, running this pipeline on May 5th, 2015 results in an output for ~2,100 securities


In [11]:
result = run_pipeline(make_pipeline(), '2015-05-05', '2015-05-05')
print 'Number of securities that passed the filter: %d' % len(result)
result


Number of securities that passed the filter: 2110
Out[11]:
percent_difference
2015-05-05 00:00:00+00:00 Equity(2 [AA]) 0.017975
Equity(24 [AAPL]) 0.016905
Equity(53 [ABMD]) -0.024682
Equity(62 [ABT]) 0.014385
Equity(64 [ABX]) 0.046963
Equity(67 [ADSK]) -0.003921
Equity(76 [TAP]) -0.008759
Equity(114 [ADBE]) 0.009499
Equity(122 [ADI]) 0.009271
Equity(128 [ADM]) 0.015760
Equity(154 [AEM]) 0.026035
Equity(161 [AEP]) 0.010405
Equity(166 [AES]) 0.022158
Equity(168 [AET]) 0.005853
Equity(185 [AFL]) -0.002239
Equity(197 [AGCO]) 0.032124
Equity(216 [HES]) 0.036528
Equity(239 [AIG]) 0.012322
Equity(253 [AIR]) -0.012412
Equity(266 [AJG]) 0.012267
Equity(270 [AKRX]) -0.024963
Equity(273 [ALU]) -0.021750
Equity(300 [ALK]) 0.015147
Equity(301 [ALKS]) -0.033228
Equity(328 [ALTR]) 0.012284
Equity(337 [AMAT]) -0.050162
Equity(351 [AMD]) -0.101477
Equity(353 [AME]) -0.003008
Equity(357 [TWX]) 0.000365
Equity(368 [AMGN]) 0.008860
... ...
Equity(48126 [HABT]) 0.063080
Equity(48129 [UBS]) 0.025888
Equity(48169 [KLXI]) 0.021062
Equity(48215 [QSR]) 0.037460
Equity(48220 [LC]) -0.035048
Equity(48317 [JUNO]) -0.103370
Equity(48384 [QRVO]) -0.050578
Equity(48465 [SWNC]) 0.061669
Equity(48486 [BOX]) -0.003837
Equity(48531 [VSTO]) 0.017196
Equity(48543 [SHAK]) 0.175877
Equity(48544 [HIFR]) 0.027339
Equity(48547 [ONCE]) -0.112191
Equity(48575 [XHR]) -0.008521
Equity(48629 [INOV]) -0.068366
Equity(48662 [JPM_PRF]) 0.002978
Equity(48672 [TOTL]) 0.000991
Equity(48730 [AGN_PRA]) -0.008843
Equity(48821 [CJES]) 0.099492
Equity(48823 [SEDG]) 0.056643
Equity(48863 [GDDY]) -0.003563
Equity(48892 [IGT]) 0.005591
Equity(48925 [ADRO]) -0.076840
Equity(48933 [PRTY]) -0.001741
Equity(48934 [ETSY]) -0.030142
Equity(48943 [VIRT]) -0.009077
Equity(48962 [CSAL]) 0.000000
Equity(48969 [NSA]) 0.000000
Equity(48971 [BSM]) 0.000000
Equity(48972 [EVA]) 0.000000

2110 rows × 1 columns

Inverting a Filter

The ~ operator is used to invert a filter, swapping all True values with Falses and vice-versa. For example, we can write the following to filter for low dollar volume securities:


In [12]:
low_dollar_volume = ~high_dollar_volume

This will return True for all securities with an average dollar volume below or equal to $10,000,000 over the last 30 days.

In the next lesson, we will look at combining filters.