---
title: "Handling Data"
description: "Your algorithm uses the data to make trading decisions and LEAN uses the data to update your positions, track your portfolio value, and simulate orders."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/securities/handling-data
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/securities/handling-data.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/03%20Securities/03%20Handling%20Data
modified: 2026-10-29
index: https://www.quantconnect.com/llms.txt
---

# Handling Data

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Securities > Handling Data

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

If you create a data subscription, your algorithm receives data updates for that security or [custom data source](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/key-concepts.md).

## 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 `securities` dictionary and access the price attributes.

```python
# 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 `on_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](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/us-equity/corporate-actions.md), and chains for [Option](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/handling-data.md#04-Option-Chains) and [Future](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/handling-data.md#05-Futures-Chains) 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`.

```python
# 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 Format | Slice Property |
| --- | --- |
| `TradeBar` | `bars` |
| `QuoteBar` | `quote_bars` |
| `Tick` | `ticks` |

```python
# 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](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md).

## Cache

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

```python
# Get the most recent data for a security.
data = self.securities["SPY"].get_last_data()
```

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

```python
# 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]()
```

## Market Session

The `Session` property of a `Security` object contains the open, high, low, close, volume, and open interest of trading sessions. The `Session` object is a `RollingWindow` object with size of zero by default. To enable market session tracking, set the size of the `Session` object to 2, so the previous session data is at index 1.

```python
session = self.securities[self._symbol].session
session.size = 2
today_open = session.open
today_high = session.high
today_low = session.low
today_cumulative_volume = session.volume
if session.is_ready:
    yesterday_close = session[1].close
```

Increase the size of the `Session` object to store more session data. You can use cached data in the `Session` property instead of requesting [historical daily data](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/history-requests.md).

```python
equity = self.add_equity("SPY")
# Increase the session lookback to 252 from default (0)
equity.session.size = 252
# Get all closing prices in the session history
closes = [x.close for x in session][::-1]
```

For more information about rolling windows, see [Rolling Window](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/rolling-window.md).

## Examples

The following examples demonstrate some common practices for handling data.

### Example 1: Get QuoteBar Data

The following algorithm updates an [indicator](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/key-concepts.md) with the mid-price of a quote bar to increase the accuracy of the indicator values for illiquid assets. Then, make use of the SMA indicator to trade the SMA cross strategy.

```python
class HandlingSecuritiesDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)

        self._symbol = self.add_equity("SPY").symbol
        self._indicator = SimpleMovingAverage(250)

        self.set_warm_up(timedelta(350))

    def on_data(self, slice: Slice) -> None:
        # Check if the QuoteBars contain SPY quote data.
        if self._symbol not in slice.quote_bars:
            return
        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)

        # Wait for the algorithm and indicator to be warmed up.
        if self.is_warming_up or not self._indicator.is_ready:
            return
        # Trade SMA cross strategy.
        weight = -0.5 if self._indicator.current.value > mid_price else 0.5
        self.set_holdings(self._symbol, weight)
```

### Example 2: Get Tick Data

The following algorithm calculates the bid and ask sizes of the latest SPY quote ticks and then trades at the top of each hour. During each rebalance, it buys SPY if bid size is greater than ask size since supply is greater than demand in this case. If bid size is smaller than ask size, it sells SPY since demand is greater than supply in this case.

```python
class BidAskSizeTickAlgorithm(QCAlgorithm):
    # Set up variables to save the bid and ask sizes.
    _bid_size = 0
    _ask_size = 0
    _hour = -1

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 9, 10)
        # Seed the price of each asset with its last known price to
        # avoid trading errors.
        self.settings.seed_initial_prices = True
        self._symbol = self.add_equity('SPY', Resolution.TICK).symbol

    def on_data(self, slice: Slice) -> None:
        # Check if the Slice contain SPY tick data.
        ticks = slice.ticks.get(self._symbol)
        if ticks:
            # Iterate all the ticks to calculate the bid and ask sizes.
            for tick in ticks:
                # Make sure the tick data is a quote instead of a trade.
                if tick.tick_type == TickType.QUOTE:
                    # Update the bid and ask sizes.
                    self._bid_size += tick.bid_size
                    self._ask_size += tick.ask_size
        # Trade at the top of each hour.
        if slice.time.hour != self._hour:
            # Invest based on supply-demand relationship from all ticks.
            # If bid size is above ask size, supply is greater than
            # demand, which drives the price up. Otherwise, supply is
            # lower than demand, which drives the price down.
            self.set_holdings(
                self._symbol, 0.5 if self._bid_size > self._ask_size else -0.5
            )
            # Reset the bid and ask size variables.
            self._bid_size = 0
            self._ask_size = 0
            self._hour = slice.time.hour
```

### Example 3: Get US Equity Fundamental Data

The following algorithm gets the latest [fundamental data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/us-equity/corporate-fundamentals.md) of all the US Equities in the algorithm. We invest in the stocks with the highest PE Ratio equally to ride on the popularity.

```python
class HandlingSecuritiesDataAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)

        # Request data for a selected list of equities for trading.
        for ticker in ["AAPL", "MSFT", "TSLA", "GOOG", "AMZN"]:
            self.add_equity(ticker)

    def on_data(self, slice: Slice) -> None:
        pe_ratios = {}

        # Iterate active security objects.
        for kvp in self.active_securities:
            symbol = kvp.key
            security = kvp.value

            # Get the Fundamental cache.
            fundamental = security.fundamentals
            # Get the sector code.
            sector_code = fundamental.asset_classification.morningstar_sector_code

            pe_ratios[symbol] = fundamental.valuation_ratios.pe_ratio

        # Sort by PE ratio to get the most popular stocks.
        sorted_by_pe_ratio = sorted(pe_ratios.items(), key=lambda x: x[1])
        targets = [PortfolioTarget(x[0], 1/3) for x in sorted_by_pe_ratio[-3:]]
        targets.extend([PortfolioTarget(x[0], 0) for x in sorted_by_pe_ratio[:2]])
        # Invest equally in the highest PE Ratio stocks for evenly dissipate capital risk.
        self.set_holdings(targets)
```

### Example 4: Get Option Greeks

The following algorithm gets SPY [Option Greek](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/greeks-and-implied-volatility/key-concepts.md) values. Sell a straddle with the ATM options, selected by Option Delta (closest to 0.5).

```python
class HandlingSecuritiesDataAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)

        # Add an SPY Option universe.
        option = self.add_option("SPY")
        # Set the Option universe filter.
        option.set_filter(lambda x: x.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 not self.portfolio.invested and 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

            # Invest in a straddle strategy to capitalize the volatility
            # Trade the ATM options with the closest expiry after 7 days.
            expiry = min(x.expiry for x in chain)
            selected = sorted([x for x in chain if x.expiry == expiry],
                key=lambda x: abs(x.greeks.delta - 0.5))[0]
            option_strategy = OptionStrategies.straddle(selected.symbol.canonical, selected.strike, selected.expiry)
            self.sell(option_strategy, 1)
```

### Example 5: Get Asset Sentiment Values

The following example gets sentiment values from the [Brain Sentiment Indicator](https://www.quantconnect.com/datasets/brain-sentiment-indicator) dataset. It simply buys AAPL when the sentiment is positive and liquidates the position when the sentiment is negative.

```python
class HandlingSecuritiesDataAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        # Seed the price of AAPL with its last known price to avoid trading errors.
        self.settings.seed_initial_prices = True
        # Add the 7-day sentiment data for AAPL.
        self._symbol = self.add_equity("AAPL", Resolution.DAILY).symbol
        self._dataset_7day_symbol = self.add_data(BrainSentimentIndicator7Day, self._symbol).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}")

            # Invest if the sentiment score is above 0, which indicates positive sentiment.
            if data_point.sentiment > 0:
                self.market_order(self._symbol, 1)
            # Liquidate otherwise.
            elif data_point.sentiment < 0 and self.portfolio[self._symbol].invested:
                self.liquidate(self._symbol)
```

### Example 6: Market Session as History

Using `Session` instead of [history requests](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/history-requests.md) or [rolling window](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/rolling-window.md) to cache the last 252 OHLCV bars, the following algorithm buys SPY accordingly when the market opens above the 252-day max of closing prices.

```python
class MarketSessionAsDailyHistory(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        equity = self.add_equity("SPY")

        # Increase the session lookback to 252 from default (0)
        # since our strategy break out the 252-day max of closing prices
        equity.session.size = 252
        # Warm up with daily data for speed
        self.set_warm_up(equity.session.size, Resolution.DAILY)

        self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.after_market_open("SPY", 1), self.trade_break_out)

    def trade_break_out(self):
        '''Break-out strategy. If the market opens above the 252-day max of closing prices,
        allocate all in SPY. Liquidate if it opens below the mean.
        '''
        session = self.securities["SPY"].session
        # The session is ready when the number of samples is greater than the size (252)
        if self.is_warming_up or not session.is_ready:
            return

        # Create a pandas Series of the closing prices of session
        # to use the max and mean methods
        closes = pd.Series([x.close for x in session][::-1])
        _open, _max, _mean = session.open, closes.max(), closes.mean()

        # Invest all in SPY if the open break out the 252-day max and liquidate below the mean
        if _open > _max:
            self.set_holdings("SPY", 1, tag=f'{_open=:.2f}, {_max=:.2f}')
        if _open < _mean:
            self.liquidate("SPY", tag=f'{_open=:.2f}, {_mean=:.2f}')
```
