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 OnSecuritiesChanged
on_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 Type | Description |
---|---|
Manual Universes | Universes that use a fixed, static set of assets |
Fundamental Universes | Universes for US Equities that are based on coarse price or fundamental data |
Scheduled Universes | Universes that trigger on regular, custom intervals |
Futures Universes | Universes that subscribe to Future chains |
Option Universes | Universes that subscribe to Option chains |
Add Models
To add a Universe Selection model, in the Initialize
initialize
method, call the AddUniverseSelection
method.
var symbols = new [] {QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)}; AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
# Adds a universe selection model to the algorithm, manually defining the set of securities to include in the algorithm. 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.
// Configures asynchronous universe settings for faster updates and includes both manual and EMA cross universe selection models for dynamic and static selection. UniverseSettings.Asynchronous = true; var symbols = new [] {QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)}; AddUniverseSelection(new ManualUniverseSelectionModel(symbols)); AddUniverseSelection(new EmaCrossUniverseSelectionModel());
# Configures asynchronous universe settings for faster updates and includes both manual and EMA cross universe selection models for dynamic and static selection. 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
create_universes
method, which receives an algorithm
object and returns an array of Universe
objects.
// Extend UniverseSelectionModel to define a custom security universe tailored to the algorithm. 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; } }
# Extend UniverseSelectionModel to define a custom security universe tailored to the algorithm. 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 OnSecuritiesChanged
on_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.AddedSecurities
changes.added_securities
method property. To access the removed securities, check the changes.RemovedSecurities
changes.removed_securities
method property.
// Log added and removed securities to update the universe and adapt the strategy. 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}"); } }
# Log added and removed securities to update the universe and adapt the strategy. 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 RemoveSecurity
remove_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 ActiveSecuritiesactive_securities in the OnWarmupFinishedon_warmup_finished event handler.