EquityUniverseFilter
EquityUniverseFilter#
-
class sigtech.framework.equities.equity_universe_filter.EquityUniverseFilter
Class designed to filter stocks by fundamentals, e.g. dividend yield or EBIT, by history fields, e.g. volume, VWAP, TRBC classification scheme, e.g. economic or business sector, and IBES analyst estimates.
Basic filter usage:
some_dates = pd.date_range(dtm.date(2019, 1, 15), dtm.date(2020, 9, 15), freq='Q') equity_filter = sig.EquityUniverseFilter('SPX INDEX') # Add: top 10 equity_filter.add('MARKETCAP', 'top', 10, 'Daily') # Add: top 50% equity_filter.add('vwap', 'top', 50, 'Daily', percent=True) # Add: minimum number of data points of VWAP timeseries (at least 85% non-NaNs of last 250 points, on the day # the filter is applied) equity_filter.add('vwap', 'min_data_size', (250, 0.85), 'Daily') # Add: TRBC sector - 'in' and 'not_in' on a single sector equity_filter.add('Healthcare', 'in', 'TRBC_ECONOMIC_SECTOR') # Add: TRBC sector - 'in' on a list of sectors (logic OR operator between sectors) equity_filter.add(['Healthcare', 'Industrials'], 'in', 'TRBC_ECONOMIC_SECTOR') # Add: TRBC sector - 'not_in' on a list of sectors (logic AND operator between sectors) equity_filter.add(['Financials', 'Industrials'], 'not_in', 'TRBC_ECONOMIC_SECTOR') # Add: IBES analyst estimates (fields available may not coincide with the fundamental fields available for the # the single stocks) equity_filter.add('Price/Sales Ratio', 'top', 10, analyst_estimates=True, metric='mean_est', historical_period_index='FY1') # Apply all filters previously defined: filtered_ids = equity_filter.apply_filter(some_dates)
Customised aggregation functions:
def compute_rolling_volume(ts): return ts.rolling(window=30).median() def compute_payout_ratio(ts): s1, s2 = ts[0:2] return s1.divide(s2) equity_filter.add('Volume', '>', 1e4, 'Daily', compute_rolling_volume) equity_filter.add(['TOTAL DIVIDENDS', 'Net Income'], 'top', 20, 'Daily', compute_payout_ratio) equity_filter.add(['TOTAL DIVIDENDS', 'Net Income'], 'top', 20, ['Daily', 'Daily'], compute_payout_ratio)
The two examples of defining the frequencies corresponding to the fields used by
compute_payout_ratio
are equivalent. However, if a list of frequencies is provided, its length must be equal to the length of the list of fields.In the example below, an additional
stock_obj
parameter is used within the aggregation function to access the single stock’s data directly. Please note that the parameters order (ts
,stock_obj
) cannot be changed, and additional parameters are not allowed.def compute_rolling_volatility(ts, stock_obj): adjusted_prices = stock_obj.adjusted_price_history(True, True) return 1 / adjusted_prices.pct_change().dropna().rolling(window=21).std()
Operator precedence: all sector operators are first applied in the order defined by the user. Then, all comparison operators are applied in the order defined by the user. Finally, all ranking operators are applied in the order defined by the user.
Sector operators:
'in'
,'not_in'
.Comparison operators:
'<'
,'<='
,'=='
,'!='
,'>='
,'>'
,'min_data_size'
.Ranking operators:
'top'
,'bottom'
,'body'
. Operator body with value x filters out the top x and bottom x stocks by the selected fundamental or history field.
To generate a composite universe from multiple stock indices:
equity_filter = sig.EquityUniverseFilter(['SPX INDEX', 'RIY INDEX'])
To override the operator precedence and use the order specified by the method
add()
:equity_filter = sig.EquityUniverseFilter('SPX INDEX', use_add_order=True)
To retain only the most liquid listing for every stock in the universe:
from sigtech.framework.equities.liquidity_indicators import LiquidityIndicators equity_filter = sig.EquityUniverseFilter('SPX INDEX', most_liquid=True, liquidity_function=LiquidityIndicators.rolling_dollar_vol)
Keyword argument
liquidity_function
is mandatory,rolling_window
,min_periods_ratio
and additional SIGMaster filters (filters
) are optional.To display all available operators:
equity_filter.OPERATORS
To retain all NaN values when applying comparison operators:
equity_filter = sig.EquityUniverseFilter('SPX INDEX', exclude_nans=False)
To display all available fields for a given stock identifier stock_id:
equity_filter.available_fields(stock_id)
To display all available TRBC categories:
equity_filter.TRBC_COLUMNS
-
OPERATORS = ['<', '<=', '==', '!=', '>=', '>', 'min_data_size', 'top', 'bottom', 'body', 'in', 'not_in']
Filter operators available.
-
FREQUENCIES = ['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Restated – Quarterly', 'Quarterly – Cumulative', 'Restated – Quarterly Cumulative', 'Semi-Annual', 'Annual', 'Restated – Annual', 'Trimester', 'Trimester - Cumulative', 'Restated – Semi-Annual', 'Restated – Trimester', 'Restated – Trimester Cumulative']
Fundamental frequencies available.
-
TRBC_COLUMNS = ['TRBC_ECONOMIC_SECTOR', 'TRBC_BUSINESS_SECTOR', 'TRBC_INDUSTRY_GROUP', 'TRBC_INDUSTRY', 'TRBC_ACTIVITY']
TRBC fields available
-
universe_ids(date: Union[pandas._libs.tslibs.timestamps.Timestamp, datetime.date, datetime.datetime]) list
Return a list of stock IDs representing the universe at a point in time. The output is affected by the flag
most_liquid
set in the constructor.- Parameters
date – A point in time (timestamp, date or datetime).
- Returns
List of stock IDs representing the universe at a point in time.
-
available_fields(stock_id: str) dict
History fields and fundamental fields available for an underlying.
- Parameters
stock_id – Stock identifier.
- Returns
Dict of history and fundamental fields with list of available frequencies.
-
available_frequencies(field: str, date: Optional[Union[pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime]] = None) list[str]
Return a list of frequencies available for all stocks in the universe.
- Parameters
field – Fundamental or history field.
date – An optional point in time for the universe (timestamp or datetime). If not provided, the universe considered is the superset of all the individual points in time.
- Returns
List of frequencies available for all stocks in the universe.
-
add(field: Union[str, list[str]], op: str, value: Union[int, float, str, tuple], frequency: Optional[Union[str, list[str]]] = None, aggr_method=None, percent: bool = False, analyst_estimates=False, **kwargs) None
Add a filter to the list of filters.
- Parameters
field – Fundamental field, history field, IBES analyst estimates field, list of fundamental/history fields, TRBC sector identifier or list of TRBC sector identifiers. If a list of sector identifiers is provided, the logic
AND
operator is applied while filtering using'not_in'
, whereas the logicOR
operator is applied while filtering using'in'
.op – Filter operator.
value – Value/threshold.
frequency – Field frequency or list of field frequencies (only required for fundamental and history fields).
aggr_method – Customised aggregation method (optional).
percent – Value parameter is in percentage (default is False).
analyst_estimates – Filter is based on IBES analyst estimates field (default is False).
kwargs – Additional keyword arguments, e.g.
metric
andhistorical_period_index
for IBES analyst estimates.
-
clean() None
Empty the list of filters defined by the user.
-
apply_filter(dates: Union[pandas._libs.tslibs.timestamps.Timestamp, datetime.date, datetime.datetime, list[datetime.date], list[datetime.datetime], pandas.core.indexes.datetimes.DatetimeIndex], ignore_asofdate: bool = True) pandas.core.series.Series
Filter a stock universe according to a set of filters.
- Parameters
dates – A
date
,datetime
, pandastimestamp
or set of datetimes (pandasDatetimeIndex
). If the universe is represented by an index, the index constituents on the dates provided are used. If the universe is represented by a customised dict, the dates provided should be in the set of universe dates.ignore_asofdate – If set to True, timeseries data are retrieved using the as_of_date of the environment. If set to False, the as_of_date of the timeseries coincides with the date in which the filter is applied (when applied to multiple dates, this setting may be more computationally expensive).
- Returns
A pandas series (date: list of filtered stock identifiers).
-
display_fields_data(date: Union[pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime], ids: list[str], fields: list[str], frequencies: list[str], ignore_asofdate: bool = True) pandas.core.frame.DataFrame
Return a DataFrame containing timeseries data defined by a date and a list of stock IDs, fields and frequencies.
- Parameters
date – A point in time (timestamp, date or datetime).
ids – List of stock identifiers.
fields – List of field identifiers.
frequencies – List of field frequencies.
ignore_asofdate – If set to True, timeseries data are retrieved using the as_of_date of the environment. If set to False, the as_of_date of the timeseries coincides with the display date (this setting may be more computationally expensive).
- Returns
pandas.DataFrame.
-
diff_additions() Optional[pandas.core.series.Series]
Return the stocks added at every point in time given last timeseries computed by
apply_filter
. If less that two data points are available, the method returns None.For instance, given the following filtered stocks:
2019-01-15: [Z, B] 2019-01-16: [Z, E] 2019-01-17: [Z, E] 2019-01-18: [Z, D] 2019-01-21: [Z, A]
The method returns:
2019-01-16: [E] 2019-01-17: [] 2019-01-18: [D] 2019-01-21: [A]
-
diff_deletions() Optional[pandas.core.series.Series]
Return the stocks removed at every point in time given last timeseries computed by
apply_filter
. If less that two data points are available, the method returns None.For instance, given the following filtered stocks:
2019-01-15: [Z, B] 2019-01-16: [Z, E] 2019-01-17: [Z, E] 2019-01-18: [Z, D] 2019-01-21: [Z, A]
The method returns:
2019-01-16: [B] 2019-01-17: [] 2019-01-18: [E] 2019-01-21: [D]
-
list() list
Return the list of filters defined by the user.