Situation
You want to know how to plot a text message in the Status Line with a colour that is dependent on the evaluation of an expression.

Programming example

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

namespace PowerLanguage.Indicator
{
    [UpdateOnEveryTick(true)]
    public class Example_ColouringStatusLine : IndicatorObject
    {
        private IPlotObjectStr statusLinePlot;
        private DateTime prevUpdateTime;
        
        public Example_ColouringStatusLine(object _ctx) : base(_ctx) { }
                
        protected override void Create()
        {
            statusLinePlot = AddPlot(new StringPlotAttributes());
        }
        
        protected override void CalcBar()
        {
            // Only execute the indicator on the last bar of the chart
            if (!Bars.LastBarOnChart)
                return;

            // Store the time of a new incoming tick
            if (Environment.CalcReason == CalculationReason.Default)
            {
                prevUpdateTime = Bars.StatusLine.Time;
            }

            TimeSpan timeDifference = DateTime.Now - prevUpdateTime;

            string statusLineText = string.Format("{0} ({1}s)",
                prevUpdateTime.ToString("HH:mm:ss.fff"),
                Math.Round(timeDifference.TotalSeconds, 1));

            // Depending on the time difference, plot with a different colour
            if (timeDifference > TimeSpan.FromSeconds(30))
            {
                statusLinePlot.Set(statusLineText, Color.Red);
            }
            else if (timeDifference > TimeSpan.FromSeconds(15))
            {
                statusLinePlot.Set(statusLineText, Color.Orange);
            }
            else
            {
                statusLinePlot.Set(statusLineText, Color.DarkGreen);
            }

            // Recalculate every second
            ExecControl.RecalcLastBarAfter(TimeSpan.FromSeconds(1));
        }

        // This method is called after each RecalcLastBarAfter() TimeSpan period elapses
        protected override void OnRecalcLastBarAfterEvent()
        {
            // Only perform the recalculation when the current day is not in the weekend
            if (DateTime.Now.DayOfWeek != DayOfWeek.Saturday && 
                DateTime.Now.DayOfWeek != DayOfWeek.Sunday)
            {
                this.CalcBar();
            }
        }
    }
}

Output of the programming example

The indicator generates the following output to the Status Line, with a colour that is dependent on the time since the last tick update:

Example of coloured Status Line in MultiCharts .NET

Working with the Status Line in MultiCharts .NET

The Status Line in MultiCharts .NET, the area at the top of the price chart, can display indicator values without having to create a line plot for the indicator. This is convenient for indicators whose historical values are not relevant, such as the average bid-ask spread, since this keeps the chart uncluttered.

Programmatically speaking, plotting text in the Status Line requires an IPlotObjectStr object, which can have its value set to a string variable through the Set() method (see MultiCharts, 2013).

Let’s see how that works in a concrete example.

MultiCharts .NET programming example

The example begins with setting the UpdateOnEveryTick attribute to true (line 8). That way the indicator is updated with every incoming price tick instead of only on bar close.

Then an IPlotObjectStr (named statusLinePlot) and a DateTime variable (prevUpdateTime) are declared (lines 11-12). This last variable will be used to store the time of the last tick update, so that the time difference can be calculated.

Creating the string plot

Making the string plot is done in the Create() override method:

protected override void Create()
{
    statusLinePlot = AddPlot(new StringPlotAttributes());
}

Here a new StringPlotAttributes object is created and assigned to the statusLinePlot variable we declared earlier in line 11.

Calculating the time since the last tick update

The next part in the example is the CalcBar() method. This method consists out of multiple parts. We first deal with calculating the time since the last tick update:

// Only execute the indicator on the last bar of the chart
if (!Bars.LastBarOnChart)
    return;

// Store the time of a new incoming tick
if (Environment.CalcReason == CalculationReason.Default)
{
    prevUpdateTime = Bars.StatusLine.Time;
}

TimeSpan timeDifference = DateTime.Now - prevUpdateTime;

Since it is unnecessary to calculate the indicator on historical price data, the return statement is called conditionally here on historical bars. This is tested with the Bars.LastBarOnChart property, which returns true if the current bar is the last bar on the chart, together with the logical not operator (!).

Since this example uses a periodic recalculation (which is a CalculationReason.Timer calculation reason), the if statement in line 28 ensures that only the time of new price ticks is used in the time difference calculation. Otherwise, bid or ask updates times that coincide with the periodic calculation are also stored in the prevUpdateTime variable.

Next the if statement in line 28 evaluates if the current calculation (Environment.CalcReason) is caused by a new incoming price tick (CalculationReason.Default). If that expression evaluates to true, the current data feed update time (Bars.StatusLine.Time) is assigned to the prevUpdateTime variable. By doing so, this variable gets assigned the DateTime value of each recent tick price update.

By subtracting the time of the last tick (prevUpdateTime) from the current computer time (DateTime.Now), we arrive at a TimeSpan structure that holds the time difference (line 33).

Generating the status line string

The next part generates the string message used in the Status Line:

string statusLineText = string.Format("{0} ({1}s)",
    prevUpdateTime.ToString("HH:mm:ss.fff"),
    Math.Round(timeDifference.TotalSeconds, 1));

With the use of string substitution parameters two variables are inserted into the string: the prevUpdateTime DateTime value formatted to a string and the timeDifference variable.

This timeDifference variable is outputted with the total amount of seconds by using the TotalSeconds property from a TimeSpan structure. Since TotalSeconds returns a double variable, which can hold up to 16 significant figures (see Liberty & MacDonald, 2009), Math.Round() is used to round this to a number of one decimal.

Colouring the Status Line indicator conditionally

In the next part a cascaded if-else statement is used to plot the Status Line message with different colours:

// Depending on the time difference, plot with a different colour
if (timeDifference > TimeSpan.FromSeconds(30))
{
    statusLinePlot.Set(statusLineText, Color.Red);
}
else if (timeDifference > TimeSpan.FromSeconds(15))
{
    statusLinePlot.Set(statusLineText, Color.Orange);
}
else
{
    statusLinePlot.Set(statusLineText, Color.DarkGreen);
}

By the way, the most restrictive condition in the cascaded if-else statement is tested here first because the less restrictive condition (greater than 15 seconds time difference) can also include timeDifference values that match the greater than 30 seconds conditional expression.

The timeDifference variable is evaluated here twice against a TimeSpan structure: if the time difference is larger than 30 seconds, the text will be plotted in red. Should the second if statement evaluate to true, the text will be displayed in orange. Finally, the else statement acts as a default option: all other timeDifference values will be plotted in dark green.

Recalculating the indicator periodically

Since indicators and trading strategies are updated with incoming ticks in MultiCharts .NET (see MultiCharts Wiki, 2012), we also need to recalculate the indicator based on a time interval. That way the plotted text displays an accurate value for the amount of seconds since the last price update.

To perform a periodic recalculation, the RecalcLastBarAfter() method is called at the end of the CalcBar() method:

// Recalculate every second
ExecControl.RecalcLastBarAfter(TimeSpan.FromSeconds(1));

This method, in turn, calls the OnRecalcLastBarAfterEvent() method which is implemented as follows:

// This method is called after each RecalcLastBarAfter() TimeSpan period elapses
protected override void OnRecalcLastBarAfterEvent()
{
    // Only perform the recalculation when the current day is not in the weekend
    if (DateTime.Now.DayOfWeek != DayOfWeek.Saturday && 
        DateTime.Now.DayOfWeek != DayOfWeek.Sunday)
    {
        this.CalcBar();
    }
}

In this method we evaluate if the current day is not a Saturday or Sunday (lines 61-62), so that the recalculation is not performed during the weekend. More information about recalculating a script periodically can be found in the recalculate a script based on a time interval article.

Key points:

  • An IPlotObjectStr object is used for plotting text in the Status Line;
  • To colour plotted text, the overloaded Set() method with parameters for the string variable and colour needs to be used;
  • To conditionally change colours, set the colour in the body of if statements;
  • When using an if-else statement to set a plot with a colour, include a default else case: otherwise, the plot will not be plotted if none of the if statements evaluate to true on the indicator update.
References

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

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

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