Universe Selection

Key Concepts

Introduction

The Universe Selection model creates Universe objects, which select the assets for your algorithm. As the universe changes, we notify your algorithm through the OnSecuritiesChangedon_securities_changed event handler. With this event handler, you can track the current universe constituents in other parts of your algorithm without breaking the separation of concerns design principle.

Types of Universe Selection

We have identified several types of universes that cover most people's requirements and built helper classes to make their implementation easier. The following table describes the types of pre-built Universe Selection models:

Universe TypeDescription
Manual UniversesUniverses that use a fixed, static set of assets
Fundamental UniversesUniverses for US Equities that are based on coarse price or fundamental data
Scheduled UniversesUniverses that trigger on regular, custom intervals
Futures UniversesUniverses that subscribe to Future chains
Option UniversesUniverses that subscribe to Option chains

Add Models

To add a Universe Selection model, in the Initializeinitialize method, call the AddUniverseSelection method.

var symbols = new [] {QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)};
AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
symbols = [Symbol.create("SPY", SecurityType.EQUITY, Market.USA)]
self.add_universe_selection(ManualUniverseSelectionModel(symbols))

To view all the pre-built Universe Selection models, see Types of Universe Selection.

Multi-Universe Algorithms

You can add multiple Universe Selection models to a single algorithm.

UniverseSettings.Asynchronous = true;
var symbols = new [] {QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)};
AddUniverseSelection(new ManualUniverseSelectionModel(symbols));

AddUniverseSelection(new EmaCrossUniverseSelectionModel());
self.universe_settings.asynchronous = True
symbols = [Symbol.create("SPY", SecurityType.EQUITY, Market.USA)]
self.add_universe_selection(ManualUniverseSelectionModel(symbols))
		
self.add_universe_selection(EmaCrossUniverseSelectionModel())

If you add multiple Universe Selection models, the algorithm subscribes to the constituents of all the models.

Model Structure

Universe Selection models should extend the UniverseSelectionModel class. Extensions of the UniverseSelectionModel class must implement the CreateUniverses method, which receives an algorithm object and returns an array of Universe objects.

public class MyUniverseSelectionModel : UniverseSelectionModel
{
    // Creates the universes for this algorithm
    public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
    {
        return new List<Universe>();
    }

    // Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
    public override DateTime GetNextRefreshTimeUtc()
    {
        return DateTime.MaxValue;
    }
}
class MyUniverseSelectionModel(UniverseSelectionModel):

    # Creates the universes for this algorithm
    def create_universes(self, algorithm: QCAlgorithm) -> List[Universe]:
        universes = []
        return universes
    
    # Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
    def get_next_refresh_time_utc(self):
        return datetime.max

The algorithm argument that the methods receive is an instance of the base QCAlgorithm class, not your subclass of it.

Generally, you should be able to extend one of the pre-built Universe Selection types. If you need to do something that doesn't fit into the pre-built types, let us know and we'll create a new foundational type of Universe Selection model.

Track Security Changes

When the Universe Selection model adjusts the universe constituents, we notify your algorithm through the OnSecuritiesChangedon_securities_changed event handler on your other framework components. The method receives QCAlgorithm and SecurityChanges objects. The QCAlgorithm object is an instance of the base QCAlgorithm class, not a reference to your algorithm object. To access the added securities, check the changes.AddedSecuritieschanges.added_securities method property. To access the removed securities, check the changes.RemovedSecuritieschanges.removed_securities method property.

public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
    foreach (var security in changes.AddedSecurities)
    {
        Log($"Added {security.Symbol}");
    }

    foreach (var security in changes.RemovedSecurities)
    {
        Log($"Removed {security.Symbol}");
    }
}
def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    for security in changes.added_securities::
        self.log(f"Added {security.symbol}")

    for security in changes.removed_securities:
        self.log(f"Removed {security.symbol}")

Live Trading Considerations

In live trading, the securities in your brokerage account are added to your user-defined universe. If your Universe Selection model doesn't select these securities, they are not removed from your user-defined universe. When you liquidate the positions, you can remove them from the user-defined universe. If you call the RemoveSecurityremove_security method, it automatically liquidates the position.

To see the securities in your user-defined universe that were loaded from your brokerage account, check your algorithm's ActiveSecurities in the OnWarmupFinished event handler.

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: