---
title: "Consolidator History"
description: "This page explains how to save and access historical consolidated bars."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/consolidating-data/consolidator-history
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/consolidating-data/consolidator-history.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/18%20Consolidating%20Data/03%20Consolidator%20History
modified: 2026-10-31
index: https://www.quantconnect.com/llms.txt
---

# Consolidator History

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

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

## Introduction

Consolidators keep a built-in [RollingWindow](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/rolling-window.md) of the bars they produce. This section explains how to access these historical consolidated bars.

## Save Consolidated Bars

Every [consolidator](https://www.quantconnect.com/docs/v2/writing-algorithms/consolidating-data/getting-started.md) keeps a built-in `RollingWindow` of the bars it produces, so you can access recent consolidated bars without creating and maintaining your own `RollingWindow`. The window updates automatically each time the consolidator emits a bar. By default, it holds the 2 most recent bars.

```python
# Create and register a consolidator.
self._consolidator = TradeBarConsolidator(timedelta(minutes=10))
self.subscription_manager.add_consolidator("SPY", self._consolidator)
```

To access the trailing consolidated bars, use reverse list access semantics with positive and negative indexing. The current (most recent) bar is at index 0 or the `current` property, the previous bar is at index 1 or the `previous` property, and so on until the length of the window. Before the consolidator emits its first bar, `current` is `None`, so check the `window.count` or the window's `is_ready` flag first.

```python
current_bar = self._consolidator.current   # or self._consolidator[0]
previous_bar = self._consolidator.previous # or self._consolidator[1]
bar_count = self._consolidator.window.count
```

To access all the consolidated bars in the window, iterate through the consolidator.

```python
for bar in self._consolidator:
    self.log(f"{bar}")
```

To keep more than the 2 most recent bars, set the `size` of the window.

```python
self._consolidator.window.size = 10
```

## Get Historical Bars

The consolidator's built-in `window` is a [RollingWindow](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/rolling-window.md), so you can use negative indexing to get the oldest bar it holds.

```python
oldest_bar = self._consolidator.window[-1]
```

To get the consolidated bar that was most recently removed from the window, use the `most_recently_removed` property.

```python
removed_bar = self._consolidator.window.most_recently_removed
```

## Examples

The following examples demonstrate some common practices for consolidator history.

### Example 1: Price Action

The following algorithm trades breakout price action on the SPY five-minute trade bar. To do so, we create a five-minute trade bar consolidator and increase its built-in [rolling window](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/rolling-window.md) to hold 3 trade bars to check if the trade conditions are fulfilled.

```python
class ConsolidatorHistoryAlgorithm(QCAlgorithm):

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

        # Request SPY data for signal generation and trading.
        self.spy = self.add_equity("SPY", Resolution.MINUTE).symbol

        # The breakout is based on a 5-minute consolidated trade bar.
        self._consolidator = TradeBarConsolidator(timedelta(minutes=5))
        # Keep the last 3 consolidated bars to identify a breakout pattern.
        self._consolidator.window.size = 3
        # Subscribe for automatically updating the consolidator with SPY data.
        self.subscription_manager.add_consolidator(self.spy, self._consolidator)
        # Add a consolidator handler to check that the breakout condition is fulfilled and traded.
        self._consolidator.data_consolidated += self.on_consolidated

        self.set_warm_up(timedelta(1))

    def on_consolidated(self, sender: object, bar: TradeBar) -> None:
        # Inside the handler, the built-in window is already updated, so bar is self._consolidator[0].
        if not self.is_warming_up and self._consolidator.window.is_ready:
            # Buy if the breakout price action is fulfilled.
            # 1. Increasing price trend.
            # 2. The last 3 bars are green.
            # 3. The 3rd and 2nd last bars range is decreasing.
            # 4. The last bar exceeds the 2nd last bar by double the 2nd last bar's range.
            second_last = self._consolidator[1]
            third_last = self._consolidator[2]
            second_last_range = second_last.close - second_last.open
            if bar.close > second_last.close and second_last.close > third_last.close and\
            third_last.close > third_last.open and second_last.close > second_last.open and\
            bar.close > bar.open and third_last.close - third_last.open > second_last_range and\
            bar.close > second_last.close + 2 * second_last_range:
                self.set_holdings(self.spy, 0.5)

    def on_order_event(self, order_event: OrderEvent) -> None:
        if order_event.status == OrderStatus.FILLED:
            if order_event.ticket.order_type == OrderType.MARKET:
                # Stop loss order at 1%.
                stop_price = order_event.fill_price * 0.99 if order_event.fill_quantity > 0 else order_event.fill_price * 1.01
                self.stop_market_order(self.spy, -self.portfolio[self.spy].quantity, stop_price)
                # Take profit order at 2%.
                take_profit_price = order_event.fill_price * 1.02 if order_event.fill_quantity > 0 else order_event.fill_price * 0.98
                self.limit_order(self.spy, -self.portfolio[self.spy].quantity, take_profit_price)
            elif order_event.ticket.order_type == OrderType.STOP_MARKET or order_event.ticket.order_type == OrderType.LIMIT:
                # Cancel any open order if stop loss or take profit order filled.
                self.transactions.cancel_open_orders()
```
