Situation
You want to know how to access price, volume, and time data from additional symbols that are applied to a chart or added to a portfolio.

Programming example

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

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true)]
    public class Example_AccessAdditionalDataSeries : IndicatorObject
    {
        bool alreadyPrinted;

        public Example_AccessAdditionalDataSeries(object _ctx) : base(_ctx) { }

        protected override void StartCalc()
        {
            alreadyPrinted       = false;
            ExecInfo.MaxBarsBack = 10;
        }

        protected override void CalcBar()
        {
            // Output data from the data series on the last bar
            if (Bars.LastBarOnChart && !alreadyPrinted)
            {
                Output.WriteLine("Current price: Symbol 1: {0}, Symbol 2: {1}, Symbol 3: {2}",
                    BarsOfData(1).Close[0],
                    BarsOfData(2).Close[0],
                    BarsOfData(3).Close[0] + System.Environment.NewLine);

                Output.WriteLine("Ticks for the previous bar: " 
                    + "Symbol 1: {0}, Symbol 2: {1}, Symbol 3: {2}",
                    BarsOfData(1).Ticks[1],
                    BarsOfData(2).Ticks[1],
                    BarsOfData(3).Ticks[1]);

                alreadyPrinted = true;
            }
        }
    }
}

Output of the programming example

When applied to the following chart that has three data series (EUR/USD, EUR/GBP, and EUR/CHF):

Example of multiple data series in MultiCharts .NET

The indicator generates the following text to the PowerLanguage .NET Editor:

Current price: Symbol 1: 1,36124, Symbol 2: 0,79812, Symbol 3: 1,21683

Ticks for the previous bar: Symbol 1: 70293, Symbol 2: 50797, Symbol 3: 27322

Working with additional data series in MultiCharts .NET

Price and volume data are represented by price bars in MultiCharts .NET. For the primary data series, the Bars property provides access to the price and time data and volume data (MultiCharts, 2013).

Additional data series of a chart or portfolio can be accessed with the BarsOfData() method, whereby the data number needs to be provided as an argument (MultiCharts, 2013). This method can be used in the StartCalc(), CalcBar(), and StopCalc() override methods provided that the number of bars referenced is less than or equal to the MaxBarsBack setting.

Bars and BarsOfData() are both references to the IInstrument interface, making them interchangeable. So for accessing additional data series, replace the Bars property with the BarsOfData() method. For instance, Bars.Info.Name returns the symbol for the primary data series, whereas BarsOfData(2).Info.Name does so for the second data series. And Bars.CurrentBar returns the bar number for the primary data series, while BarsOfData(3).CurrentBar does the same for the third data series.

Referencing price bar data from additional data series

Price bar data from the primary data series can be accessed either with the Bars property or by using BarsOfData(1).

The table below provides examples for accessing price, volume, and time data from additional data series. To learn more, see the articles referencing historical price bars, using price and time data, and working with volume data.

BarsOfData() example Description
BarsOfData(2).CloseValue Returns the current price of the second data series.
BarsOfData(5).DownTicks[1] Returns the number of down ticks for the previous bar of the fifth data series.
BarsOfData(3).High[5] Returns the high price of five bars ago for the third data series.
BarsOfData(1).Low[1] Returns the low price of the previous bar for the first (i.e., primary) data series.
BarsOfData(2).Open[0] Returns the open price for the current bar of the second data series.
BarsOfData(4).OpenIntValue Returns the open interest for the current bar of the fourth data series.
BarsOfData(2).Ticks[0] Returns the number of ticks for the current bar of the second data series.
BarsOfData(1).Time[3] Returns the DateTime value of three bars ago for the first data series.
BarsOfData(6).UpTicks[1] Returns the number of upticks for the previous bar for the sixth data series.
BarsOfData(2).Volume[1] Returns the volume for the previous bar of the second data series.

Let’s now take a closer look at the programming example.

MultiCharts .NET programming example

The example begins by setting the SameAsSymbol attribute to true:

[SameAsSymbol(true)]

This lets the indicator plot on the first data series as opposed to creating a separate sub-chart.

Then a Boolean variable (alreadyPrinted) is declared in line 11 and initialised in the StartCalc() override method:

protected override void StartCalc()
{
    alreadyPrinted       = false;
    ExecInfo.MaxBarsBack = 10;
}

The StartCalc() method is executed at the beginning of every calculation (see MultiCharts, 2013). By setting the alreadyPrinted variable here to false, we ensure that the data is only printed to the PowerLanguage .NET Editor once per indicator calculation.

Programmatically setting the MaxBarsBack is also done in this method (line 18). This prevents that the indicator automatically recalculates when the automatic, initially assigned MaxBarsBack value proves to be insufficient.

Outputting price and volume data

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

protected override void CalcBar()
{
    // Output data from the data series on the last bar
    if (Bars.LastBarOnChart && !alreadyPrinted)
    {
        Output.WriteLine("Current price: Symbol 1: {0}, Symbol 2: {1}, Symbol 3: {2}",
            BarsOfData(1).Close[0],
            BarsOfData(2).Close[0],
            BarsOfData(3).Close[0] + System.Environment.NewLine);

        Output.WriteLine("Ticks for the previous bar: " 
            + "Symbol 1: {0}, Symbol 2: {1}, Symbol 3: {2}",
            BarsOfData(1).Ticks[1],
            BarsOfData(2).Ticks[1],
            BarsOfData(3).Ticks[1]);

        alreadyPrinted = true;
    }
}

The if statement (line 24) evaluates two conditions. First, whether the current bar of the primary data series is the last bar on the chart (in which case the Bars.LastBarOnChart property returns true). Second, if the Boolean alreadyPrinted variable is false by using the logical not operator (!).

When both conditions evaluate to true, BarsOfData(1).Close[0] to BarsOfData(3).Close[0] output the current prices of the symbols with the use of string substitution parameters (lines 26-29). In addition, a new line string is added with the System.Environment.NewLine property (line 29) to keep the output of both Output.WriteLine() methods separate.

See the articles what are up and down ticks and working with volume data to learn more about volume and ticks in MultiCharts .NET.

The second part of the if statement body outputs the total number of ticks of the previous bar for each of the three data series by using BarsOfData(1).Ticks[1] to BarsOfData(3).Ticks[1] (lines 31-35).

Finally, the last statement sets the alreadyPrinted variable to true so that the output is only generated once per indicator calculation.

Key points:

  • Price bar data from additional data series can be accessed with the BarsOfData() method by providing the data series number (starting with 1 for the first data series);
  • The Bars property and the BarsOfData() method both provide access to the same type of instrument data and can be used interchangeably;
  • BarsOfData(1) is the equivalent of the Bars property.
References

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