Universe Selection

Fundamental Universes

Introduction

A FundamentalUniverseSelectionModel selects a universe of US Equities based on Fundamental data. Depending on the Fundamental properties you use, these universes rely on the US Equity Coarse Universe dataset, the US Fundamental dataset, or both.

These types of universes operate on daily schedule by default. In backtests, they select assets at midnight. In live trading, the selection timing depends on the data provider you use. To adjust the selection schedule, see Schedule.

If you use a fundamental Universe Selection model, the only way to unsubscribe from a security is to return a list from the selection function that doesn't include the security Symbol. The RemoveSecurityremove_security method doesn't work with these types of Universe Selection models.

Fundamental Selection

The FundamentalUniverseSelectionModel lets you select stocks based on corporate Fundamental data. You can specific the selection method, which takes a list of Fundamental objects as argument and returns a list of Symbol objects.

public override void Initialize()
{
    UniverseSettings.Asynchronous = true;
    AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
}

public override List<Symbol> FundamentalFilterFunction(List<Fundamental> fundamental)
{
    return (from f in fundamental
            where f.HasFundamentalData && f.Price > 10 && !Double.IsNaN(f.ValuationRatios.PERatio)
            orderby f.ValuationRatios.PERatio
            select f.Symbol).Take(10);
}
def initialize(self) -> None:
    self.universe_settings.asynchronous = True
    self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_filter_function))

def fundamental_filter_function(self, fundamental: List[Fundamental]):
    filtered = [f for f in fundamental if f.has_fundamental_data and f.price > 10 and not np.isnan(f.valuation_ratios.pe_ratio)]
    sorted_by_pe_ratio = sorted(filtered, key=lambda f: f.valuation_ratios.pe_ratio)
    return [f.symbol for f in sorted_by_pe_ratio[:10]]

The following table describes the arguments the model accepts:

ArgumentData TypeDescriptionDefault Value
selector Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> Callable[[List[Fundamental]], List[Symbol]]Filter function to select assets based on fundamental data.
universeSettingsuniverse_settingsUniverseSettingsThe universe settings. If you don't provide an argument, the model uses the algorithm.UniverseSettingsalgorithm.universe_settings by default.Nonenull

The Fundamental objects have the following properties:

To move the selection function outside of the algorithm class, create a universe selection model that inherits the FundamentalUniverseSelectionModel class and override its Select method.

// In Initialize
UniverseSettings.Asynchronous = true;            
AddUniverseSelection(new LiquidAndLowPEUniverseSelectionModel());

// Outside of the algorithm class
public class LiquidAndLowPEUniverseSelectionModel : FundamentalUniverseSelectionModel
{
    public override IEnumerable Select(QCAlgorithm algorithm, IEnumerable fundamental)
    {
        return fundamental
            // select symbols with fundamental data and a price above $1
            .Where(x => x.HasFundamentalData && x.Price > 1 && !Double.IsNaN(x.ValuationRatios.PERatio))
            // sort descending by daily dollar volume
            .OrderByDescending(x => x.DollarVolume)
            .Take(100)
            // sort descending by P/E ratio
            .OrderByDescending(x => x.ValuationRatios.PERatio)
            .Take(10)
            .Select(x => x.Symbol);
    }
}
# In Initialize
self.UniverseSettings.Asynchronous = True
self.AddUniverseSelection(LiquidAndLowPEUniverseSelectionModel())

# Outside of the algorithm class
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
class LiquidAndLowPEUniverseSelectionModel(FundamentalUniverseSelectionModel):
    def Select(self, algorithm: QCAlgorithm, fundamental: List[Fundamental]) -> List[Symbol]:
        filtered = [x for x in fundamental if x.Price > 1 and not np.isnan(x.ValuationRatios.PERatio)]
        most_liquid = sorted(filtered, key=lambda x: x.DollarVolume)[-100:]
        lowest_pe_ratio = sorted(most_liquid, key=lambda x: x.ValuationRatios.PERatio)[:10]
        return [x.Symbol for x in lowest_pe_ratio]

To return the current universe constituents from the selection function, return Universe.Unchanged.

To view the implementation of this model, see the LEAN GitHub repositoryLEAN GitHub repository.

EMA Cross Selection

The EmaCrossUniverseSelectionModel applies two exponential moving average (EMA) indicators to the price history of assets and then selects the assets that have their fast EMA furthest above their slow EMA on a percentage basis.

public override void Initialize()
{
    UniverseSettings.Asynchronous = true;        
    AddUniverseSelection(new EmaCrossUniverseSelectionModel());
}
def initialize(self) -> None:
    self.universe_settings.asynchronous = True   
    self.add_universe_selection(EmaCrossUniverseSelectionModel())

The following table describes the arguments the model accepts:

ArgumentData TypeDescriptionDefault Value
fastPeriodintFast EMA period100
slowPeriodintSlow EMA period300
universeCountintMaximum number of members of this universe selection500
universeSettingsuniverse_settingsUniverseSettingsThe universe settings. If you don't provide an argument, the model uses the algorithm.UniverseSettingsalgorithm.universe_settings by default.Nonenull

To view the implementation of this model, see the LEAN GitHub repositoryLEAN GitHub repository.

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: