My algorithm work with 15 minute heikin ashi bars, and they re-evaluated every minute, adding to a 15 minutes bar even if we didn't have full data for that 15 minutes. 

I've looked into consolidators but it seems like they only consolidate data once an entire minute/hour/etc has passed. I've tried with a custom consolidator and I've created a separate function to update the 15 minute bar every minute. Is this the correct approach? thanks

from AlgorithmImports import *
from datetime import datetime, timedelta

class HeikinAshiConsolidator:
    def __init__(self, period):
        self.period = period
        self.current_bar = None
        self.last_emit_time = datetime.min

    def update(self, bar):
        if self.current_bar is None:
            self.current_bar = TradeBar(
                time=bar.time,
                symbol=bar.symbol,
                open=bar.open,
                high=bar.high,
                low=bar.low,
                close=bar.close,
                volume=bar.volume
            )
        else:
            prev_close = self.current_bar.close
            self.current_bar.close = (bar.open + bar.high + bar.low + bar.close) / 4
            self.current_bar.high = max(bar.high, self.current_bar.open, self.current_bar.close)
            self.current_bar.low = min(bar.low, self.current_bar.open, self.current_bar.close)
            self.current_bar.volume += bar.volume

            prev_open = self.current_bar.open
            self.current_bar.open = (prev_open + prev_close) / 2

    def emit(self, algorithm):
        if self.current_bar is not None:
            algorithm.on_data_consolidated(self.current_bar)
            self.current_bar = None

    def should_emit(self, bar):
        return bar.time - self.last_emit_time >= self.period

    def scan(self, algorithm, bar):
        if self.should_emit(bar):
            self.emit(algorithm)
            self.last_emit_time = bar.time
        else:
            # Log and plot the bar at every minute for the chart
            algorithm.log_and_plot_heikin_ashi(self.current_bar)


class HeikinBollingerRsi(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2023, 12, 1)
        self.set_end_date(2023, 12, 31)
        self.set_cash(10000)

        self.symbol = self.add_equity("SPY", Resolution.MINUTE).symbol
        self.consolidator = HeikinAshiConsolidator(timedelta(minutes=15))

        # Create a chart and add a series to it
        chart = Chart("Heikin Ashi")
        chart.add_series(Series("15 Minute Bars", SeriesType.CANDLE, 0))
        self.add_chart(chart)

        self.set_warmup(11)

    def on_data(self, slice):
        if slice.bars.contains_key(self.symbol):
            bar = slice.bars[self.symbol]
            self.consolidator.update(bar)
            self.consolidator.scan(self, bar)

    def on_data_consolidated(self, bar):
        self.log(f"Consolidated Heikin Ashi Bar: {bar.time}, Open: {bar.open}, High: {bar.high}, Low: {bar.low}, Close: {bar.close}, Volume: {bar.volume}")

        # Plot the consolidated Heikin Ashi bar
        self.plot_heikin_ashi(bar)

    def log_and_plot_heikin_ashi(self, bar):
        if bar is not None:
            self.log(f"Current Heikin Ashi Bar: {bar.time}, Open: {bar.open}, High: {bar.high}, Low: {bar.low}, Close: {bar.close}, Volume: {bar.volume}")
            self.plot("Heikin Ashi", "15 Minute Bars", bar.time, bar.open, bar.high, bar.low, bar.close)

    def plot_heikin_ashi(self, bar):
        if bar is not None:
            self.plot("Heikin Ashi", "15 Minute Bars", bar.time, bar.open, bar.high, bar.low, bar.close)