Contents
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
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
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.AddUniverseSelection(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.
AddUniverseSelection(new EmaCrossUniverseSelectionModel()); AddUniverseSelection(new TechnologyETFUniverse());
self.AddUniverseSelection(EmaCrossUniverseSelectionModel()) self.AddUniverseSelection(TechnologyETFUniverse())
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 CreateUniverses(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 GetNextRefreshTimeUtc(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.
Universe Settings
The universe settings of your algorithm configure some properties of the universe constituents. The following table describes the properties of the UniverseSettings
object:
Property | Data Type | Description | Default Value |
---|---|---|---|
ExtendedMarketHours | bool | Should assets also feed extended market hours? | false False |
FillForward | bool | Should asset data fill forward? | true True |
MinimumTimeInUniverse | TimeSpan timedelta | What's the minimum time assets should be in the universe? | TimeSpan.FromDays(1) timedelta(1) |
Resolution | Resolution | What resolution should assets use? | Resolution.Minute |
ContractDepthOffset | int | What offset from the current front month should be used for continuous Future contracts? 0 uses the front month and 1 uses the back month contract. This setting is only available for Future assets. | 0 |
DataMappingMode | DataMappingMode | How should continuous Future contracts be mapped? This setting is only available for Future assets. | DataMappingMode.OpenInterest |
DataNormalizationMode | DataNormalizationMode | How should historical prices be adjusted? This setting is only available for Equity and Futures assets. | DataNormalizationMode.Adjusted |
Leverage | decimal float | What leverage should assets use in the universe? This setting is not available for derivative assets. | Security.NullLeverage |
To set the UniverseSettings
, update the preceding properties in the Initialize
method before you add the Universe Selection model. These settings are globals, so they apply to all universes you create.
// Request second resolution data. This will be slow! UniverseSettings.Resolution = Resolution.Second; AddUniverseSelection(new VolatilityETFUniverse());
# Request second resolution data. This will be slow! self.UniverseSettings.Resolution = Resolution.Second self.AddUniverseSelection(VolatilityETFUniverse())
Configure Securities
Instead of configuring global universe settings, you can individually configure the settings of each security in the universe with a security initializer. Security initializers let you apply any security-level reality model or special data requests on a per-security basis. To set the security initializer, in the Initialize
method, call the SetSecurityInitializer
method and then define the security initializer.
//In Initialize SetSecurityInitializer(CustomSecurityInitializer); private void CustomSecurityInitializer(Security security) { // Disable trading fees security.SetFeeModel(new ConstantFeeModel(0, "USD")); }
#In Initialize self.SetSecurityInitializer(self.CustomSecurityInitializer) def CustomSecurityInitializer(self, security: Security) -> None: # Disable trading fees security.SetFeeModel(ConstantFeeModel(0, "USD"))
For simple requests, you can use the functional implementation of the security initializer. This style lets you configure the security object with one line of code.
SetSecurityInitializer(security => security.SetFeeModel(new ConstantFeeModel(0, "USD")));
self.SetSecurityInitializer(lambda security: security.SetFeeModel(ConstantFeeModel(0, "USD")))
In some cases, you may want to trade a security in the same time loop that you create the security subscription. To avoid errors, use a security initializer to set the market price of each security to the last known price.
var seeder = new FuncSecuritySeeder(GetLastKnownPrices); SetSecurityInitializer(security => seeder.SeedSecurity(security));
seeder = FuncSecuritySeeder(self.GetLastKnownPrices) self.SetSecurityInitializer(lambda security: seeder.SeedSecurity(security))
If you call the SetSecurityInitializer
method, it overwrites the default security initializer. The default security initializer uses the security-level reality models of the brokerage model to set the following reality models of each security:
The default security initializer also sets the leverage of each security and intializes each security with a seeder function. To extend upon the default security initializer instead of overwriting it, create a custom BrokerageModelSecurityInitializer
.
// In Initialize SetSecurityInitializer(new MySecurityInitializer(BrokerageModel, new FuncSecuritySeeder(GetLastKnownPrices))); class MySecurityInitializer : BrokerageModelSecurityInitializer { public MySecurityInitializer(IBrokerageModel brokerageModel, ISecuritySeeder securitySeeder) : base(brokerageModel, securitySeeder) {} public override void Initialize(Security security) { // First, call the superclass definition // This method sets the reality models of each security using the default reality models of the brokerage model base.Initialize(security); // Next, overwrite some of the reality models security.SetFeeModel(new ConstantFeeModel(0, "USD")); } }
# In Initialize self.SetSecurityInitializer(MySecurityInitializer(self.BrokerageModel, FuncSecuritySeeder(self.GetLastKnownPrices))) class MySecurityInitializer(BrokerageModelSecurityInitializer): def __init__(self, brokerage_model: IBrokerageModel, security_seeder: ISecuritySeeder) -> None: super().__init__(brokerage_model, security_seeder) def Initialize(self, security: Security) -> None: # First, call the superclass definition # This method sets the reality models of each security using the default reality models of the brokerage model super().Initialize(security) # Next, overwrite some of the reality models security.SetFeeModel(ConstantFeeModel(0, "USD"))
Track Security Changes
When the Universe Selection model adjusts the universe constituents, we notify your algorithm through the OnSecuritiesChanged
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
property. To access the removed securities, check the changes.RemovedSecurities
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 OnSecuritiesChanged(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None: for security in changes.AddedSecurities: self.Log(f"Added {security.Symbol}") for security in changes.RemovedSecurities: 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
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.