After drawing a trend line on price data we can retrieve the recently active trend line in case we didn’t store the trend line reference. But how can we retrieve all MultiCharts .NET trend lines from the chart?

Creating and retrieving multiple MultiCharts .NET trend lines

The DrwTrendLine.Create() method draws trend lines and returns a reference to the line created (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). With that reference stored in an ITrendLineObject variable we can do things like relocating a trend line, changing a line’s appearance, removing a line, and extending a line. And when we don’t have the line’s reference assigned to a variable, we can select the recently active trend line. But how about selecting multiple trend lines?

We use the DrwTrendLine.GetTrendLineObjects() method to work with a group of trend lines. That method returns a collection implementing the IEnumerable<T> interface (see PowerLanguage .NET Help, n.d.), which is a type-safe collection interface that can be enumerated (that is, looped over) with foreach (Liberty & MacDonald, 2009). The <T> means it’s generic: this T will be replaced with whatever type the collection should hold (Stellman & Greene, 2010). In the case of trend lines, it will be a collection of type ITrendLineObject. For more on this method, see working with a collection of trend lines in MultiCharts .NET.

Example: creating and working with multiple MultiCharts .NET trend lines

When we apply the example indicator to an E-micro EUR/USD future chart, it looks as follows:

Collection of MultiCharts .NET trend lines

Once the script has drawn these trend lines, it outputs their bar numbers to the PowerLanguage .NET Editor Output Window. For example:

Trend line started at bar number 151 and ended at bar #161.
Trend line started at bar number 141 and ended at bar #161.
Trend line started at bar number 131 and ended at bar #161.
Trend line started at bar number 121 and ended at bar #161.
Trend line started at bar number 111 and ended at bar #161.
Trend line started at bar number 101 and ended at bar #161.
Trend line started at bar number 91 and ended at bar #161.
Trend line started at bar number 81 and ended at bar #161.
Trend line started at bar number 71 and ended at bar #161.
Trend line started at bar number 61 and ended at bar #161.

Programmatically retrieving all MultiCharts .NET trend lines on the chart

The above example indicator’s code is the following:

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

    private bool alreadyDrawn = false;

    protected override void CalcBar()
    {
        if (Bars.LastBarOnChart && !alreadyDrawn)
        {
            ChartPoint end = new ChartPoint(
                Bars.Time[0],
                Bars.Close[0]);

            // Create a bunch of lines, all with the same end point
            for (int i = 10; i <= 100; i += 10)
            {
                ChartPoint begin = new ChartPoint(
                    Bars.FullSymbolData.Time[i],
                    Bars.FullSymbolData.Close[i]);

                ITrendLineObject line = DrwTrendLine.Create(begin, end);

                line.Color = Color.DarkOrange;
            }

            // Retrieve all trends lines on the chart and loop over them
            IEnumerable<ITrendLineObject> allTrendLines = 
                DrwTrendLine.GetTrendLineObjects(EDrawingSource.AnyTechOrManual);

            foreach (ITrendLineObject trendLine in allTrendLines)
            {
                Output.WriteLine("Trend line started at bar number {0}" +
                    " and ended at bar #{1}.",
                    trendLine.Begin.BarNumber,
                    trendLine.End.BarNumber);
            }
            alreadyDrawn = true;
        }
    }
}

We start with defining a couple of MultiCharts .NET class attributes. Setting SameAsSymbol to true displays the indicator on the data series and not in a subchart. And RecoverDrawings set to false prevents automatic removal of intra-bar drawings (MultiCharts, 2014).

Then we declare the alreadyDrawn Boolean variable in the indicator’s class and initialise it to false. We use this variable afterward to check if the trend lines have been drawn. That way the script doesn’t create new lines with every price update.

Creating multiple trend lines with a for loop

Next is the CalcBar() method which consists out of an if statement that evaluates two conditions. The first is whether the current bar is the last of the primary data series, in which case Bars.LastBarOnChart returns true (PowerLanguage .NET Help, n.d.). The other condition verifies whether alreadyDrawn is false. We test that with the logical not operator (!), which returns the opposite of the value being evaluated (see Liberty & MacDonald, 2009).

The if statement’s code is executed when both conditions are true. That code block begins with declaring and initialising a ChartPoint struct variable named end that is set to the current bar’s time (Bars.Time[0]) and price (Bars.Close[0]). This variable holds the end point for each of the trend lines.

Then a for loop sets its i loop variable to 10 and continues as long as this variable is less than or equal to (<=) 100. After each loop cycle i is incremented with 10 by the addition compound assignment operator (+=), which is shorter way to write i = i + 10.

In the loop we declare and initialise a ChartPoint variable. This begin variable is set to the time (Bars.FullSymbolData.Time[i]) and close (Bars.FullSymbolData.Close[i]) of i bars ago. This way each subsequent trend line has a starting point further into the past (since the i variable increases with each loop cycle). The benefit of the Bars.FullSymbolData property is that it can access any price bar of the data series (see PowerLanguage .NET Help, n.d.).

We then call the DrwTrendLine.Create() method inside the loop and pass in the begin and end variables to draw the trend line between them. The value returned by this method is assigned to the line ITrendLineObject variable. We then use this variable to change the line’s appearance by setting the line’s Color property to a new value.

Retrieving a collection of all trend lines on the chart

Once the for loop ends we declare a collection that implements the IEnumerable<ITrendLineObject> interface from the System.Collections.Generic namespace. That namespace is added with a using statement to the top of the code file (see full example below).

This collection is assigned the value returned by the DrwTrendLine.GetTrendLineObjects() method, in which we pass the EDrawingSource.AnyTechOrManual enumerated value. This causes the method to return a collection with all programmatic and manual drawn trend lines on the chart (see PowerLanguage .NET Help, n.d.). See working with a collection of trend lines to learn more about EDrawingSource.

Now that we have a group of trend lines, we create a foreach loop to loop over the trend lines. This loop’s collection is set to allTrendLines and its type to an ITrendLineObject element named trendLine. This latter is used inside the loop to access the collection’s current item.

We call Output.WriteLine() inside the loop to print text to the PowerLanguage .NET Editor Output Window. In this method we pass a literal string and with two values: the bar number where the line starts and where it ends, which are retrievable with the trend line’s Begin.BarNumber and End.BarNumber properties (see PowerLanguage .NET Help, n.d.). This way we output data for each of the trend lines in the allTrendLines collection.

After the foreach loop ends we set the alreadyDrawn variable to true. Since that invalidates the CalcBar()’s if statement, the trend lines are only drawn and looped over once.

To learn more about working with a collection of trend lines, see looping over a collection of trend lines, removing all trend lines on the chart, and changing a specific trend line.

Summary

A single trend line is drawn by DrwTrendLine.Create(). Retrieving a chart’s trend lines is done with the DrwTrendLine.GetTrendLineObjects() method, which returns a collection that can be looped over with foreach. Depending on the EDrawingSource value provided to this method, it returns a subset or all trend lines (when EDrawingSource is set to AnyTechOrManual). We can then loop over the trend lines, operating on each trend line in turn.

Full MultiCharts .NET indicator example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using System.Collections.Generic;       // Added

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

        private bool alreadyDrawn = false;

        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart && !alreadyDrawn)
            {
                ChartPoint end = new ChartPoint(
                    Bars.Time[0],
                    Bars.Close[0]);

                // Create a bunch of lines, all with the same end point
                for (int i = 10; i <= 100; i += 10)
                {
                    ChartPoint begin = new ChartPoint(
                        Bars.FullSymbolData.Time[i],
                        Bars.FullSymbolData.Close[i]);

                    ITrendLineObject line = DrwTrendLine.Create(begin, end);

                    line.Color = Color.DarkOrange;
                }

                // Retrieve all trends lines on the chart and loop over them
                IEnumerable<ITrendLineObject> allTrendLines = 
                    DrwTrendLine.GetTrendLineObjects(EDrawingSource.AnyTechOrManual);

                foreach (ITrendLineObject trendLine in allTrendLines)
                {
                    Output.WriteLine("Trend line started at bar number {0}" +
                        " and ended at bar #{1}.",
                        trendLine.Begin.BarNumber,
                        trendLine.End.BarNumber);
                }

                /*
                Trend line started at bar number 151 and ended at bar #161.
                Trend line started at bar number 141 and ended at bar #161.
                Trend line started at bar number 131 and ended at bar #161.
                Trend line started at bar number 121 and ended at bar #161.
                Trend line started at bar number 111 and ended at bar #161.
                Trend line started at bar number 101 and ended at bar #161.
                Trend line started at bar number 91 and ended at bar #161.
                Trend line started at bar number 81 and ended at bar #161.
                Trend line started at bar number 71 and ended at bar #161.
                Trend line started at bar number 61 and ended at bar #161.
                */

                alreadyDrawn = true;
            }
        }
    }
}

References

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

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