Situation
You want to know how to loop over historical price bars so that you can, for example, calculate the average price over the last few bars.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true), UpdateOnEveryTick(false)]
    public class Example_LoopHistoricalBars : IndicatorObject
    {
        private IPlotObject averagePrice;

        public Example_LoopHistoricalBars(object _ctx) : base(_ctx) { }
        
        protected override void Create()
        {
            averagePrice = AddPlot(new PlotAttributes("AveragePrice", EPlotShapes.Line, Color.ForestGreen));
        }
        
        protected override void CalcBar()
        {
            averagePrice.Set(CalculateAverage(10));
        }

        // The CalculateAverage() method calculates the average closing
        // price for the last 'numberOfBars' bars back
        private double CalculateAverage(int numberOfBars)
        {
            double sumOfPrices = 0;

            for (int i = 0; i < numberOfBars; i++)
            {
                sumOfPrices += Bars.Close[i];
            }

            return (sumOfPrices / numberOfBars);
        }
    }
}

Output of the programming example

Applied to a chart, the indicator plots the following line:

MultiCharts .NET example of looping over bars

Working with historical price bars in MultiCharts .NET

Data of price bars, such as the price and time data and price bar volume data, can be retrieved with several ISeriesSymbolData members, accessible through the Bars property (MultiCharts, 2013).

Accessing historical price data in MultiCharts .NET requires using the Bars property with an index greater than zero (see MultiCharts, 2013). For example, Bars.Close[1] returns the closing price of the previous bar for the primary data series, while Bars.High[2] returns the high of two bars ago for the primary data series.

Note: the number of historical bars that can be referenced depends on the MaxBarsBack setting. For more, see What are ‘MaxBarsBack’?.

Looping in C#

Repeatedly executing a code block, like aggregating prices of each bar, can be done with looping statements in C#. While there are different types of loops (such as the while, do-while, and foreach loops), the for loop is especially convenient because it combines several features in its header (see Liberty & MacDonald, 2009).

Let’s take a look at the programming example to see how accessing historical price bars can be combined with the for loop.

Programming example: class attributes in MultiCharts .NET

The example begins with setting two attributes:

[SameAsSymbol(true), UpdateOnEveryTick(false)]

Setting the SameAsSymbol attribute to true displays the indicator’s plotted line on the main data series and not in a separate sub-chart. The UpdateOnEveryTick attribute set to false forces the indicator to be only updated on bar close.

Plotting an indicator line in MultiCharts .NET

To plot an indicator line, we first need to declare an IPlotObject:

private IPlotObject averagePrice;

The averagePrice IPlotObject is subsequently initialised in the Create() override method:

protected override void Create()
{
    averagePrice = AddPlot(new PlotAttributes("AveragePrice", EPlotShapes.Line, Color.ForestGreen));
}

This statement (line 17) creates an indicator plot object that is named "AveragePrice" in the MultiCharts .NET data window and is plotted as a line (EPlotShapes.Line) with a green colour (Color.ForestGreen).

Setting the values of the plotted line

The next part of the example is the CalcBar() method:

protected override void CalcBar()
{
    averagePrice.Set(CalculateAverage(10));
}

The CalcBar() method is called on price bar, starting from the first (taking the MaxBarsBack setting into account) to the very last price bar (MultiCharts, 2013). On every bar, the averagePrice plot is set to the value of the CalculateAverage() method with an argument of 10, which defines the number of bars to loop over (see below).

Looping over historical price bars

This CalculateAverage() method is implemented as follows:

// The CalculateAverage() method calculates the average closing
// price for the last 'numberOfBars' bars back
private double CalculateAverage(int numberOfBars)
{
    double sumOfPrices = 0;

    for (int i = 0; i < numberOfBars; i++)
    {
        sumOfPrices += Bars.Close[i];
    }

    return (sumOfPrices / numberOfBars);
}

This method consists out of three parts. First a double variable is declared and initialised to zero to keep track of sum of prices (line 29).

The next part is the for loop (lines 31-34). This loop has its counter variable initialised to zero (int i = 0), which is incremented by one at the end of each iteration with the postfix increment operator (i++). As long as the value of i is less than the method's numberOfBars parameter, the loop is executed (the i < numberOfBars expression).

In the loop, the following statement is executed:

sumOfPrices += Bars.Close[i];

The sumOfPrices variable is calculated here with the self-assignment operator (+=). This operator is nothing more than a short way to write sumOfPrices = sumOfPrices + Bars.Close[i]. So, the existing variable value is added to a bar's closing price to arrive at the new sumOfPrices value.

The Bars.Close property in combination with the counter variable i is used to access the price data for the last bars. On the first run of the for loop, i will have a value of 0 so the current bar close (i.e., Bars.Close[0]) will be added to the sumOfPrices variable. On the next pass, i has a value of 1 and the previous bar close (i.e., Bars.Close[1]) is added to the sumOfPrices variable. This continues until i equals the numberOfBars integer value, after which the loop is stopped and the remainder of the CalculateAverage() method is executed.

The last part of this method calculates the average price by dividing the summed prices by the number of bars (line 36). This value is subsequently returned back to the calling method with the return keyword.

Key points:

  • Historical price bars can be accessed with the Bars property and an index greater than zero (e.g., Bars.Close[1] to return the closing price of the previous bar);
  • The number of bars that can be referenced historically is limited by the MaxBarsBack setting;
  • Looping over historical price bars can be done with the for loop and using the counter variable as the index (e.g., Bars.High[i] when the iterator is the i integer variable).
References

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

MultiCharts (2013). MultiCharts .NET Programming Guide (version 1.0). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.0.pdf