Universe Selection

Universe Settings

Introduction

Universe settings and security initializers enable you to configure some properties of the securities in a universe.

Resolution

The Resolution setting defines the time period of the asset data. The Resolution enumeration has the following members:

To view which resolutions are available for the asset class of your universe, follow these steps:

  1. Open the Asset Classes documentation page.
  2. Click an asset class.
  3. Click Requesting Data.
  4. On the Requesting Data page, in the table of contents, click Resolutions.

The default value is Resolution.Minute. To change the resolution, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.Resolution = Resolution.Daily;
AddUniverseSelection(new ETFConstituentsUniverseSelectionModel("SPY"));
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverseSelection(ETFConstituentsUniverseSelectionModel("SPY"))

Leverage

The Leverage setting is a floatdecimal that defines the maximum amount of leverage you can use for a single asset in a non-derivative universe. The default value is Security.NullLeverage (0). To change the leverage, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.Leverage = 2.0m;
AddUniverseSelection(new EmaCrossUniverseSelectionModel());
self.UniverseSettings.Leverage = 2.0
self.AddUniverseSelection(EmaCrossUniverseSelectionModel())

Fill Forward

The FillForward setting is a bool that defines whether or not too fill forward data. The default value is trueTrue. To disable fill forward in non-derivative universes, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.FillForward = false;
AddUniverseSelection(
    new OptionUniverseSelectionModel(
        TimeSpan.FromDays(1), 
        _ => new [] { QuantConnect.Symbol.Create("SPY", SecurityType.Option, Market.USA) }
    )
);
from Selection.OptionUniverseSelectionModel import OptionUniverseSelectionModel 

self.UniverseSettings.FillForward = False
self.AddUniverseSelection(
    OptionUniverseSelectionModel(
        timedelta(1), lambda _: [Symbol.Create("SPY", SecurityType.Option, Market.USA)]
    )
)

Extended Market Hours

The ExtendedMarketHours setting is a bool that defines the trading schedule. If it's trueTrue, your algorithm receives price data for all trading hours. If it's falseFalse, your algorithm receives price data only for regular trading hours. The default value is falseFalse.

You only receive extended market hours data if you create the subscription with an intraday resolution. If you create the subscription with daily resolution, the daily bars only reflect the regular trading hours.

To view the trading schedule of an asset, open Asset Classes, click an asset class, then click Market Hours.

To enable extended market hours, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.ExtendedMarketHours = true;
var tickers = new[] {"SPY", "QQQ", "IWM"};
var symbols = tickers.Select(ticker => QuantConnect.Symbol.Create(ticker, SecurityType.Equity, Market.USA));
AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
self.UniverseSettings.ExtendedMarketHours = True
tickers = ["SPY", "QQQ", "IWM"]
symbols = [ Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers]
self.AddUniverseSelection(ManualUniverseSelectionModel(symbols))

Minimum Time in Universe

The MinimumTimeInUniverse setting is a timedeltaTimeSpan object that defines the minimum amount of time an asset must be in the universe before the universe can remove it. The default value is TimeSpan.FromDays(1)timedelta(1). To change the minimum time, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.MinimumTimeInUniverse = TimeSpan.FromDays(7);
AddUniverseSelection(new ETFConstituentsUniverseSelectionModel("QQQ"));
self.UniverseSettings.MinimumTimeInUniverse = timedelta(7)
self.AddUniverseSelection(ETFConstituentsUniverseSelectionModel("QQQ"))

Data Normalization Mode

The DataNormalizationMode setting is an enumeration that defines how historical data is adjusted. This setting is only applicable for US Equities and Futures.

In the case of US Equities, the data normalization mode affects how historical data is adjusted for corporate actions. To view all the available options, see Data Normalization. To change the data normalization mode, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

In the case of Futures, the data normalization mode affects how historical data of two contracts is stitched together to form the continuous contract. To view all the available options, see Data Normalization.

The default value is DataNormalizationMode.Adjusted. To change the data normalization mode, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;

var tickers = new[] {"MSTR", "MSFT", "IBM"};
var symbols = tickers.Select(ticker => QuantConnect.Symbol.Create(ticker, SecurityType.Equity, Market.USA));
AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw

tickers = ["MSTR", "MSFT", "IBM"]
symbols = [ Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers]
self.AddUniverseSelection(ManualUniverseSelectionModel(symbols))

Contract Depth Offset

The ContractDepthOffset setting is an int that defines which contract to use for the continuous Futures contract. 0 is the front month contract, 1 is the following back month contract, and 3 is the second back month contract. The default value is 0. To change the contract depth offset, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.ContractDepthOffset = 1;
AddUniverseSelection(
    new FutureUniverseSelectionModel(
        TimeSpan.FromDays(1), 
        _ => new List<Symbol> {{ QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME) }}
    )
);
from Selection.FutureUniverseSelectionModel import FutureUniverseSelectionModel

self.UniverseSettings.ContractDepthOffset = 1
self.AddUniverseSelection(
    FutureUniverseSelectionModel(
        timedelta(1), 
        lambda _: [Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME)]
    )
)

Asynchronous Selection

The Asynchronous setting is a bool that defines whether or not LEAN can run universe selection asynchronously, utilizing concurrent execution to increase the speed of your algorithm. The default value for this setting is falseFalse. If you enable this setting, abide by the following rules:

  • Don't make any history requests in your filter function. History requests can only provide data up to the algorithm time, but if your filter function runs asynchronously, the algorithm time may not be what you expect.
  • Don't use the portfolio, security, or orders state. The Portfolio, Securities, and Transactions objects are also functions of the algorithm time.
  • If your filter function updates a class variable, don't update the class variable anywhere else in your algorithm.

To enable asynchronous universe selection, in the Initialize method, adjust the algorithm's UniverseSettings before you create the Universe Selection model.

UniverseSettings.Asynchronous = true;
AddUniverseSelection(new EmaCrossUniverseSelectionModel());
self.UniverseSettings.Asynchronous = True
self.AddUniverseSelection(EmaCrossUniverseSelectionModel())

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. The GetLastKnownPrices method seeds the security price by gathering the security data over the last 3 days. If there is no data during this period, the security price remains at 0.

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)));

// Outside of the algorithm class
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)))

# Outside of the algorithm class
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"))

To set a seeder function without overwriting the reality models of the brokerage, use the standard BrokerageModelSecurityInitializer.

SetSecurityInitializer(new BrokerageModelSecurityInitializer(BrokerageModel, new FuncSecuritySeeder(GetLastKnownPrices)));
self.SetSecurityInitializer(BrokerageModelSecurityInitializer(self.BrokerageModel, FuncSecuritySeeder(self.GetLastKnownPrices)))

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: