Consolidating Data

Estimated reading time: 3 min

Consolidating data allows you to create bars of any length from smaller bars. Commonly this is used to combine one-minute price bars into longer bars such as 10-20 minute bars. Using the price movement over a longer period can sometimes reduce the noise of the markets to make trading more efficient.

To achieve this, MachinaTrader allows you to create Consolidator objects and register them for data. Using a consolidator makes creating longer periods easier and reduces the chance of bugs. In the following sections, we will introduce the different types of consolidators and show you how to shape data into any form.

Consolidated output data is in the same format as the input. In other words, small TradeBars are aggregated into large TradeBars.

consolidating data

The most common request is to create bars based on a period of time. MachinaTrader has a helper for this called Consolidate(). The consolidate method looks up the Symbol requested, creates a consolidator for the given period, and passes the output to the provided function event handler. With just one line of code, you can create data in any format required. The consolidate helper accepts a timedelta, Resolution, or Calendar period specifier:

// Consolidate 1min BTCUSD -> 45min Bars
Consolidate("BTCUSD", TimeSpan.FromMinutes(45), FortyFiveMinuteBarHandler)

// Consolidate 1min BTCUSD -> 1-Hour Bars
Consolidate("BTCUSD", Resolution.Hour, HourBarHandler)

// Consolidate 1min BTCUSD -> 1-Week Bars
Consolidate("BTCUSD", Calendar.Weekly, WeekBarHandler)

The event handler function of Consolidate accepts one argument, the resulting bar.

// Example event handler from Consolidate helper.
void FortyFiveMinuteBarHandler(TradeBar consolidated) {
    Log($"{consolidated.EndTime:o} 45 minute consolidated.");

Using Consolidated Data

Consolidated data can easily be used with indicators along the period-resolution boundaries. This is possible with one line of code by the basic indicator API, as shown below. Using these helper methods, the required consolidators are created, and the output bar is automatically used to update the indicator. See the Indicators documentation for more information.

 // Consolidating minute SPY into 14-bar daily indicators
var ema = EMA("BTCUSD", 14, Resolution.Daily);
var sma = SMA("BTCUSD", 14, Resolution.Daily);

A common request is to use consolidators with indicators to create indicators with exotic data (e.g. 35-minute EMA). To do this, you will need to create the indicator and register it to receive updates. This is done with the RegisterIndicator function. Registering the indicator wires it up to get data updates from the Machina Engine automatically.

// Generate 7 minute bars; then SMA-10 generates the average of last 10 bars.
AddEquity("BTCUSD", Resolution.Minute);
var sma = new SimpleMovingAverage(10);
RegisterIndicator("BTCUSD", sma, TimeSpan.FromMinutes(7));

You can consolidate a certain number of bars or ticks using the count constructor of the consolidators. It will have the effect of joining n-bars together. To do this, you must create a manual consolidator and register it to receive data. The output of the consolidated bars will be piped to an event handler.

public override void Initialize()
    var threeCountConsolidator = new TradeBarConsolidator(3);
    threeCountConsolidator.DataConsolidated += ThreeBarHandler;
    SubscriptionManager.AddConsolidator("BTCUSD", threeCountConsolidator);

private void ThreeBarHandler(object sender, TradeBar bar) {
    // With hourly data the bar period is 3-hours
    Debug((bar.EndTime - bar.Time).ToString() + " " + bar.ToString());

Most people will not need to manually consolidate data, but if needed this gives you more control over the objects performing the aggregation and the data being used to feed them.

Data can be aggregated according to a period, with the time of the bars used to perform the consolidation. This requires the input data to be of a higher resolution than the desired consolidation period, e.g. to build a 1.5 hour bar you need minute data.

The mechanics are identical to consolidation counts described previously. You must create a consolidator object and then register it to receive data with the Subscription Manager.

public override void Initialize()
     // Assuming your symbol is "BTCUSD"

    // Create consolidator you need and attach event handler
    var thirtyMinuteConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(30));
    thirtyMinuteConsolidator.DataConsolidated += ThirtyMinuteHandler;

    // Register consolidator to get automatically updated with minute data
    SubscriptionManager.AddConsolidator("BTCUSD", thirtyMinuteConsolidator);

private void ThirtyMinuteHandler(object sender, TradeBar bar) {
    // Bar period is 30 min from the consolidator above.
    Debug((bar.EndTime - bar.Time).ToString() + " " + bar.ToString());

Renko bars are the consolidation of fixed price movements instead of fixed time periods. When you define a RenkoConsolidator you set the price movement instead of the period of the consolidation.

// Create Renko consolidator to trigger event when price moves $2.50
var renkoClose = new RenkoConsolidator(2.5m);
renkoClose.DataConsolidated += HandleRenkoClose;

// Register the consolidator for data
SubscriptionManager.AddConsolidator("BTCUSD", renkoClose);

The result of the consolidation is passed into an event handler. An event handler is a function in your algorithm designed to receive the bar. It can have any name but must have the required parameters. Depending on how you're using the consolidator system, you must use one of the method patterns below:

// self.Consolidate() Event Handler
void FortyFiveMinuteBarHandler(TradeBar consolidated) {

// Manually Created Event Handler
void ThirtyMinuteBarHandler(object sender, TradeBar consolidated) {

If you manually create a consolidator for a universe subscription, you should remember to remove it again later once the security leaves your universe. If you do not "tidy up", these can compound internally, causing your algorithm to slow down and eventually die once it runs out of RAM.

You will need to save a reference to the consolidator to remove it cleanly. We recommend using a class to organize all of the symbol-specific objects created over the lifetime of a security.

// Remove a consolidator instance from subscription manager
algorithm.SubscriptionManager.RemoveConsolidator(symbol, myConsolidator)
Was this article helpful?
Dislike 0
Views: 3