Import packages, data and modules
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage
from quantopian.pipeline.filters.morningstar import IsPrimaryShare
from quantopian.pipeline.data.zacks import broker_ratings
from quantopian.research import run_pipeline
from zipline.api import get_datetime
from zipline.pipeline.factors.Factor import isnan
import numpy as np
import pandas as pd
def universe_filters():
"""
Create a Pipeline producing Filters implementing common acceptance criteria.
Returns
-------
zipline.Filter
Filter to control tradeablility
"""
# Primary share equities.
primary_share = IsPrimaryShare()
# Equities listed as common stock. 'ST00000001' indicates common stock.
common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')
# Non-depositary receipts
not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest
# Equities not trading over-the-counter.
not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')
# Not when-issued equities.
not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')
# Equities without LP in their name
not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')
# Equities with a null value in the limited_partnership
not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()
# Equities whose most recent Morningstar market cap is not null have fundamental data and therefore are not ETFs.
have_market_cap = morningstar.valuation.market_cap.latest.notnull()
universe_filter = (
primary_share
& common_stock
& not_depositary
& not_otc
& not_wi
& not_lp_name
& not_lp_balance_sheet
& have_market_cap
)
return universe_filter
def make_pipeline():
#Get price data
latest_close = USEquityPricing.close.latest
mean_close_10 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10)
percent_difference = latest_close / mean_close_10 - 1
#Get key financial ratios
price_to_book = morningstar.valuation_ratios.pb_ratio.latest #TO-DO: adjust for goodwill_and_other_intangible_assets
price_to_earnings = morningstar.valuation_ratios.pe_ratio.latest #TO-DO: exclude extraordinary earnings items
debt_to_equity = morningstar.operation_ratios.total_debt_equity_ratio.latest
financials_ratio = (1/price_to_book + 10/price_to_earnings - debt_to_equity)/3
#Add time discount from last filing date
last_filing_date = morningstar.financial_statement_filing.file_date.latest #TO-DO: check what is the most relevant statement date
#today = get_datetime()
#time_penalty = (today - last_filing_date - 30)^2/100000
#Get analyst estimations
rating_strong_buys = broker_ratings.rating_cnt_strong_buys.latest
rating_buys = broker_ratings.rating_cnt_mod_buys.latest
rating_holds = broker_ratings.rating_cnt_holds.latest
rating_sells = broker_ratings.rating_cnt_mod_sells.latest
rating_strong_sells = broker_ratings.rating_cnt_strong_sells.latest
ratings = np.array([rating_strong_buys, rating_buys, rating_holds, rating_sells, rating_strong_sells]) #TO-DO: Replace NaNs with 0
"""
#Replace NaNs with 0 for calculation purposes
if np.isnan(ratings).any():
ratings = 0
"""
rating_weights = np.array([0.025, 0.015, 0.005, -0.005, -0.015])
rating_coefficient = (ratings*rating_weights).sum()
#Market capitalisation component
market_cap = morningstar.valuation.market_cap.latest
market_cap_coefficient = 46066000/market_cap
#Calculate potential
potential = (
financials_ratio
+ rating_coefficient
#- time_penalty
- market_cap_coefficient
)
screening = potential.top(25)
return Pipeline(
columns={
'P/B': price_to_book,
'P/E' : price_to_earnings,
'D/E' : debt_to_equity,
'Financials ratio' : financials_ratio,
'Rating coefficient': rating_coefficient,
'Market cap coefficient': market_cap_coefficient,
'Potential': potential*100
#'Strong buy': rating_strong_buys,
#'Buy': rating_buys,
#'Hold': rating_holds,
#'Sell': rating_sells,
#'Strong sell': rating_strong_sells
},
screen=universe_filters() & screening
)
my_pipe = make_pipeline()
result = run_pipeline(my_pipe, '2013-05-05', '2013-05-05')
print 'Number of securities that passed the filter: %d' % len(result)
result.sort('Potential', ascending=False)