Situation
You want to know how to use the calculation status of the current price bar for a more efficient script calculation of indicators and trading strategies in MultiCharts .NET.

Programming example

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

namespace PowerLanguage.Indicator
{
    [UpdateOnEveryTick(true), SkipIdenticalTicks(false), SameAsSymbol(true)]
    public class Example_BarStatus : IndicatorObject
    {
        public Example_BarStatus(object _ctx) : base(_ctx) { }
        
        protected override void StartCalc()
        {
            Output.Clear();
        }
        
        protected override void CalcBar()
        {
            if (Bars.Status == EBarState.Close)
            {
                Output.WriteLine("#{0} - {1} - {2} - Place calculation intensive code here",
                    Bars.CurrentBar,
                    Bars.Time[0].ToString("HH:mm"),
                    BarStatus());
            }
            else
            {
                Output.WriteLine("#{0} - {1} - {2}",
                    Bars.CurrentBar,
                    Bars.Time[0].ToString("HH:mm"),
                    BarStatus());
            }
        }

        // The BarStatus() method returns a string with the
        // current calculation bar status
        private string BarStatus()
        {
            switch (Bars.Status)
            {
                case EBarState.Close:
                    return "Bar close";

                case EBarState.Inside:
                    return "Intra-bar price update";

                case EBarState.Open:
                    return "First tick of bar";

                default:
                    return "Not specified";
            }
        }
    }
}

Output of the programming example

When applied to a real-time chart like the following:

Example of script calculation in MultiCharts .NET

The indicator generates an output like (redundant lines removed for brevity):

#1845 - 09:20 - Intra-bar price update
#1845 - 09:20 - Intra-bar price update
#1845 - 09:20 - Intra-bar price update
#1845 - 09:20 - Bar close - Place calculation intensive code here
#1846 - 09:25 - First tick of bar
#1846 - 09:25 - Intra-bar price update
#1846 - 09:25 - Intra-bar price update
#1846 - 09:25 - Intra-bar price update
#1846 - 09:25 - Intra-bar price update
#1846 - 09:25 - Bar close - Place calculation intensive code here
#1847 - 09:30 - First tick of bar
#1847 - 09:30 - Intra-bar price update
#1847 - 09:30 - Intra-bar price update
#1847 - 09:30 - Intra-bar price update
#1847 - 09:30 - Intra-bar price update
#1847 - 09:30 - Bar close - Place calculation intensive code here
#1848 - 09:35 - First tick of bar
#1848 - 09:35 - Intra-bar price update
#1848 - 09:35 - Intra-bar price update
#1848 - 09:35 - Intra-bar price update

Efficient script calculation with the price bar status

Price data in MultiCharts .NET are represented by price bars, and price and time data for the primary data series can be accessed through the Bars property (MultiCharts, 2013). Real-time price bars (or historical price bars when the Bar Magnifier is enabled) can cause a script to be calculated on every tick.

While updating on every tick has its uses, it is not always necessary nor efficient. For example, most moving average trading strategies will only need to calculate their moving average values at the bar close. More efficient code processing is possible by using the current calculation bar status, which can be accessed through the Bars.Status property (MultiCharts, 2013).

Different types of price bar updates in MultiCharts .NET

The Bars.Status property returns an enumerator (from the EBarState enumeration) that expresses the price update on which the CalcBar() override method is calculated. This enumerator can have one of four values (PowerLanguage .NET Help, n.d.):

  • Open: when the current price update is the first tick of the bar;
  • Inside: if the current tick is an intra-bar price update;
  • Close: when the current tick marks the end of the bar;
  • None: when the market is closed and the script is periodically recalculated or when there are multiple data series on the chart and there is no bar yet for the specified data series (MultiCharts Support, personal communication, June 23, 2014).

Note that the Bars.Status property can only be accessed for the current bar since previous bars are already closed. Let's take a look at the programming example.

Programming example: attribute setting and Output Window clearing

The example begins with setting three class attributes:

[UpdateOnEveryTick(true), SkipIdenticalTicks(false), SameAsSymbol(true)]

The UpdateOnEveryTick attribute set to true makes the indicator update on every tick instead of only on bar close. By setting the SkipIdenticalTicks attribute to false, all price updates are processed by the indicator. Lastly, the SameAsSymbol attribute set to true plots the indicator on the main price chart and not in a separate sub-chart.

Then the StartCalc() override method is implemented:

protected override void StartCalc()
{
    Output.Clear();
}

This method, executed every time the script begins its calculation (MultiCharts, 2013), calls the Output.Clear() method to clear the PowerLanguage .NET Editor Output Window to prevent cluttering.

Differentiating on current bar calculation status

The next part is the CalcBar() method:

protected override void CalcBar()
{
    if (Bars.Status == EBarState.Close)
    {
        Output.WriteLine("#{0} - {1} - {2} - Place calculation intensive code here",
            Bars.CurrentBar,
            Bars.Time[0].ToString("HH:mm"),
            BarStatus());
    }
    else
    {
        Output.WriteLine("#{0} - {1} - {2}",
            Bars.CurrentBar,
            Bars.Time[0].ToString("HH:mm"),
            BarStatus());
    }
}

The first part of this if-else statement verifies if Bars.Status equals the bar close (EBarState.Close). When that is the case, the accompanying code block (lines 22-25) is executed; otherwise, the code block following the else statement (lines 29-32) is executed.

Sidenote: A price bar is considered closed when no additional ticks can be added to it (see MultiCharts Wiki, 2012). Time and range charts therefore have their bars closed when a new tick is outside the bar’s range or time interval.

Both Output.WriteLine() statements in the CalcBar() method are highly similar. Each uses string substitution parameters to output the current bar number (returned by the Bars.CurrentBar property), the current bar DateTime formatted to a string, and the string returned by the BarStatus() method (discussed below) to the PowerLanguage .NET Editor Output Window.

Switching on the bar status enumerator

The BarStatus() method is implemented as follows:

// The BarStatus() method returns a string with the
// current calculation bar status
private string BarStatus()
{
    switch (Bars.Status)
    {
        case EBarState.Close:
            return "Bar close";

        case EBarState.Inside:
            return "Intra-bar price update";

        case EBarState.Open:
            return "First tick of bar";

        default:
            return "Not specified";
    }
}

This method uses a switch statement to return a string dependent on the value of the Bars.Status enumerator. This way a more descriptive text is generated to describe the values of the EBarState enumeration.

By the way, the bar status of additional data series can be accessed with the BarsOfData() method: for example, BarsOfData(2).Status returns the bar status of the second data series.

Key points:

  • The current bar calculation status is returned by the Bars.Status property;
  • Bars.Status returns an enumerator from the EBarState enumeration;
  • The EBarState enumeration consists out of four named constants: Close (the closing tick of a price bar), Open (the first price update of a bar), Inside (ticks that happen intra-bar), and None for when there is no current bar calculation.
References

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

MultiCharts Wiki (February 2012). How Scripts Work. Retrieved on June 23, 2014, from http://www.multicharts.com/trading-software/index.php/How_Scripts_Work

PowerLanguage .NET Help (n.d.). Retrieved on May 16, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm