We can draw trend lines on the script’s data series or in an indicator’s subchart. But how to draw trend lines on multiple chart symbols?

Drawing trend lines on multiple data series in MultiCharts .NET

The DrwTrendLine.Create() method draws trend lines in MultiCharts .NET (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). This is an overloaded method, which means it has several versions that we can call by providing different arguments (Liberty & MacDonald, 2009).

Each DrwTrendLine.Create() version returns a reference to the created line (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). When this is stored in an ITrendLineObject variable, we can use the variable to access the trend line’s properties and methods for things like relocating the trend line or adjusting its visual appearance.

The DrwTrendLine.Create() version that draws trend lines on different data series requires two ChartPoint structs (for the line’s begin and end point) and an integer that specifies the data series (starting with 1 for the first data series) (PowerLanguage .NET Help, n.d.).

Oddities with drawing trend lines on multiple data series in MultiCharts .NET

Drawing trend lines on multiple data series has two potentially confusing features. First, multiple data series on the chart aren’t necessarily numbered consecutively. For example, if we have three data series on the chart and remove the second symbol, the two remaining data series are numbered 1 and 3.

We can check the current data series numbers by right-clicking on the chart, selecting ‘Format Instruments’, and then look for the ‘Data #’ column:

Multiple data series in MultiCharts .NET

It’s not possible to programmatically determine the number of data series on the chart (MultiCharts Support, personal communication, December 8, 2014) nor can the actual data series numbers be retrieved. And so we need to provide the correct data series numbers to DrwTrendLine.Create() ourselves; otherwise, the ‘Study is missing data x. Please setup your chart data’-error message is triggered:

Error in MultiCharts .NET for multiple data series

The second oddity is that the order in which trend lines are drawn on the data series matters: with two data series, the trend line on the second data series needs to be created before drawing the line on the first data series (MultiCharts Support, personal communication, March 16, 2015).

Example of drawing lines on different chart symbols

Before the example indicator is applied to the chart, the E-mini S&P 500 and E-mini NASDAQ-100 symbols looks like:

MultiCharts .NET trend lines on multiple data series - before

Adding the indicator draws the trend lines on different data series:

MultiCharts .NET trend lines on multiple data series - after

Programmatically drawing trend lines on multiple data series

The programming example is the following:

[SameAsSymbol(true), RecoverDrawings(false)]
public class Example_TrendLinesDataSeries : IndicatorObject
{
    public Example_TrendLinesDataSeries(object _ctx) : base(_ctx) { }

    private ITrendLineObject data1Line, data2Line;

    protected override void StartCalc()
    {
        // Reset the trend line variables
        data1Line = null;
        data2Line = null;
    }

    protected override void CalcBar()
    {
        if (Bars.LastBarOnChart)
        {
            // Create the line on the second data series
            if (data2Line == null)
            {
                ChartPoint beginPoint = new ChartPoint(
                    BarsOfData(2).FullSymbolData.Time[60],
                    BarsOfData(2).FullSymbolData.Close[60]
                    );

                ChartPoint endPoint = new ChartPoint(
                    BarsOfData(2).Time[0],
                    BarsOfData(2).Close[0]
                    );

                data2Line = DrwTrendLine.Create(beginPoint, endPoint, 2);

                // Change the line's appearance
                data2Line.Size  = 3;
                data2Line.Style = ETLStyle.ToolDashed;
                data2Line.Color = Color.Tomato;
            }

            // Create the line on the first data series
            if (data1Line == null)
            {
                data1Line = DrwTrendLine.Create(
                    new ChartPoint(Bars.FullSymbolData.Time[40],
                        Bars.FullSymbolData.Close[40]),
                    new ChartPoint(Bars.Time[0],
                        Bars.Close[0]),
                        1);

                // Adjust the line's look
                data1Line.Size  = 2;
                data1Line.Color = Color.SpringGreen;
            }
        }
    }
}

We start with defining two class attributes. Setting SameAsSymbol to true displays the indicator on the data series (and not in its own subchart). And RecoverDrawings set to false prevents intra-bar generated drawings from being deleted automatically (MultiCharts, 2014).

We then declare two ITrendLineObject variables (data1Line and data2Line). These variables, that will hold the trend line references later on, are explicitly set to their default value of null in the StartCalc() method (see Sempf, Sphar, & Davis, 2010).

With this null value these reference variables don’t point to a trend line object (Stephens, 2014), making them in effect empty. By doing this in the StartCalc() method, which is called once before every calculation (MultiCharts, 2014), our trend line variables are reset when the script is toggled on or off. That way the script always draws the trend lines once.

Creating a trend line on the second data series

Next in the example is the CalcBar() method. This part begins with an if statement to check whether the current bar is the last, in which case the Bars.LastBarOnChart property returns true (PowerLanguage .NET Help, n.d.).

Inside the if statement, a nested if statement evaluates whether the data2Line variable equals null, which it does when this variable doesn’t point to a trend line object (Albahari & Albahari, 2012). This means we haven’t associated this variable with a trend line on the chart yet. And so it’s time to draw a trend line first.

For that we first create a ChartPoint struct variable named beginPoint that defines the line’s starting point. This variable is initialised to the time and close of 60 bars ago from the second data series. With the BarsOfData() method we can access any data series (see MultiCharts, 2014), and passing 2 inside this method gives us access to the second data series. To retrieve the historical price data we use the FullSymbolData property, which allows access to any price bar of the data series (MultiCharts, 2014; PowerLanguage .NET Help, n.d.).

Then we create a ChartPoint variable named endPoint. This chart coordinate is set to the time (BarsOfData(2).Time[0]) and close (BarsOfData(2).Close[0]) of the current bar of the second data series.

Once we’ve defined those chart coordinates on the second data series, we draw the trend line by calling the DrwTrendLine.Create() method and pass in both ChartPoint variables as arguments alongside with a value of 2. With that integer the line is drawn on the second data series. We assign the value returned by DrwTrendLine.Create() to the data2Line variable so we can modify the line once it has been made.

We subsequently change the trend line’s appearance by setting a new value to its Size, Style, and Color properties to create a medium-thick tomato-red line in a dashed style.

Drawing a trend line on the primary data series

The next part draws a trend line on the primary data series. First an if statement checks whether data1Line equals (==) null so that we only draw the line when it hasn’t been created yet.

Inside the if statement we call the DrwTrendLine.Create() method with three arguments. The first is a ChartPoint struct value set to time and close of 40 bars ago on the primary data series, which we retrieve with the Bars.FullSymbolData property (see PowerLanguage .NET Help, n.d.). The second argument, which marks the line’s end point, is a ChartPoint set to the current bar’s time and close (Bars.Time[0] and Bars.Close[0]). The third and final argument is the integer of 1 to draw the line on the first data series.

Here we also assign DrwTrendLine.Create()’s returned value to a variable (data1Line). That allows us to modify the line through the variable, which we do by assigning new values to the Size and Color properties.

See the essentials of drawing trend lines for an overview of the different DrwTrendLine.Create() versions, while trend line methods and properties provides an impression of working with trend lines in MultiCharts .NET. Examples of other ways to draw trends lines are drawing trend lines on price data and drawing trend lines on indicator values in a subchart.

Summary

Trend lines are made with the DrwTrendLine.Create() method. One version of this method requires two ChartPoint structs (for the line’s begin and end point) and an integer variable that specifies the data series number to draw on. Data series are, however, not always numbered consecutive. And trend lines need to be drawn on non-primary data series first before creating them on the primary data series.

Complete MultiCharts .NET indicator example

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

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true), RecoverDrawings(false)]
    public class Example_TrendLinesDataSeries : IndicatorObject
    {
        public Example_TrendLinesDataSeries(object _ctx) : base(_ctx) { }

        private ITrendLineObject data1Line, data2Line;

        protected override void StartCalc()
        {
            // Reset the trend line variables
            data1Line = null;
            data2Line = null;
        }

        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart)
            {
                // Create the line on the second data series
                if (data2Line == null)
                {
                    ChartPoint beginPoint = new ChartPoint(
                        BarsOfData(2).FullSymbolData.Time[60],
                        BarsOfData(2).FullSymbolData.Close[60]
                        );

                    ChartPoint endPoint = new ChartPoint(
                        BarsOfData(2).Time[0],
                        BarsOfData(2).Close[0]
                        );

                    data2Line = DrwTrendLine.Create(beginPoint, endPoint, 2);

                    // Change the line's appearance
                    data2Line.Size  = 3;
                    data2Line.Style = ETLStyle.ToolDashed;
                    data2Line.Color = Color.Tomato;
                }

                // Create the line on the first data series
                if (data1Line == null)
                {
                    data1Line = DrwTrendLine.Create(
                        new ChartPoint(Bars.FullSymbolData.Time[40],
                            Bars.FullSymbolData.Close[40]),
                        new ChartPoint(Bars.Time[0],
                            Bars.Close[0]),
                            1);

                    // Adjust the line's look
                    data1Line.Size  = 2;
                    data1Line.Color = Color.SpringGreen;
                }
            }
        }
    }
}

To learn more about C# programming, checkout Kodify's C# tutorials.


References

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

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

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

Sempf, B., Sphar, C., & Davis, S.R. (2010). C# 2010 All-In-One for Dummies. Hoboken, NJ: John Wiley & Sons.

Stephens, R. (2014). C# 5.0 Programmer Reference. Indianapolis, IN: John Wiley & Sons.

Visit Kodify for more helpful coding articles.