Contents
Algorithm Reference
Handling Data
Introduction
Requested data is passed into event handlers for you to use to make trading decisions. The primary event handler, Slice,
groups all data types together at a single moment in time in the
OnData(Slice data)
def OnData(self, slice):
handler. Slice is short
for "time slice" - representing a slice of time and values of the data at that time.
C# and F# also allow you to receive data with dedicated event handlers for each data type
e.g OnData(TradeBars data).Python only supports the Slice event handlers.
All data uses DataDictionary
objects to group data by symbol and provide easy access to information. The plural of
the type denotes the collection of objects (e.g., the TradeBars DataDictionary is made up of TradeBar objects; QuoteBars DataDictionary is made up of QuoteBar objects). You
can access individual data points in the dictionary through its string or symbol dictionary index. For example
var ibmTradeBar = slice.Bars["IBM"]
ibmTradeBar = slice.Bars["IBM"]
.
Time Slices
The Slice event handler combines all of the data into a single method. It represents the data at a point in
time.
The Slice object contains many helpers for accessing your data. The Slice objects arrive to the
OnData(Slice data)
def OnData(self, slice)
event
handler.
The Slice object gives you threetwo ways to access your data:
- Dynamic string/symbol indexer, which returns a dynamic object of your type slice["IBM"].
- Statically typed properties (slice.Bars[], slice.QuoteBars[]).
- Statically typed Get<T>() helper
Strongly typed access gives you compile-time safety, but dynamic types can sometimes simplify coding. We recommend static types as they are easier to debug.
Slice has the following internal structure:
class Slice : IEnumerable<KeyValuePair<Symbol, BaseData>> { TradeBars Bars; QuoteBars QuoteBars; Ticks Ticks; OptionChains OptionChains; FuturesChains FuturesChains; Splits Splits; Dividends Dividends; Delistings Delistings; SymbolChangedEvents SymbolChangedEvents; }
class Slice: TradeBars Bars; QuoteBars QuoteBars; Ticks Ticks; OptionChains OptionChains; FuturesChains FuturesChains; Splits Splits; Dividends Dividends; Delistings Delistings; SymbolChangedEvents SymbolChangedEvents;
It contains all the data for a given moment in time. TradeBars and QuoteBars are symbol/string indexed dictionaries
so you
can easily access the data. Ticks is a list of ticks for that moment of time, indexed by the symbol.
To make accessing the data easier the Slice object itself can also be indexed. E.g. slice["IBM"]
will
return a
TradeBar for IBM, and slice["EURUSD"]
will return a QuoteBar for EURUSD. TradeBars are supported for Equity,
Options, and Future asset types; QuoteBars are supported for Forex, CFD, and Future asset types.
Since the Slice object is indexed, it is possible to check if the time slice contains specific data. e.g.
slice.ContainsKey("EURUSD")
will return a boolean. Even if requesting data to be filled forward, you should check
if the data exists in the dictionary first. If there is little trading, or you are in the same time loop as when
you added the security, it may not have any data.
Other Event Handlers
In C#/F# data is also piped into dedicated event handlers for each data type. To use data this way, you
need to put an event handler in your algorithm that follows the pattern:
public void OnData(TradeBars data) {}
. LEAN automatically detects the method exists and sends data to it.
Python passes all data events into the def OnData(self, slice):
event handler. This is the preferred way to
access data for your strategy. This includes all the data you've requested for your algorithm, including custom data.
public void OnData(TradeBars data) { // TradeBars objects are piped into this method. } public void OnData(Ticks data) { // Ticks objects are piped into this method. }
Data Formats
There are seven financial data types: Tick, TradeBar, QuoteBar, Delisting, SymbolChangedEvent, Split, and Dividend. All data extends from BaseData, the core data class, which provides Symbol, Time, and Value properties.
Ticks
Ticks data provides LastPrice and Quantity properties for a given time. If it is a quote tick, it also contains non-zero BidPrice, BidSize, AskPrice, and AskSize properties. A Trade Tick is a record of a transaction or sale for the security. A Quote Tick is a bid or offer to purchase the security for a specific price. For equities, all of the ticks for given second are grouped together in backtesting. In live trading, ticks are streamed directly to your algorithm as soon as they occur. Data with millisecond resolution timestamps (Forex, CFD, and Futures) generally only have 1 tick in their list, but when multiple trades occur within a millisecond they may also be grouped together.
self.AddEquity("IBM", Resolution.Tick) ## Subscribe to tick-level IBM data def OnData(self, data): ## Use the [-1] indexer to access to most recent tick that arrived self.Debug(f"Last price: {data['IBM'][-1].LastPrice}") self.Debug(f"Last price: {data['IBM'][-1].Quantity}")
Tick data is raw and unfiltered. It may contain bad ticks which skew your trade results. We recommend only using tick data if you understand the risks and are able to perform your own online tick filtering. Ticks which QuantConnect believes are suspicious are marked with the boolean Suspicious
flag.
TradeBars
TradeBars are individual trades from the exchanges consolidated into price bars. The TradeBar provides Open, High, Low, Close, and Volume properties for a given period of time. TradeBars are only supported for Equity, Options, and Futures asset types (NOT Forex or CFD).

self.AddEquity("IBM", Resolution.Hour) ## Subscribe to hourly TradeBars def OnData(self, data): ## You can access the TradeBar dictionary in the slice object and then subset by symbol ## to get the TradeBar for IBM tradeBars = data.Bars ibmTradeBar = tradeBars['IBM'] ibmOpen = ibmTradeBar.Open ## Open price ibmClose = ibmTradeBar.Close ## Close price ## Or you can access the IBM TradeBar by directly subsetting the slice object ## (since you are subscribed to IBM equity data, this will return a TradeBar rather than a QuoteBar) ibmOpen = data['IBM'].Open ## Open price imbClose = data['IBM'].Close ## Close price
QuoteBars
QuoteBars are built by consolidating the bid and ask ticks from the exchanges into bars. The QuoteBar provides Open, High, Low, Close, Bid, Ask, LastBidSize, and LastAskSize properties for a given period of time. The Bid and the Ask properties are Bar objects that contain Open, High, Low, and Close. The QuoteBar Open, High, Low, and Close properties values are the mean of the respective Bid and Ask properties. QuoteBars are supported for all asset types.

self.AddForex('EURUSD', Resolution.Hour) # Subscribe to hourly QuoteBars in Initialize(self) def OnData(self, data): ## You can access the EURUSD QuoteBar directly by subsetting the slice object fxOpen = data['EURUSD'].Open ## Market Open FX Rate fxClose = data['EURUSD'].Close ## Market Close FX Rate ## If you are subscribed to more than one Forex or Futures data stream then you can ## access the QuoteBar dictionary and then subset this for your desired Forex symbol fxQuoteBars = data.QuoteBars eurusdQuoteBar = fxQuoteBars['EURUSD'] ## EURUSD QuoteBar fxOpen = eurusdQuoteBar.Open ## Market Open FX Rate fxClose = eurusdQuoteBar.Close ## Market Close FX Rate
With a specific QuoteBar, you can also access Bid and Ask Bars for the same security. These Bars provide information specific to the Bid and Ask side of Forex and Future asset types, while the QuoteBar.Open, High, Low, and Close properties are the midpoint of the Bid-Ask spread at that moment of time. These QuoteBar.Bid and QuoteBar.Ask bars have Open, High, Low, and close properties (e.g., QuoteBar.Bid.Open
).
self.AddForex('EURUSD', Resolution.Hour) # Subscribe to hourly QuoteBars in Initialize(self) def OnData(self, data): quoteBar = data['EURUSD'] ## EURUSD QuoteBar self.Log(f"Mid-point open price: {quoteBar.Open}") bidBar = quoteBar.Bid ## EURUSD Bid Bar askBar = quoteBar.Ask ## EURUSD Ask Bar self.Log(f"Bid open price: {bidBar.Open}") self.Log(f"Ask open price: {askBar.Open}")
Dividends
Dividend events are triggered on payment of a dividend. It provides the Distribution per share.
def Initialize(self): self.SetStartDate(2017, 6, 1) self.SetEndDate(2017, 6, 28) self.spy = self.AddEquity("SPY", Resolution.Hour) def OnData(self, data): if not self.Portfolio.Invested: self.Buy("SPY", 100) ## Condition to see if SPY is in the Dividend DataDictionary if data.Dividends.ContainsKey("SPY"): ## Log the dividend distribution self.Log(f"SPY paid a dividend of {data.Dividends['SPY'].Distribution}")
Splits
Split events are triggered on a share split or reverse split event. It provides a SplitFactor and ReferencePrice.
def Initialize(self): self.SetStartDate(2003, 2, 1) self.SetEndDate(2003, 2, 28) self.SetCash(100000) self.msft = self.AddEquity("MSFT", Resolution.Daily) self.msft.SetDataNormalizationMode(DataNormalizationMode.Raw) def OnData(self, data): if not self.Portfolio.Invested: self.Buy("MSFT", 100) ## If MSFT had a split, print out information about it if data.Splits.ContainsKey("MSFT"): ## Log split information spySplit = data.Splits['MSFT'] if spySplit.Type == 0: self.Log('MSFT stock will split next trading day') if spySplit.Type == 1: self.Log("Split type: {0}, Split factor: {1}, Reference price: {2}".format(spySplit.Type, spySplit.SplitFactor, spySplit.ReferencePrice))
SymbolChangedEvent
SymbolChangedEvents provides notice of new ticker names for stocks, or mergers of two tickers into one. It provides the OldSymbol and NewSymbol tickers.
def Initialize(self): self.SetStartDate(2014, 4, 1) self.SetEndDate(2014, 4, 3) self.SetCash(100000) self.goog = self.AddEquity("GOOG", Resolution.Daily) def OnData(self, data): self.MarketOrder('GOOG', 10) ## Log old and new symbol if 'GOOG' symbol has changed if data.SymbolChangedEvents.ContainsKey('GOOG'): self.Log("Old symbol: {0}, New symbol: {1}".format(data.SymbolChangedEvents['GOOG'].OldSymbol,data.SymbolChangedEvents['GOOG'].NewSymbol))
Delistings
Delisting events provide notice that an asset is no longer trading on the exchange. A delisting warning is issued on the final trading day for a stock delisting event to give your algorithm time to gracefully exit out of positions before forced termination.
def Initialize(self): self.SetStartDate(2007, 5, 16) self.SetEndDate(2007, 5, 25) self.SetCash(100000); equity = self.AddEquity("AAA", Resolution.Daily) def OnData(self, data): self.MarketOrder('AAA', 10) ## Print delisting warnings and noritifications if data.Delistings.ContainsKey('AAA'): delisting = data.Delistings['AAA'] ## Log the delisting warning type self.Log(delisting.ToString()) if delisting.Type == 0: self.Log('AAA will be delisted EOD') if delisting.Type == 1: self.Log('AAA delisted')