Now that we've covered the basic components of the Pipeline API, let's construct a pipeline that we might want to use in an algorithm.
To do so, we will create a filter to narrow down the full universe of US stocks to a subset of tradable securities, defined as those securities that meet all of the following criteria:
usstock_SecurityType2
field will automatically exclude preferred stocks, ETFs, ADRs, and LPs, as the latter all have different values for usstock_SecurityType2
.Former Quantopian users may notice that this universe is modeled on Quantopian's most popular universe, QTradableStocksUS
, described in this archived Quantopian forum post. To reduce data dependencies, we have omitted one rule, namely that market cap must be over \$500M. See the note further down if you have a Sharadar fundamentals subscription and would like to add this market cap filter.
Let's create a filter for each criterion and combine them together to create a TradableStocksUS
filter.
from zipline.pipeline import EquityPricing, master
from zipline.pipeline.factors import AverageDollarVolume, Latest
The first two rules - common stocks only and primary shares only - are static characteristics that derive from the securities master database and thus can be applied as the initial_universe
. We will place these rules in their own function, which returns a filter that can be passed to a Pipeline as the initial_universe
argument.
def InitialUniverse():
# Equities listed as common stock (not preferred stock, ETF, ADR, LP, etc)
common_stock = master.SecuritiesMaster.usstock_SecurityType2.latest.eq('Common Stock')
# Filter for primary share equities; primary shares can be identified by a
# null usstock_PrimaryShareSid field (i.e. no pointer to a primary share)
is_primary_share = master.SecuritiesMaster.usstock_PrimaryShareSid.latest.isnull()
# combine the security type filters to form our initial universe
initial_universe = common_stock & is_primary_share
return initial_universe
We place the remaining rules in a separate function. As discussed in the lesson on masking, we use masks in the later steps of our asset funnel to reduce computational load. This function will return a filter that can be passed to a pipeline as the screen
argument or as the mask
argument of another Term. In conjunction with the initial universe, it will limit the pipeline to the stocks we've defined as tradable.
def TradableStocksUS():
# require high dollar volume
tradable_stocks = AverageDollarVolume(window_length=200) >= 2.5e6
# also require price > $5. Note that we use Latest(...) instead of EquityPricing.close.latest
# so that we can pass a mask
tradable_stocks = Latest(EquityPricing.close, mask=tradable_stocks) > 5
# also require no missing data for 200 days
tradable_stocks = EquityPricing.close.all_present(200, mask=tradable_stocks)
has_volume = EquityPricing.volume.latest > 0
tradable_stocks = has_volume.all(200, mask=tradable_stocks)
return tradable_stocks
Note that when defining our filters, we used several methods that we haven't yet seen including isnull
, all
, and all_present
. Documentation on these methods is available in the Pipeline API Reference or by clicking on the method name in JupyterLab and pressing Control.
If you have a Sharadar fundamentals subscription and would like to add a market cap filter to your universe to fully re-create the QTradableStocksUS
universe, you can do so by adding the following line to the above function:
# also require market cap over $500M
tradable_stocks = Latest([sharadar.Fundamentals.slice(dimension='ARQ', period_offset=0).MARKETCAP], mask=tradable_stocks) >= 500e6
Our universe may be useful to us in numerous notebooks and Zipline algorithms, so a practical next step is to transfer the pipeline code to a .py
file to facilitate code reuse. We have done so in tradable_stocks.py. The initial universe and the full universe can now be imported in any notebook or Zipline algorithm as follows:
from codeload.pipeline_tutorial.tradable_stocks import InitialUniverse, TradableStocksUS
initial_universe = InitialUniverse()
universe = TradableStocksUS()
We'll import and use this universe in the next lesson.
Next Lesson: Using Pipeline with Alphalens