Universes

Settings

Introduction

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

Resolution

The Resolutionresolution 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.MinuteResolution.MINUTE. To change the resolution, in the Initialize method, pass a resolution argument to the universe creation method.

// Add daily Equity Option data for the SPY.
AddOption("SPY", resolution: Resolution.Daily);
# Add daily Equity Option data for the SPY.
self.add_option("SPY", resolution=Resolution.DAILY)

Leverage

The Leverageleverage 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.NullLeverageSecurity.NULL_LEVERAGE (0). To change the leverage, in the Initialize method, adjust the algorithm's UniverseSettingsuniverse_settings before you add the universe.

// Assign 2x leverage for all securities in the universe. 
UniverseSettings.Leverage = 2.0m;
// Add a universe of the 50 most liquid US Equities.
AddUniverse(Universe.DollarVolume.Top(50));
# Assign 2x leverage for all securities in the universe.  
self.universe_settings.leverage = 2.0
# Add a universe of the 50 most liquid US Equities.
self.add_universe(self.universe.dollar_volume.top(50))

Fill Forward

The FillForwardfill_forward 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 UniverseSettingsuniverse_settings before you add the universe.

// Disable fill-forward data before creating the universe (it's enabled by default). 
UniverseSettings.FillForward = false;
// Add the 50 Equities to the universe that have the most dollar trading volume.
AddUniverse(Universe.DollarVolume.Top(50));
# Disable fill-forward data before creating the universe (it's enabled by default).
self.universe_settings.fill_forward = False
# Add the 50 Equities to the universe that have the most dollar trading volume.
self.add_universe(self.universe.dollar_volume.top(50))

To disable fill forward in derivative universes, pass a fillForwardfill_forward argument to the universe creation method.

// Disable fill-forward in the VIX Index Option universe.
AddIndexOption("VIX", fillForward: false);
# Disable fill-forward in the VIX Index Option universe.
self.add_index_option("VIX", fill_forward=False)

Extended Market Hours

The ExtendedMarketHoursextended_market_hours 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 non-derivative universes, in the Initialize method, adjust the algorithm's UniverseSettingsuniverse_settings before you add the universe.

// Enable pre- and post-market hours data for assets in the universe. 
UniverseSettings.ExtendedMarketHours = true;
// Add the 50 Equities to the universe that have the most dollar trading volume.
AddUniverse(Universe.DollarVolume.Top(50));
# Enable pre- and post-market hours data for assets in the universe.
self.universe_settings.extended_market_hours = True
# Add the 50 Equities to the universe that have the most dollar trading volume.
self.add_universe(self.universe.dollar_volume.top(50))

To enable extended market hours in derivative universes, pass an extendedMarketHoursextended_market_hours argument to the universe creation method.

// Request pre- and post-market hours data for a Futures universe.
AddFuture(Futures.Currencies.BTC, extendedMarketHours: true);
# Request pre- and post-market hours data for a Futures universe.
self.add_future(Futures.Currencies.BTC, extended_market_hours=True)

Minimum Time in Universe

The MinimumTimeInUniverseminimum_time_in_universe 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 UniverseSettingsuniverse_settings before you add the universe.

// Keep each security in the universe for a minimum of 7 days.
UniverseSettings.MinimumTimeInUniverse = TimeSpan.FromDays(7);
// Add the top 50 most liquid Equities to the universe.
AddUniverse(Universe.DollarVolume.Top(50));
# Keep each security in the universe for a minimum of 7 days.
self.universe_settings.minimum_time_in_universe = timedelta(7)
# Add the top 50 most liquid Equities to the universe.
self.add_universe(self.universe.dollar_volume.top(50))

Data Normalization Mode

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

US Equities

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. The default value is DataNormalizationMode.AdjustedDataNormalizationMode.ADJUSTED. To change the data normalization mode, in the Initialize method, adjust the algorithm's UniverseSettingsuniverse_settings before you add the universe.

// Pipe raw price data (unadjusted for splits and dividends) into the algorithm. 
// Equity Options require raw data and it improves the accuracy of modeling historical periods. 
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
// Add a universe of the 50 most liquid US Equities.
AddUniverse(Universe.DollarVolume.Top(50));
# Pipe raw price data (unadjusted for splits and dividends) into the algorithm. 
# Equity Options require raw data and it improves the accuracy of modeling historical periods. 
self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
# Add a universe of the 50 most liquid US Equities.
self.add_universe(self.universe.dollar_volume.top(50))

Futures

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.AdjustedDataNormalizationMode.ADJUSTED. To change the data normalization mode, in the Initialize method, pass a dataNormalizationModedata_normalization_mode argument to the AddFutureadd_future method.

// Set a specific data normalization mode for the continuous contract 
// with the dataNormalizationMode parameter of the AddFuture method.
AddFuture(Futures.Currencies.BTC, dataNormalizationMode: DataNormalizationMode.BackwardsRatio);
# Set a specific data normalization mode for the continuous contract 
# with the data_normalization_mode parameter of the add_future method.
self.add_future(Futures.Currencies.BTC, data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO)

Contract Depth Offset

The ContractDepthOffsetcontract_depth_offset 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, pass a contractDepthOffsetcontract_depth_offset argument to the AddFutureadd_future method.

// To adjust the contract depth offset to the second back month contract, 
// pass the value 3 to the contractDepthOffset argument in the AddFuture method.
AddFuture(Futures.Currencies.BTC, contractDepthOffset: 3);
# To adjust the contract depth offset to the second back month contract, 
# pass the value 3 to the contract_depth_offset argument in the add_future method.
self.add_future(Futures.Currencies.BTC, contract_depth_offset=3)

Asynchronous Selection

The Asynchronousasynchronous 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 Portfolioportfolio, Securitiessecurities, and Transactionstransactions 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 UniverseSettingsuniverse_settings before you add the universe.

// To speed up algorithm performance, enable asynchronous universe selection. 
// Only use this when the code is self-contained and stateless.
UniverseSettings.Asynchronous = true;
AddUniverse(Universe.DollarVolume.Top(50));
# To speed up algorithm performance, enable asynchronous universe selection. 
// Only use this when the code is self-contained and stateless.
self.universe_settings.asynchronous = True
self.add_universe(self.universe.dollar_volume.top(50))

Schedule

The Scheduleschedule setting defines the selection schedule of the universe. Most universes run on a daily schedule. To change the selection schedule, call the UniverseSettings.Schedule.Onuniverse_settings.schedule.on method with an IDateRule object before you add the universe.

// Run universe selection on a monthly basis.
UniverseSettings.Schedule.On(DateRules.MonthStart());
AddUniverse(Universe.DollarVolume.Top(50));
# Run universe selection on a monthly basis.
self.universe_settings.schedule.on(self.date_rules.month_start())
self.add_universe(self.universe.dollar_volume.top(50))

The following table describes the supported DateRules:

MemberDescription
self.date_rules.set_default_time_zone(time_zone: DateTimeZone) DateRules.SetDefaultTimeZone(DateTimeZone timeZone);Sets the time zone for the DateRules object used in all methods in this table. The default time zone is the algorithm time zone.
self.date_rules.on(year: int, month: int, day: int) DateRules.On(int year, int month, int day)Trigger an event on a specific date.
self.date_rules.every_day() DateRules.EveryDay()Trigger an event every day.
self.date_rules.every_day(symbol: Symbol, extended_market_hours: bool = False) DateRules.EveryDay(Symbol symbol, bool extendedMarketHours = false)Trigger an event every day a specific symbol is trading.
self.date_rules.every(days: List[DayOfWeek]) DateRules.Every(params DayOfWeek[] days)Trigger an event on specific days throughout the week. To view the DayOfWeek enum members, see DayOfWeek Enum in the .NET documentation.
self.date_rules.month_start(days_offset: int = 0) DateRules.MonthStart(int daysOffset = 0)Trigger an event on the first day of each month plus an offset.
self.date_rules.month_start(symbol: Symbol, daysOffset: int = 0) DateRules.MonthStart(Symbol symbol, int daysOffset = 0)Trigger an event on the first tradable date of each month for a specific symbol plus an offset.
self.date_rules.month_end(days_offset: int = 0) DateRules.MonthEnd(int daysOffset = 0)Trigger an event on the last day of each month minus an offset.
self.date_rules.month_end(symbol: Symbol, daysOffset: int = 0) DateRules.MonthEnd(Symbol symbol, int daysOffset = 0)Trigger an event on the last tradable date of each month for a specific symbol minus an offset.
self.date_rules.week_start(days_offset: int = 0) DateRules.WeekStart(int daysOffset = 0)Trigger an event on the first day of each week plus an offset.
self.date_rules.week_start(symbol: Symbol, days_offset: int = 0) DateRules.WeekStart(Symbol symbol, int daysOffset = 0)Trigger an event on the first tradable date of each week for a specific symbol plus an offset.
self.date_rules.week_end(days_offset: int = 0) DateRules.WeekEnd(int daysOffset = 0)Trigger an event on the last day of each week minus an offset.
self.date_rules.week_end(symbol: Symbol, days_offset: int = 0) DateRules.WeekEnd(Symbol symbol, int daysOffset = 0)Trigger an event on the last tradable date of each week for a specific symbol minus an offset.
self.date_rules.year_start(days_offset: int = 0) DateRules.YearStart(int daysOffset = 0)Trigger an event on the first day of each year plus an offset.
self.date_rules.year_start(symbol: Symbol, days_offset: int = 0) DateRules.YearStart(Symbol symbol, int daysOffset = 0)Trigger an event on the first tradable date of each year for a specific symbol plus an offset.
self.date_rules.year_end(days_offset: int = 0) DateRules.YearEnd(int daysOffset = 0)Trigger an event on the last day of each year minus an offset.
self.date_rules.year_end(symbol: Symbol, days_offset: int = 0) DateRules.YearEnd(Symbol symbol, int daysOffset = 0)Trigger an event on the last tradable date of each year for a specific symbol minus an offset.
self.date_rules.todayDateRules.TodayTrigger an event once today.
self.date_rules.tomorrowDateRules.TomorrowTrigger an event once tomorrow.

To define custom date rules, create a FuncDateRule object. The FuncDateRule constructor expects a name argument of type stringstr and a getDatesFunctionget_dates_function argument of type Func<DateTime, DateTime, IEnumerable<DateTime>>Callable[[datetime, datetime], List[datetime]]. The getDatesFunctionget_dates_function function receives the start and end dates of the algorithm and returns a list of dates for the date rule. In live trading, the end date is 12/31/2025. The following example demonstrates how to define a date rule that represents the 10th day of each month:

// Create a date rule that specifies the 10th day of each month.
var dateRule = new FuncDateRule(
    name: "10th_day_of_the_month",
    getDatesFunction: (start, end) => Enumerable.Range(start.Year, end.Year - start.Year + 1)
        .SelectMany(year => Enumerable.Range(1, 12).Select(month => new DateTime(year, month, 10)))
);
# Create a date rule that specifies the 10th day of each month.
date_rule = FuncDateRule(
    name="10th_day_of_the_month", 
    get_dates_function=lambda start, end: [
        datetime(year, month, 10) 
        for year in range(start.year, end.year) for month in range(1,12)
    ]
) 

In live trading, scheduled universes run at roughly 8 AM Eastern Time to ensure there is enough time for the data to process.

Configure Universe 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 Initializeinitialize method, call the SetSecurityInitializerset_security_initializer method and then define the security initializer.

// A custom security initializer can override default models such as 
// setting new fee and fill models for the security.
SetSecurityInitializer(CustomSecurityInitializer);

private void CustomSecurityInitializer(Security security)
{
    security.SetFeeModel(new ConstantFeeModel(0, "USD"));
}
# A custom security initializer can override default models such as
# setting new fee and fill models for the security.
self.set_security_initializer(self._custom_security_initializer)

def _custom_security_initializer(self, security: Security) -> None:
    security.set_fee_model(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.

// Disable the trading fees for each security by passing a functional 
// implementation for the SetSecurityInitializer argument.
SetSecurityInitializer(security => security.SetFeeModel(new ConstantFeeModel(0, "USD")));
# Disable the trading fees for each security by using lambda function 
# for the set_security_initializer argument.
self.set_security_initializer(lambda security: security.set_fee_model(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 GetLastKnownPricesget_last_known_prices 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.

// Gather the last 3 days of security prices by using GetLastKnowPrice as the seed in Initialize.
var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
SetSecurityInitializer(security => seeder.SeedSecurity(security));
# Gather the last 3 days of security prices by using get_last_known_prices as the seed in initialize.
seeder = FuncSecuritySeeder(self.get_last_known_prices)
self.set_security_initializer(lambda security: seeder.seed_security(security))

If you call the SetSecurityInitializerset_security_initializer 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.

public class BrokerageModelExampleAlgorithm : QCAlgorithm
{
    public override void Initialize()
    {
        // In the Initialize method, set the security initializer to seed initial the prices and models of assets.
        SetSecurityInitializer(new MySecurityInitializer(BrokerageModel, new FuncSecuritySeeder(GetLastKnownPrices)));
    }
}

public 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"));    }
}
class BrokerageModelExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        # In the Initialize method, set the security initializer to seed initial the prices and models of assets.
        self.set_security_initializer(MySecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices)))

# 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.set_fee_model(ConstantFeeModel(0, "USD"))

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

var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
SetSecurityInitializer(new BrokerageModelSecurityInitializer(BrokerageModel, seeder));
seeder = FuncSecuritySeeder(self.get_last_known_prices)
self.set_security_initializer(BrokerageModelSecurityInitializer(self.brokerage_model, seeder))

Examples

The following examples demonstrate some common practices for universe settings.

Example 1: Weekly-Updating Liquid Universe

The following algorithm demonstrates daily EMA cross, trading on the top 10 most liquid stocks. The universe is set to be updated weekly. Various universe settings have been set to simulate the brokerage environment best and for trading needs.

public class UniverseSettingsAlgorithm : QCAlgorithm
{
    public override void Initialize()
    {
        SetStartDate(2021, 1, 1);
        SetEndDate(2021, 2, 1);
        
        // To avoid over-updating the universe, which causes insufficient time to earn the trend, update the universe weekly.
        UniverseSettings.Schedule.On(DateRules.WeekStart());
        UniverseSettings.MinimumTimeInUniverse = TimeSpan.FromDays(7);
        // Rebalancing frequency is daily, so we only need to subscribe to daily resolution.
        UniverseSettings.Resolution = Resolution.Daily;
        // To best simulate IB's margin requirement set the leverage to 50%.
        UniverseSettings.Leverage = 2;
        // Since we trade by market order, we cannot use extended market hours data to fill.
        UniverseSettings.ExtendedMarketHours = false;
        // We want to trade the EMA with raw price but not altered by splits.
        UniverseSettings.DataNormalizationMode = DataNormalizationMode.SplitAdjusted;

        // Only trade on the top 10 most traded stocks since they have the most popularity to drive trends.
        AddUniverse(Universe.DollarVolume.Top(10));
    }

    public override void OnData(Slice slice)
    {
        foreach (var (symbol, bar) in slice.Bars)
        {
            // Trade the trend by EMA crossing.
            var ema = (Securities[symbol] as dynamic).ema;
            if (bar.Close > ema)
            {
                SetHoldings(symbol, 0.05m);
            }
            else
            {
                SetHoldings(symbol, -0.05m);
            }
        }
    }

    public override void OnSecuritiesChanged(SecurityChanges changes)
    {
        foreach (var removed in changes.RemovedSecurities)
        {
            // Liquidate the ones leaving the universe since we will not trade their EMA anymore.
            Liquidate(removed.Symbol);
            // Deregister the EMA indicator to free resources
            DeregisterIndicator((removed as dynamic).ema as ExponentialMovingAverage);
        }

        foreach (var added in changes.AddedSecurities)
        {
            var security = added as dynamic;
            // Create EMA indicator for trend trading signals.
            security.ema = EMA(added.Symbol, 50, Resolution.Daily);
            // Warm up the EMA indicator to ensure its readiness for immediate use.
            WarmUpIndicator(added.Symbol, (ExponentialMovingAverage)security.ema, Resolution.Daily);
        }
    }
}
class UniverseSettingsAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2021, 1, 1)
        self.set_end_date(2021, 2, 1)
        
        # To avoid over-updating the universe, which causes insufficient time to earn the trend, update the universe weekly.
        self.universe_settings.schedule.on(self.date_rules.week_start())
        self.universe_settings.minimum_time_in_universe = timedelta(7)
        # Rebalancing frequency is daily, so we only need to subscribe to daily resolution.
        self.universe_settings.resolution = Resolution.DAILY
        # To best simulate IB's margin requirement, set the leverage to 50%.
        self.universe_settings.leverage = 2
        # Since we trade by market order, we cannot use extended market hours data to fill.
        self.universe_settings.extended_market_hours = False
        # We want to trade the EMA with raw price but not altered by splits.
        self.universe_settings.data_normalization_mode = DataNormalizationMode.SPLIT_ADJUSTED

        # Only trade on the top 10 most traded stocks since they have the most popularity to drive trends.
        self.add_universe(self.universe.dollar_volume.top(10))

    def on_data(self, slice: Slice) -> None:
        for symbol, bar in slice.bars.items():
            # Trade the trend by EMA crossing.
            ema = self.securities[symbol].ema.current.value
            if bar.close > ema:
                self.set_holdings(symbol, 0.05)
            else:
                self.set_holdings(symbol, -0.05)

    def on_securities_changed(self, changes: SecurityChanges) -> None:
        for removed in changes.removed_securities:
            # Liquidate the ones leaving the universe since we will not trade their EMA anymore.
            self.liquidate(removed.symbol)
            # Deregister the EMA indicator to free resources
            self.deregister_indicator(removed.ema)

        for added in changes.added_securities:
            # Create EMA indicator for trend trading signals.
            added.ema = self.ema(added.symbol, 50, Resolution.DAILY)
            # Warm up the EMA indicator to ensure its readiness for immediate use.
            self.warm_up_indicator(added.symbol, added.ema, Resolution.DAILY)

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: