Once we’ve drawn a trend line programmatically we can change its visual appearance. But how can we change a trend line such that it alternates between different colours continuously?

Drawing MultiCharts .NET trend lines and changing their appearance

We draw trend lines in MultiCharts .NET with DrwTrendLine.Create(), a method that returns a reference to the line made (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). When stored in an ITrendLineObject variable, that reference provides access to the line’s properties and methods. For example, with that variable we can relocate, remove, or change a line’s look.

One use of trend lines is comparing their price value with the recent price, and then trigger alerts messages based on that. But how to make a notification that’s less distracting, like changing the look of the trend line itself?

We need two things for that: first retrieving the line’s price value of the current bar (so we can compare it to the recent price) and then adjusting the line’s appearance based on that comparison. Retrieving a trend line’s price values is done with PriceValue(), a method that returns the line’s price value for any DateTime value on the chart (MultiCharts, 2014; PowerLanguage .NET Help, n.d.).

By comparing the current price with the trend line’s price value for that bar, we can find out if the price trades below the line. If it does, the second step is changing the line’s appearance. We can, for example, do that by changing the line’s colour by settings its Color property to a different value (see PowerLanguage .NET Help, n.d.). Let’s examine the programming example to see how to repeatedly change a line’s colour in a certain situation.

Example: rotating a trend line’s colours in MultiCharts .NET

The example indicator draws a trend line with an initial colour that’s specified by the ‘FirstColour’ input. So when added to an E-mini S&P 500 future chart, it looks like:

Flashing trend line in MultiCharts .NET - 1

When the most recent price is below the trend line, the line changes its colour every few seconds. First, it switches to the second colour from the indicator’s inputs:

Flashing trend line in MultiCharts .NET - 2

Three seconds later the line changes to the third colour:

Flashing trend line in MultiCharts .NET - 3

When the recent price is not above the trend line, the line doesn’t change and keeps the colour from the first input, as this EUR/USD chart shows:

Flashing trend line in MultiCharts .NET - 4

‘Flashing’ a MultiCharts .NET trend line programmatically

This indicator’s programming code is the following:

[UpdateOnEveryTick(true), SameAsSymbol(true)]
public class Example_FlashingTrendLine : IndicatorObject
{
    private ITrendLineObject trendLine;

    [Input]
    public Color FirstColour { get; set; }

    [Input]
    public Color SecondColour { get; set; }

    [Input]
    public Color ThirdColour { get; set; }

    public Example_FlashingTrendLine(object _ctx) : base(_ctx) 
    {
        // Set the inputs to default values
        FirstColour  = Color.LimeGreen;
        SecondColour = Color.RoyalBlue;
        ThirdColour  = Color.Red;
    }

    protected override void CalcBar()
    {
        // Draw the trend line on the bar preceding the last bar
        if (Bars.FullSymbolData.Current == (Bars.FullSymbolData.Count - 1))
        {
            ChartPoint begin = new ChartPoint(
                Bars.FullSymbolData.Time[40],
                Bars.FullSymbolData.Close[40]);

            ChartPoint end = new ChartPoint(
                Bars.Time[0], Bars.Close[0]);

            trendLine = DrwTrendLine.Create(begin, end);

            trendLine.Size     = 2;
            trendLine.Color    = FirstColour;
            trendLine.ExtLeft  = true;
            trendLine.ExtRight = true;
        }

        // Recalculate the script every second on the last bar
        if (Bars.LastBarOnChart)
            ExecControl.RecalcLastBarAfter(new TimeSpan(0, 0, 1));
    }

    protected override void OnRecalcLastBarAfterEvent()
    {
        if (trendLine == null)
            return;

        // Change the trend line's colour when the current 
        //      price is below the line
        if ((DateTime.Now.Second % 3 == 0) &&
            (Bars.Close[0] < trendLine.PriceValue(Bars.Time[0])))
        {
            // Switch the line's colour based on the current colour
            if (trendLine.Color.ToArgb() == FirstColour.ToArgb())
            {
                trendLine.Color = SecondColour;
            }
            else if (trendLine.Color.ToArgb() == SecondColour.ToArgb())
            {
                trendLine.Color = ThirdColour;
            }
            else if (trendLine.Color.ToArgb() == ThirdColour.ToArgb())
            {
                trendLine.Color = FirstColour;
            }
        }

        this.CalcBar();
    }
}

We first set the UpdateOnEveryTick attribute to true so that the indicator is updated on every tick. And by setting the SameAsSymbol attribute to true we display the indicator on the price chart and not in its own subchart.

After that we declare an ITrendLineObject variable named trendLine. We’ll use this variable later on to hold the line reference so that we can access the trend line object.

Then we add three inputs to the script, all of which are automatic properties of type Color. They are named FirstColour, SecondColour, and ThirdColour and set in the indicator’s constructor to default values of Color.LimeGreen, Color.RoyalBlue, and Color.Red, respectively. We’ll use these when changing the line’s colour.

Drawing a trend line in MultiCharts .NET

Next in the example is the CalcBar() method. It starts with an if statement that evaluates whether the bar that the script is currently being calculated on, returned by the Bars.FullSymbolData.Current property (PowerLanguage .NET Help, n.d.), equals (==) the bar preceding the last bar. This latter value is retrieved with Bars.FullSymbolDate.Count, a property that returns the number of bars of the first data series (see PowerLanguage .NET Help, n.d.).

With that condition being true, we create two ChartPoint struct variables to define the line’s chart coordinates. The first, begin, is set to time and close of 40 bars ago, retrieved with the Bars.FullSymbolData property that allows access to any bar of the data series (PowerLanguage .NET Help, n.d.), irrespective of the indicator’s MaxBarsBack value. The second chart location, dubbed end, is set to the current bar’s time and close (Bars.Time[0] and Bars.Close[0]).

Then we call the DrwTrendLine.Create() method to draw a trend line and pass in the begin and end variables to define the line’s begin and end point. We assign the reference returned by this method to the trendLine variable, which is then used to change the trend line’s appearance by setting its Size and Color properties to different values. With the ExtLeft and ExtRight properties set to true, the line is extended into both directions.

The second if statement in CalcBar() checks if the Bars.LastBarOnChart property returns true, which happens when the current bar is the last of the data series (see MultiCharts, 2014). In that situation we call the ExecControl.RecalcLastBarAfter() method with a TimeSpan struct argument of 1 second. As soon as this time interval has passed, this method calls the OnRecalcLastBarAfterEvent() method to perform a periodic script recalculation (see PowerLanguage .NET Help, n.d.).

Preventing exceptions with a MultiCharts .NET trend line

The example’s last part implements the OnRecalcLastBarAfterEvent() method, which is executed when the periodic script calculation triggered by ExecControl.RecalcLastBarAfter() occurs. It starts with an if statement that evaluates if trendLine equals (==) null. Such a value signals that a reference variable doesn’t point to an object (Albahari & Albahari, 2012), which in this context means the trendLine variable doesn’t hold a reference to the line object on the chart.

When that happens, a NullReferenceException is triggered when we try to access one of the line’s properties or methods through the trendLine variable (see Stellman & Greene, 2010). We prevent that with the return keyword that causes the method’s remaining code to be skipped (see Dorman, 2010). And so the code in OnRecalcLastBarAfterEvent() that’s placed below return is only executed when trendLine is actually associated with a trend line.

Changing a trend line’s colours continuously

The next if statement evaluates two expressions. The first is whether the number of seconds of the current computer time (returned by the DateTime.Now.Seconds property; Microsoft Developer Network [MSDN], n.d. a) divides evenly into 3. We check this with the modulus operator (%), which returns the arithmetic remainder of dividing the first value with the second (Sharp, 2013). As such, this condition is only true once every 3 seconds.

The other condition is whether the most recent price (Bars.Close[0]) is less than (<) the trend line’s price value. Retrieving the line’s price value for any DateTime value on the chart is done with PriceValue() (see PowerLanguage .NET Help, n.d.), a method in which we pass the current bar’s date and time (Bars.Time[0]) here.

When this if statement’s conditions are both true, an if/else statement changes the trend line’s colour based on its current colour, which is returned by the Color property (PowerLanguage .NET Help, n.d.). To compare the line’s colour with the indicator’s input options, we test for equality and call the ToArgb() method on both Color values. This method returns the ARGB value (alpha, red, green, and blue colour components) of the Color structure (MSDN, n.d. b), and such allows for comparing different colour values exactly.

When any of these three nested if statements evaluate to true, the line’s Color property is assigned the next colour from the indicator’s inputs. So when the line has the second colour, it switches to the third. And when it has the third colour, it starts over with the first colour again.

The last statement in OnRecalcLastBarAfterEvent() calls the CalcBar() method preceded with the this keyword, which refers to the current instance of an object and such removes any ambiguity (Liberty & MacDonald, 2009). Note that this is what creates the script’s periodic recalculation: CalcBar() calls ExecControl.RecalcLastBarAfter(), that in turn calls OnRecalcLastBarAfterEvent() which then calls CalcBar() again.

Other programming examples that notify when certain conditions happen are colouring price bars above or below the line, generating automatic trend line alerts, creating custom trend line alerts, and triggering intra-bar trend line alerts.

Summary

Trend lines drawn with DrwTrendLine.Create() return a reference needed to access the line. A line’s PriceValue() method returns the line’s price value for any DateTime value on the chart. By comparing the recent price with the trend line’s price we can change a line’s characteristics (like it colour) conditionally. Changing a line’s colour repeatedly requires first comparing its current Color value with several predefined ones, and then set the line’s Color property to the next colour. Periodically recalculating a script is done by passing a TimeSpan struct into the ExecControl.RecalcLastBarAfter() method, which in turn will call OnRecalcLastBarAfterEvent() once this time interval has elapsed.

Complete MultiCharts .NET indicator example

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

namespace PowerLanguage.Indicator
{
    [UpdateOnEveryTick(true), SameAsSymbol(true)]
    public class Example_FlashingTrendLine : IndicatorObject
    {
        private ITrendLineObject trendLine;

        [Input]
        public Color FirstColour { get; set; }

        [Input]
        public Color SecondColour { get; set; }

        [Input]
        public Color ThirdColour { get; set; }

        public Example_FlashingTrendLine(object _ctx) : base(_ctx) 
        {
            // Set the inputs to default values
            FirstColour  = Color.LimeGreen;
            SecondColour = Color.RoyalBlue;
            ThirdColour  = Color.Red;
        }

        protected override void CalcBar()
        {
            // Draw the trend line on the bar preceding the last bar
            if (Bars.FullSymbolData.Current == (Bars.FullSymbolData.Count - 1))
            {
                ChartPoint begin = new ChartPoint(
                    Bars.FullSymbolData.Time[40],
                    Bars.FullSymbolData.Close[40]);

                ChartPoint end = new ChartPoint(
                    Bars.Time[0], Bars.Close[0]);

                trendLine = DrwTrendLine.Create(begin, end);

                trendLine.Size     = 2;
                trendLine.Color    = FirstColour;
                trendLine.ExtLeft  = true;
                trendLine.ExtRight = true;
            }

            // Recalculate the script every second on the last bar
            if (Bars.LastBarOnChart)
                ExecControl.RecalcLastBarAfter(new TimeSpan(0, 0, 1));
        }

        protected override void OnRecalcLastBarAfterEvent()
        {
            if (trendLine == null)
                return;

            // Change the trend line's colour when the current 
            //      price is below the line
            if ((DateTime.Now.Second % 3 == 0) &&
                (Bars.Close[0] < trendLine.PriceValue(Bars.Time[0])))
            {
                // Switch the line's colour based on the current colour
                if (trendLine.Color.ToArgb() == FirstColour.ToArgb())
                {
                    trendLine.Color = SecondColour;
                }
                else if (trendLine.Color.ToArgb() == SecondColour.ToArgb())
                {
                    trendLine.Color = ThirdColour;
                }
                else if (trendLine.Color.ToArgb() == ThirdColour.ToArgb())
                {
                    trendLine.Color = FirstColour;
                }
            }

            this.CalcBar();
        }
    }
}

References

Albahari, J. & Albahari, B. (2012). C# 5.0 in a Nutshell: The Definitive Reference (5th edition). Sebastopol, CA: O’Reilly Media.

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN: Sams/Pearson Education.

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

Microsoft Developer Network (MSDN) (n.d. a). DateTime.Second Property. Retrieved on May 24, 2015, from https://msdn.microsoft.com/en-us/library/system.datetime.second%28v=vs.110%29.aspx

Microsoft Developer Network (MSDN) (n.d. b). Color.ToArgb Method. Retrieved on May 25, 2015, from https://msdn.microsoft.com/en-us/library/system.drawing.color.toargb%28v=vs.110%29.aspx

MultiCharts (2014). MultiCharts .NET Programming Guide (version 1.1). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.1.pdf

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

Sharp, J. (2013). Microsoft Visual C# 2013 Step by Step. Microsoft Press.

Stellman, A. & Greene, J. (2010). Head First C#: A Brain-Friendly Guide (2nd edition). Sebastopol, CA: O’Reilly Media.