Securities

Handling Data

Introduction

If you create a data subscription, your algorithm receives data updates for that security or custom data source.

Get Prices

LEAN uses data updates to set the current prices of a security and compute the contribution of securities you hold to the portfolio value. To get the current prices of a security, find the Security object in the Securitiessecurities dictionary and access the price attributes.

// Use the Securities object as a dictionary to get the current ask and bid price of the SPY.
var security = Securities["SPY"];
var price = security.Price;
var bidPrice = security.BidPrice;
var askPrice = security.AskPrice;
# Use the securities object as a dictionary to get the current ask and bid price of the SPY.
security = self.securities["SPY"]
price = security.price
bid_price = security.bid_price
ask_price = security.ask_price

Data Events

The Slice that LEAN passes to the OnDataon_data method represents all of the data for your subscriptions at a single point in time. The Slice object contains data like Tick objects, TradeBar objects, QuoteBar objects, corporate actions, and chains for Option and Future contracts. You can use the data in the Slice to make trading decisions.

To access data in the Slice, index it with the security Symbol. If you use the security ticker instead of the Symbol, LEAN automatically finds the Symbol.

// Use the OnData method to get the data for a symbol in the current time slice.
public override void OnData(Slice slice)
{
    if (slice.ContainsKey(_symbol))
    {
        var myData = slice[_symbol];
    }
}
# Use the OnData method to get the data for a symbol in the current time slice.
def on_data(self, slice: Slice) -> None:
    if slice.contains_key(self._symbol):
        my_data = slice[self._symbol]

The following table shows the Slice property to index based on the data format you want:

Data FormatSlice Property
TradeBarBarsbars
QuoteBarQuoteBarsquote_bars
TickTicksticks
// Get the tradebar from the slice.
public override void OnData(Slice slice)
{
    if (slice.ContainsKey(_symbol))
    {
        var bar = slice.Bars[_symbol];
    }
}
# Get the tradebar from the slice.
def on_data(self, slice: Slice) -> None:
    if slice.contains_key(self._symbol):
        bar = slice.bars[self._symbol]

If you just index the Slice instead of the preceding properties, it returns the correct object. For instance, if your data subscription provides QuoteBar objects and you index the Slice with the security Symbol, it returns the QuoteBar.

For more information about the Slice class, see Timeslices.

Cache

To get the most recent data for a security, call the GetLastDataget_last_data method on the Security object.

// Get the most recent data for a security.
var data = Securities["SPY"].GetLastData();
# Get the most recent data for a security.
data = self.securities["SPY"].get_last_data()

The Cachecache property of a Security object provides additional price information since you can access TradeBar, QuoteBar, and Tick data.

// Get additional price information for the security.
var cache = Securities["SPY"].Cache;
var tradeBar = cache.GetData<TradeBar>();
var quoteBar = cache.GetData<QuoteBar>();
var ticks = cache.GetAll<Tick>();
# Get additional price information for the security
cache = self.securities["SPY"].cache
trade_bar = cache.get_data[TradeBar]()
quote_bar = cache.get_data[QuoteBar]()
ticks = cache.get_all[Tick]()

Examples

The following examples demonstrate some common practices for handling data.

Example 1: Use QuoteBar Data

To increase the accuracy of indicator values for illiquid assets, update the indicator with the mid-price of a quote bar.

private Symbol _symbol;
// Initialize a new instance of a SimpleMovingAverage object
private SimpleMovingAverage _indicator = new(20);

public override void Initialize()
{
    _symbol = AddEquity("SPY").Symbol;
}

public override void OnData(Slice slice)
{
    // Check if the QuoteBars received contain SPY quote data
    if (slice.QuoteBars.ContainsKey(_symbol))
    {
        var quoteBar = slice.QuoteBars[_symbol];
        // Calculate the mid price by averaging the bid and ask price
        var midPrice = (quoteBar.Bid.Close + quoteBar.Ask.Close) * 0.5m;
        // Update the SMA indicator with the mid price
        _indicator.Update(quoteBar.EndTime, midPrice);
    }
}
def initialize(self) -> None:
    self._symbol = self.add_equity("SPY").symbol
    self._indicator = SimpleMovingAverage(20)

def on_data(self, slice: Slice) -> None:
    # Check if the QuoteBars received contain SPY quote data
    if slice.quote_bars.contains_key(self._symbol):
        quote_bar = slice.quote_bars[self._symbol]
        # Calculate the mid price by averaging the bid and ask price
        mid_price = (quote_bar.bid.close + quote_bar.ask.close) * 0.5
        # Update the SMA indicator with the mid price
        self._indicator.update(quote_bar.end_time, mid_price)

Example 2: Use Tick Data

To obtain the instant bid and ask size of the latest tick, use tick data.

private Symbol _symbol;
// Set up variables to save the bid and ask sizes.
private decimal _bidSize = 0m;
private decimal _askSize = 0m;

public override void Initialize()
{
    _symbol = AddEquity("SPY", Resolution.Tick).Symbol;
}

public override void OnData(Slice slice)
{
    // Check if the Ticks received contain SPY tick data
    if (slice.Ticks.ContainsKey(_symbol))
    {
        // Reset the bid and ask size.
        _bidSize = 0;
        _askSize = 0;

        var ticks = slice.Ticks[_symbol];
        
        // Iterate all related ticks to calculate the bid and ask size.
        // Make sure the tick data is a quote to obtain either bid and ask size.
        foreach (var tick in ticks.Where(tick => tick.TickType == TickType.Quote))
        {
            // Update the bid or ask size.
            _bidSize += tick.BidSize;
            _askSize += tick.AskSize;
        }
    }
}
def initialize(self) -> None:
    self._symbol = self.add_equity("SPY", Resolution.TICK).symbol
    # Set up variables to save the bid and ask price.
    self._bid_size = 0
    self._ask_size = 0

def on_data(self, slice: Slice) -> None:
    # Check if the Ticks received contain SPY tick data.
    if slice.ticks.contains_key(self._symbol):
        # Reset the bid and ask size
        self._bid_size = 0
        self._ask_size = 0

        ticks = slice.ticks[self._symbol]

        # Iterate all related ticks to calculate the bid and ask size.
        for tick in ticks:
            # Make sure the tick data is a quote to obtain either bid and ask size.
            if tick.tick_type == TickType.QUOTE:
                # Update the bid or ask size.
                self._bid_size += tick.bid_size
                self._ask_size += tick.ask_size

Example 3: Fundamental Cache

To get the fundamentals of an Equity, use its Fundamental data cache.

public override void OnData(Slice slice)
{
    // Iterate active security objects.
    foreach (var security in ActiveSecurities.Values)
    {
        // Get the Fundamental cache.
        var fundamental = security.Fundamentals;
        // Get the sector code.
        var sectorCode = fundamental.AssetClassification.MorningstarSectorCode;
    }
}
def on_data(self, slice: Slice) -> None:
    # Iterate active security objects.
    for security in self.active_securities.values():
        # Get the Fundamental cache.
        fundamental = security.fundamentals
        # Get the sector code.
        sector_code = fundamental.asset_classification.morningstar_sector_code

Example 4: Access Option Greeks

To get properties of an Option contract, use the OptionChainsoption_chains property of the Slice.

private Symbol _symbol;

public override void Initialize()
{
    // Subscribe to the Option data.
    var option = AddOption("SPY");
    // Set the Option universe filter.
    option.SetFilter(x => x.IncludeWeeklys().Strikes(-5, 5).Expiration(0, 60));
    // Save a reference of the canonical symbol.
    _symbol = option.Symbol;
}

public override void OnData(Slice slice)
{
    // Try to get the Option contracts within the Option chain.
    if (slice.OptionChains.TryGetValue(_symbol, out var chain))
    {
        foreach (var contract in chain)
        {
            // Get the implied volatility and greeks of each Option contract.
            var iv = contract.ImpliedVolatility;
            var greeks = contract.Greeks;
            var delta = greeks.Delta;
            var gamma = greeks.Gamma;
            var vega = greeks.Vega;
            var theta = greeks.Theta;
            var rho = greeks.Rho;
        }
    }
}
def initialize(self) -> None:
    # Subscribe to the Option data.
    option = self.add_option("SPY")
    # Set the Option universe filter.
    option.set_filter(lambda x: x.include_weeklys().strikes(-5, 5).expiration(0, 60))
    # Save a reference of the canonical symbol.
    self._symbol = option.symbol

def on_data(self, slice: Slice) -> None:
    # Try to get the Option contracts within the Option chain.
    chain = slice.option_chains.get(self._symbol)
    if chain:
        for contract in chain:
            # Get the implied volatility and greeks of each Option contract.
            iv = contract.implied_volatility
            greeks = contract.greeks
            delta = greeks.delta
            gamma = greeks.gamma
            vega = greeks.vega
            theta = greeks.theta
            rho = greeks.rho

Example 5: Get Asset Sentiment Values

The following example demonstrates how to get sentiment values from the Brain Sentiment Indicator:

private Symbol _dataset7DaySymbol;

public override void Initialize()
{
    var aapl = AddEquity("AAPL", Resolution.Daily).Symbol;
    // Subscribe to 7-day sentiment data.
    _dataset7DaySymbol = AddData<BrainSentimentIndicator7Day>(aapl).Symbol;
}

public override void OnData(Slice slice)
{
    // Check if the current slice contains the 7-day sentiment data.
    if (slice.ContainsKey(_dataset7DaySymbol))
    {
        var dataPoint = slice[_dataset7DaySymbol];
        // Log the sentiment value.
        Log($"{_dataset7DaySymbol} sentiment at {slice.Time}: {dataPoint.Sentiment}");
    }
}
def initialize(self) -> None:
    aapl = self.add_equity("AAPL", Resolution.DAILY).symbol
    # Subscribe to 7-day sentiment data.
    self.dataset_7day_symbol = self.add_data(BrainSentimentIndicator7Day, aapl).symbol

def on_data(self, slice: Slice) -> None:
    # Check if the current slice contains the 7-day sentiment data.
    if slice.contains_key(self.dataset_7day_symbol):
        data_point = slice[self.dataset_7day_symbol]
        # Log the sentiment value.
        self.log(f"{self.dataset_7day_symbol} sentiment at {slice.time}: {data_point.sentiment}")

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: