# Writing Algorithms

## Initialization

### Introduction

The Initializeinitialize method is the entry point of your algorithm where you define a series of settings, including security subscriptions, starting cash balances, and warm-up periods. LEAN only calls the Initializeinitialize method one time, at the start of your algorithm.

### Set Dates

To set the date range of backtests, call the SetStartDateset_start_date and SetEndDateset_end_date methods. The dates you provide are based in the algorithm time zone. By default, the end date is yesterday, one millisecond before midnight. In live trading, LEAN ignores the start and end dates.

SetStartDate(2013, 1, 5);                  // Set start date to January 5, 2013
SetEndDate(2015, 1, 5);                    // Set end date to January 5, 2015
SetEndDate(DateTime.Now.Date.AddDays(-7)); // Set end date to last week

self.set_start_date(2013, 1, 5)                  # Set start date to January 5, 2013
self.set_end_date(2015, 1, 5)                    # Set end date to January 5, 2015
self.set_end_date(datetime.now() - timedelta(7)) # Set end date to last week


The algorithm equity curve, benchmark, and performance statistics are denominated in the account currency. To set the account currency and your starting cash, call the SetAccountCurrencyset_account_currency method. By default, the account currency is USD and your starting cash is $100,000. If you call the SetAccountCurrencyset_account_currency method, you must call it before you call the SetCashset_cash method or add data. If you call the SetAccountCurrencyset_account_currency method more than once, only the first call takes effect. SetAccountCurrency("BTC"); // Set account currency to Bitcoin and its quantity to 100,000 BTC SetAccountCurrency("INR"); // Set account currency to Indian Rupees and its quantity to 100,000 INR SetAccountCurrency("BTC", 10); // Set account currency to Bitcoin and its quantity to 10 BTC  self.set_account_currency("BTC") # Set account currency to Bitcoin and its quantity to 100,000 BTC self.set_account_currency("INR") # Set account currency to Indian Rupees and its quantity to 100,000 INR self.set_account_currency("BTC", 10); // Set account currency to Bitcoin and its quantity to 10 BTC ### Set Cash To set your starting cash in backtests, call the SetCashset_cash method. By default, your starting cash is$100,000 USD. In live trading, LEAN ignores the SetCashset_cash method and uses the cash balances in your brokerage account instead.

SetCash(100000);       // Set the quantity of the account currency to 100,000
SetCash("BTC", 10);    // Set the Bitcoin quantity to 10
SetCash("EUR", 10000); // Set the EUR quantity to 10,000
self.set_cash(100000)       # Set the quantity of the account currency to 100,000
self.set_cash("BTC", 10)    # Set the Bitcoin quantity to 10
self.set_cash("EUR", 10000) # Set the EUR quantity to 10,000


### Set Brokerage and Cash Model

We model your algorithm with margin modeling by default, but you can select a cash account type. Cash accounts don't allow leveraged trading, whereas Margin accounts can support leverage on your account value. To set your brokerage and account type, call the SetBrokerageModelset_brokerage_model method. For more information about each brokerage and the account types they support, see the brokerage integration documentation. For more information about the reality models that the brokerage models set, see Supported Models.

SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);
self.set_brokerage_model(BrokerageName.INTERACTIVE_BROKERS_BROKERAGE, AccountType.CASH)

The AccountType enumeration has the following members:

### Set 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: Asynchronousasynchronous

Should the universe selection run asynchronously to boost speed?

Data Type: bool | Default Value: falseFalse

#### Property: ExtendedMarketHoursextended_market_hours

Should assets also feed extended market hours? 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.

Data Type: bool | Default Value: falseFalse

#### Property: FillForwardfill_forward

Should asset data fill forward?

Data Type: bool | Default Value: trueTrue

#### Property: MinimumTimeInUniverseminimum_time_in_universe

What's the minimum time assets should be in the universe?

Data Type: TimeSpantimedelta | Default Value: TimeSpan.FromDays(1)timedelta(1)

#### Property: Resolutionresolution

What resolution should assets use?

Data Type: Resolution | Default Value: Resolution.MinuteResolution.MINUTE

#### Property: ContractDepthOffsetcontract_depth_offset

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.

Data Type: int | Default Value: 0

#### Property: DataMappingModedata_mapping_mode

How should continuous Future contracts be mapped? This setting is only available for Future assets.

Data Type: DataMappingMode | Default Value: DataMappingMode.OpenInterest

#### Property: DataNormalizationModedata_normalization_mode

How should historical prices be adjusted? This setting is only available for Equity and Futures assets.

Data Type: DataNormalizationMode | Default Value: DataNormalizationMode.AdjustedDataNormalizationMode.ADJUSTED

#### Property: Leverageleverage

What leverage should assets use in the universe? This setting is not available for derivative assets.

Data Type: decimalfloat | Default Value: Security.NullLeverageSecurity.NULL_LEVERAGE

To set the UniverseSettingsuniverse_settings, update the preceding properties in the Initializeinitialize method before you add the universe. These settings are globals, so they apply to all universes you create.

// Request second resolution data. This will be slow!
UniverseSettings.Resolution = Resolution.Second;
AddUniverse(Universe.DollarVolume.Top(50));
# Request second resolution data. This will be slow!
self.universe_settings.resolution = Resolution.SECOND
self.add_universe(self.universe.dollar_volume.top(50))

### Set Security Initializer

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.

//In Initialize
SetSecurityInitializer(CustomSecurityInitializer);

private void CustomSecurityInitializer(Security security)
{
security.SetFeeModel(new ConstantFeeModel(0, "USD"));
}

#In Initialize
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.

SetSecurityInitializer(security => security.SetFeeModel(new ConstantFeeModel(0, "USD")));
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.

var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
SetSecurityInitializer(security => seeder.SeedSecurity(security));
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.

// 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.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))


You can subscribe to asset, fundamental, alternative, and custom data. The Dataset Market provides 400TB of data that you can easily import into your algorithms.

#### Asset Data

To subscribe to asset data, call one of the asset subscription methods like AddEquityadd_equity or AddForexadd_forex. Each asset class has its own method to create subscriptions. For more information about how to create subscriptions for each asset class, see Asset Classes.

AddEquity("AAPL"); // Add Apple 1 minute bars (minute by default)

self.add_equity("SPY")  # Add Apple 1 minute bars (minute by default)


In live trading, you define the securities you want, but LEAN also gets the securities in your live portfolio and sets their resolution to the lowest resolution of the subscriptions you made. For example, if you create subscriptions in your algorithm for securities with Second, Minute, and Hour resolutions, the assets in your live portfolio are given a resolution of Second.

#### Alternative Data

To add alternative datasets to your algorithms, call the AddDataadd_data method. For full examples, in the Datasets chapter, select a dataset and see the Requesting Data section.

#### Custom Data

To add custom data to your algorithms, call the AddDataadd_data method. For more information about custom data, see Importing Data.

#### Limitations

There is no official limit to how much data you can add to your algorithms, but there are practical resource limitations. Each security subscription requires about 5MB of RAM, so larger machines let you run algorithms with bigger universes. For more information about our cloud nodes, see Resources.

### Set Indicators and Consolidators

You can create and warm-up indicators in the Initializeinitialize method.

private Symbol _symbol;
private SimpleMovingAverage _sma;

_sma = SMA(_symbol, 20);
WarmUpIndicator(_symbol, _sma);
self._symbol = self.add_equity("SPY").symbol
self._sma = self.sma(self._symbol, 20)
self.warm_up_indicator(self._symbol, self._sma)

### Set Algorithm Settings

The following table describes the AlgorithmSettings properties:

#### Property: FreePortfolioValuefree_portfolio_value

Data Type: decimalfloat | Default Value: 250m

#### Property: FreePortfolioValuePercentagefree_portfolio_value_percentage

The buying power buffer percentage value.

Data Type: decimalfloat | Default Value: 0.0025m

#### Property: LiquidateEnabledliquidate_enabled

A flag to enable and disable the Liquidateliquidate method.

Data Type: bool | Default Value: trueTrue

#### Property: MaxAbsolutePortfolioTargetPercentagemax_absolute_portfolio_target_percentage

The absolute maximum valid total portfolio value target percentage.

Data Type: decimalfloat | Default Value: 1000000000m

#### Property: MinAbsolutePortfolioTargetPercentagemin_absolute_portfolio_target_percentage

The absolute minimum valid total portfolio value target percentage.

Data Type: decimalfloat | Default Value: 0.0000000001m

#### Property: MinimumOrderMarginPortfolioPercentageminimum_order_margin_portfolio_percentage

The minimum order margin portfolio percentage to ignore bad orders and orders with small sizes.

Data Type: decimalfloat | Default Value: 0.001m

#### Property: RebalancePortfolioOnInsightChangesrebalance_portfolio_on_insight_changes

Rebalance the portfolio when you emit new insights or when insights expire.

Data Type: bool/NoneType | Default Value: trueTrue

#### Property: RebalancePortfolioOnSecurityChangesrebalance_portfolio_on_security_changes

Rebalance the portfolio when your universe changes.

Data Type: bool/NoneType | Default Value: trueTrue

#### Property: StalePriceTimeSpanstale_price_time_span

The minimum time span elapsed to consider a market fill price as stale

Data Type: TimeSpantimedelta | Default Value: TimeSpan.FromHours(1)timedelta(hours=1)

#### Property: TradingDaysPerYeartrading_days_per_year

Number of trading days per year for this algorithm's portfolio statistics.

Data Type: integerint | Default Value: 252

#### Property: WarmUpResolutionwarm_up_resolution

The resolution to use during the warm-up period

Data Type: Resolution/NoneType | Default Value: nullNone

To change the Settingssettings, update some of the preceding properties.

Settings.RebalancePortfolioOnSecurityChanges = false;
Settings.TradingDaysPerYear = 365;
self.settings.rebalance_portfolio_on_security_changes = False
self.settings.trading_days_per_year = 365

To successfully update the FreePortfolioValuefree_portfolio_value, you must update it after the Initializeinitialize method.

### Set Benchmark

The benchmark performance is input to calculate several statistics on your algorithm, including alpha and beta. To set a benchmark for your algorithm, call the SetBenchmarkset_benchmark method. You can set the benchmark to a security, a constant value, or a value from a custom data source. If you don't set a brokerage model, the default benchmark is SPY. If you set a brokerage model, the model defines the default benchmark.

// Set the benchmark to IBM
SetBenchmark("IBM");

// Set the benchmark to a constant value of 0
SetBenchmark(x => 0);

// Set the benchmark to a value from a custom data source
SetBenchmark(symbol);
# Set the benchmark to IBM
self.set_benchmark("IBM")

# Set the benchmark to a constant value of 0
self.set_benchmark(lambda x: 0)

# Set the benchmark to a value from a custom data source
self.set_benchmark(symbol)

If you pass a ticker to the SetBenchmarkset_benchmark method, LEAN checks if you have a subscription for it. If you have a subscription for it, LEAN uses the security subscription. If you don't have a subscription for it, LEAN creates a US Equity subscription with the ticker. Since the ticker you pass may not reference a US Equity, we recommend you subscribe to the benchmark security before you call the SetBenchmarkset_benchmark method.

### Set Time Zone

LEAN supports international trading across multiple time zones and markets, so it needs a reference time zone for the algorithm to set the Timetime. The default time zone is Eastern Time (ET), which is UTC-4 in summer and UTC-5 in winter. To set a different time zone, call the SetTimeZoneset_time_zone method. This method accepts either a string following the IANA Time Zone database convention or a NodaTime.DateTimeZone object. If you pass a string, the method converts it to a NodaTime.DateTimeZone object. The TimeZones class provides the following helper attributes to create NodaTime.DateTimeZone objects:

SetTimeZone("Europe/London");
SetTimeZone(NodaTime.DateTimeZone.Utc);
SetTimeZone(TimeZones.Chicago);

self.set_time_zone("Europe/London")
self.set_time_zone(TimeZones.CHICAGO)


The algorithm time zone may be different from the data time zone. If the time zones are different, it might appear like there is a lag between the algorithm time and the first bar of a history request, but this is just the difference in time zone. All the data is internally synchronized in Coordinated Universal Time (UTC) and arrives in the same Slice object. A slice is a sliver of time with all the data available for this moment.

To keep trades easy to compare between asset classes, we mark all orders in UTC time.

### Set Warm Up Period

You may need some historical data at the start of your algorithm to prime technical indicators or populate historical data arrays. The warm-up period pumps data into your algorithm from before the start date. To set a warm-up period, call the SetWarmUpset_warm_up method. The warm-up feature uses the subscriptions you add in Initializeinitialize to gather the historical data that warms up the algorithm. If you don't create security subscriptions in the Initializeinitialize method, the warm-up won't occur.

// Wind time back 7 days from the start date
SetWarmUp(TimeSpan.FromDays(7));

// Feed in 100 trading days worth of data before the start date
SetWarmUp(100, Resolution.Daily);

// If you don't provide a resolution argument, it uses the lowest resolution in your subscriptions
SetWarmUp(100);

# Wind time back 7 days from the start date
self.set_warm_up(timedelta(7))

# Feed in 100 trading days worth of data before the start date
self.set_warm_up(100, Resolution.DAILY)

# If you don't provide a resolution argument, it uses the lowest resolution in your subscriptions
self.set_warm_up(100)


### Set Name and Tags

You can categorize your backtest with a name and tags. To set the algorithm Namename, call the SetNameset_name method.

SetName("Backtest Name");
self.set_name("Backtest Name")

The SetNameset_name method overwrites the names of backtests of an optimization, which contains the parameter values. To keep these values, create a name that includes them.

var fastPeriod = GetParameter("fast_period", 100);
var midPeriod = GetParameter("mid_period", 200);
var slowPeriod = GetParameter("slow_period", 300);
SetName(\$"Backtest Name ({fastPeriod},{midPeriod},{slowPeriod})");
fast_period = self.get_parameter("fast_period", 100);
mid_period = self.get_parameter("mid_period", 200);
slow_period = self.get_parameter("slow_period", 300);
self.set_name(f"Backtest Name ({fast_period},{mid_period},{slow_period})");

To add tags to you algorithm, call the AddTagadd_tag method.

AddTag("Long Only");

self.add_tag("Long Only")


Your algorithm can add 20 tags. The name and each tag can have up to 200 characters or else they are truncated.

### Post Initialization

After the Initializeinitialize method, the PostInitializepost_initialize method performs post-initialization routines, so don't override it. To be notified when the algorithm is ready to begin trading, define an OnWarmupFinishedon_warmup_finished method. This method executes even if you don't set a warm-up period.

public override void OnWarmupFinished()
{
}
def on_warmup_finished(self) -> None:
self.log("Algorithm Ready")