Universe Selection
Legacy Fundamental Universes
Introduction
Warning: This API for Universe Selection was deprecated on November 2023. Please refer to the new Fundamental Selection API.
A FundamentalUniverseSelectionModel
selects a universe of US Equities based on CoarseFundamental
and, sometimes, FineFundamental
data. If the model uses CoarseFundamental
data, it relies on the US Equity Coarse Universe dataset. If the Universe Selection model uses FineFundamental
data, it relies on the US Fundamental dataset.
These types of universes operate on daily schedule. In backtests, they select assets at midnight. In live trading, the selection timing depends on the data provider you use.
If you use a fundamental Universe Selection model, the only way to unsubscribe from a security is to return a list from the selection functions that doesn't include the security Symbol
. The RemoveSecurity
remove_security
method doesn't work with these types of Universe Selection models.
Coarse Fundamental Selection
The CoarseFundamentalUniverseSelectionModel
selects assets based on CoarseFundamental
data. To use this model, define a coarse selection function. The coarse selection function receives a list of
CoarseFundamental
objects and returns a list of Symbol
objects. The Symbol
objects you return from the coarse selection function are the constituents of the universe.
// Set asynchronous universe settings for improved speed and use CoarseFundamentalUniverseSelectionModel with a custom function to select the top 100 most liquid assets with available fundamental data, ensuring the universe consists of liquid and fundamentally strong securities for stable returns. public override void Initialize() { UniverseSettings.Asynchronous = true; AddUniverseSelection(new CoarseFundamentalUniverseSelectionModel(SelectCoarse)); } private IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> coarse) { // Return most liquid assets w/ fundamentals return coarse.Where(c => c.HasFundamentalData) .OrderByDescending(c => c.DollarVolume) .Take(100) .Select(c => c.Symbol); }
# Set asynchronous universe settings for improved speed and use CoarseFundamentalUniverseSelectionModel with a custom function to select the top 100 most liquid assets with available fundamental data, ensuring the universe consists of liquid and fundamentally strong securities for stable returns. def initialize(self) -> None: self.universe_settings.asynchronous = True self.add_universe_selection(CoarseFundamentalUniverseSelectionModel(self.select_coarse)) def select_coarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]: selected = [c for c in coarse if c.has_fundamental_data] sorted_by_dollar_volume = sorted(selected, key=lambda c: c.dollar_volume, reverse=True) return [c.symbol for c in sorted_by_dollar_volume[:100]] # Return most liquid assets w/ fundamentals
To move the coarse selection function outside of the algorithm class, create a universe selection model that inherits the CoarseFundamentalUniverseSelectionModel
class.
// Move the coarse selection function outside of the algorithm class by creating a custom universe selection model inheriting from CoarseFundamentalUniverseSelectionModel, allowing for modification and reusability of the selection logic. UniverseSettings.Asynchronous = true; AddUniverseSelection(new MostLiquidFundamentalUniverseSelectionModel(UniverseSettings)); // Outside of the algorithm class class MostLiquidFundamentalUniverseSelectionModel : CoarseFundamentalUniverseSelectionModel { public MostLiquidFundamentalUniverseSelectionModel(UniverseSettings universeSettings) : base(default(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>>), universeSettings) { } public override IEnumerable<Symbol> SelectCoarse(QCAlgorithm algorithm, IEnumerable<CoarseFundamental> coarse) { return coarse.Where(c => c.HasFundamentalData) .OrderByDescending(c => c.DollarVolume) .Take(100) .Select(c => c.Symbol); } }
# Move the coarse selection function outside of the algorithm class by creating a custom universe selection model inheriting from CoarseFundamentalUniverseSelectionModel, allowing for modification and reusability of the selection logic. self.universe_settings.asynchronous = True self.add_universe_selection(MostLiquidFundamentalUniverseSelectionModel(self.universe_settings)) # Outside of the algorithm class class MostLiquidFundamentalUniverseSelectionModel(CoarseFundamentalUniverseSelectionModel): def __init__(self, universe_settings: UniverseSettings) -> None: super().__init__(self.select_coarse, universe_settings) def select_coarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]: selected = [c for c in coarse if c.has_fundamental_data] sorted_by_dollar_volume = sorted(selected, key=lambda c: c.dollar_volume, reverse=True) return [c.symbol for c in sorted_by_dollar_volume[:100]]
To return the current universe constituents from the coarse selection function, return Universe.Unchanged
.
To view the implementation of this model, see the LEAN GitHub repository.
Fine Fundamental Selection
The FineFundamentalUniverseSelectionModel
selects assets based on CoarseFundamental
and FineFundamental
data. This is the only model that provides corporate fundamental data to your algorithm. To use this model, define a coarse selection function and a fine selection function. The coarse selection function receives a list of
CoarseFundamental
objects and returns a list of Symbol
objects. To filter the CoarseFundamental
down to the securities that have fundamental data, add a HasFundamentalData
has_fundamental_data
filter to the coarse selection function. The fine selection function receives a subset of FineFundamental
objects generated from coarse selection results and returns a list of Symbol
objects. The Symbol
objects you return from the fine selection function are the constituents of the universe.
// FineFundamentalUniverseSelectionModel integrates corporate fundamental data into the algorithm through a two-step filtering process: coarse selection ensures liquidity and fundamental data availability, while fine selection focuses on valuation metrics, refining the universe of selected stocks. public override void Initialize() { UniverseSettings.Asynchronous = true; AddUniverseSelection(new FineFundamentalUniverseSelectionModel(SelectCoarse, SelectFine)); } private IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> coarse) { // Return most liquid assets w/ fundamentals return coarse.Where(c => c.HasFundamentalData) .OrderByDescending(c => c.DollarVolume) .Take(100) .Select(c => c.Symbol); } private IEnumerable<Symbol> SelectFine(IEnumerable<FineFundamental> fine) { // Return assets with lowest P/E ratios return fine.OrderBy(f => f.ValuationRatios.PERatio) .Take(10) .Select(f => f.Symbol); }
# FineFundamentalUniverseSelectionModel integrates corporate fundamental data into the algorithm through a two-step filtering process: coarse selection ensures liquidity and fundamental data availability, while fine selection focuses on valuation metrics, refining the universe of selected stocks. def initialize(self) -> None: self.universe_settings.asynchronous = True self.add_universe_selection(FineFundamentalUniverseSelectionModel(self.select_coarse, self.select_fine)) def select_coarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]: selected = [c for c in coarse if c.has_fundamental_data] sorted_by_dollar_volume = sorted(selected, key=lambda c: c.dollar_volume, reverse=True) return [c.symbol for c in sorted_by_dollar_volume[:100]] # Return most liquid assets w/ fundamentals def select_fine(self, fine: List[FineFundamental]) -> List[Symbol]: sorted_by_pe_ratio = sorted(fine, key=lambda x: x.valuation_ratios.pe_ratio, reverse=False) return [c.symbol for c in sorted_by_pe_ratio[:10]] # Return assets with lowest P/E ratios
To move the selection functions outside of the algorithm class, create a universe selection model that inherits the FineFundamentalUniverseSelectionModel
class.
// Create a custom universe selection model inheriting from FineFundamentalUniverseSelectionModel to move both coarse and fine selection functions outside the algorithm class, enabling easier modification and reusability of the filtering and ranking logic. UniverseSettings.Asynchronous = true; AddUniverseSelection(new LowPERatioUniverseSelectionModel(UniverseSettings)); // Outside of the algorithm class class LowPERatioUniverseSelectionModel : FineFundamentalUniverseSelectionModel { public LowPERatioUniverseSelectionModel(UniverseSettings universeSettings = null) : base(default(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>>), default(Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>>), universeSettings) { } public override IEnumerable<Symbol> SelectCoarse(QCAlgorithm algorithm, IEnumerable<CoarseFundamental> coarse) { return coarse.Where(c => c.HasFundamentalData) .OrderByDescending(c => c.DollarVolume) .Take(100) .Select(c => c.Symbol); } public override IEnumerable<Symbol> SelectFine(QCAlgorithm algorithm, IEnumerable<FineFundamental> fine) { return fine.OrderBy(f => f.ValuationRatios.PERatio) .Take(10) .Select(f => f.Symbol); } }
# Create a custom universe selection model inheriting from FineFundamentalUniverseSelectionModel to move both coarse and fine selection functions outside the algorithm class, enabling easier modification and reusability of the filtering and ranking logic. self.universe_settings.asynchronous = True self.add_universe_selection(LowPERatioUniverseSelectionModel(self.universe_settings)) # Outside of the algorithm class class LowPERatioUniverseSelectionModel(FineFundamentalUniverseSelectionModel): def __init__(self, universe_settings: universe_settings = None) -> None: super().__init__(self.select_coarse, self.select_fine, universe_settings) def select_coarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]: selected = [c for c in coarse if c.has_fundamental_data] sorted_by_dollar_volume = sorted(selected, key=lambda c: c.dollar_volume, reverse=True) return [c.symbol for c in sorted_by_dollar_volume[:100]] def select_fine(self, fine: List[FineFundamental]) -> List[Symbol]: sorted_by_pe_ratio = sorted(fine, key=lambda x: x.valuation_ratios.pe_ratio, reverse=False) return [c.symbol for c in sorted_by_pe_ratio[:10]]
To return the current universe constituents from the coarse or fine selection function, return Universe.UnchangedUNCHANGED
.
If you add a FineFundamentalUniverseSelectionModel
to your algorithm, you can access fundamental data in the fine selection function or from the Equity
object. To access fundamental data from the Equity
object, use the Equity.Fundamentalsfundamentals
property.
To view the implementation of this model, see the LEAN GitHub repository.