Hello,
at the moment it' possible to use this trick (see the section below
def accept_exchange
):
class UniverseMask(CustomFactor):
"""
Return 1.0 for the following class of assets, otherwise 0.0:
* No Financials (103), Real Estate (104), Basic Materials (101) and ADR
(Basic Materials are too much sensitive to exogenous macroeconomical shocks.)
* Only primary common stocks
* Exclude When Distributed(WD), When Issued(WI) and VJ - usuallly companies in bankruptcy
* Exclude Halted stocks (_V, _H)
* Only NYSE, AMEX and Nasdaq
* mkt cap > 5,000,000
* invested_capital > 0 (sanity check)
* total_assets > 0 (sanity check)
* Avoid illiquid stock (dollar trading volume average in the last 10 days less than 100,000)
"""
window_length = 10
inputs = [USEquityPricing.close, USEquityPricing.volume,
morningstar.valuation.market_cap,
morningstar.share_class_reference.is_primary_share,
morningstar.share_class_reference.is_depositary_receipt,
morningstar.asset_classification.morningstar_sector_code,
morningstar.balance_sheet.invested_capital,
morningstar.balance_sheet.total_assets
]
def compute(self, today, assets, out, close_price, volume, mkt_cap, is_primary_share, \
is_depositary_receipt, sector_code, invested_capital, total_assets):
dollar_volume_10d_avg = np.mean(close_price * volume, axis=0)
criteria = dollar_volume_10d_avg > 1e5 # Avoid illiquid stock (dollar trading volume average in the last 10 days less than 100,000)
price_10d_avg = np.mean(close_price, axis=0)
criteria = criteria & (price_10d_avg > 3) # Avoid penny stocks (less tahn $3)
criteria = criteria & (mkt_cap[-1] > 5e6) # Mkt cap > 5,000,000
criteria = criteria & (is_primary_share[-1]) # Only primary Common Stock
criteria = criteria & (~is_depositary_receipt[-1]) # No ADR
criteria = criteria & (sector_code[-1] != 101) # No Basic Materials
criteria = criteria & (sector_code[-1] != 103) # No Financials
criteria = criteria & (sector_code[-1] != 104) # No Real Estate
criteria = criteria & (invested_capital[-1] > 0) # Sanity check
criteria = criteria & (total_assets[-1] > 0) # Sanity check
def accept_symbol(equity):
symbol = equity.symbol
if symbol.endswith("_PR") or symbol.endswith("_WI") or symbol.endswith("_WD") or \
symbol.endswith("_VJ") or symbol.endswith("_V") or symbol.endswith("_H"):
return False
else:
return True
def accept_exchange(equity):
exchange = equity.exchange
if exchange == "NEW YORK STOCK EXCHANGE":
return True
elif exchange == "AMERICAN STOCK EXCHANGE":
return True
elif exchange.startswith("NASDAQ"):
return True
else:
return False
vsid = np.vectorize(sid)
equities = vsid(assets)
# Exclude When Distributed(WD), When Issued(WI) and VJ (usuallly companies in bankruptcy) and Halted stocks (V, H)
vaccept_symbol = np.vectorize(accept_symbol)
accept_symbol = vaccept_symbol(equities)
criteria = criteria & (accept_symbol)
# Only NYSE, AMEX and Nasdaq
vaccept_exchange = np.vectorize(accept_exchange)
accept_exchange = vaccept_exchange(equities)
criteria = criteria & (accept_exchange)
out[:] = criteria.astype(float)