We can draw a trend line and adjust its visual appearance programmatically, but how do we move a trend line to a different location?

Changing the location of a trend line programmatically

Trend lines in MultiCharts .NET are drawn programmatically with DrwTrendLine.Create(). That method requires at least two ChartPoint struct values that specify the line’s begin and end points (MultiCharts, 2014; PowerLanguage .NET Help, n.d.), and returns an ITrendLineObject reference needed to further modify the line (MultiCharts, 2014).

With that returned value assigned to an ITrendLineObject variable, we can access the line’s Begin and End properties through that variable (see MultiCharts, 2014). And by assigning new ChartPoint struct values to those properties, we update the line’s location (see PowerLanguage .NET Help, n.d.).

Tip: When modifying a trend line’s location, the End coordinate needs to be changed before the Begin coordinate is modified (Henry MultiCharts, 2014).

Changing a trend line’s location in MultiCharts .NET: before and after

The example draws a trend line between the current bar and the one 30 bars ago, like with this 30-minute E-Mini S&P 500 future chart:

Change location of MultiCharts .NET trend line - before

At the close of each bar, the line’s location is updated so it moves along the newly formed price bars:

Change location of MultiCharts .NET trend line - after

Programmatically moving a trend line’s location in MultiCharts .NET

The example’s programming code is:

[SameAsSymbol(true)]
public class Example_ChangeTrendLineLocation : IndicatorObject
{
    public Example_ChangeTrendLineLocation(object _ctx) : base(_ctx) { }

    ITrendLineObject myTrendLine;

    protected override void CalcBar()
    {
        if (Bars.LastBarOnChart && Bars.Status == EBarState.Close)
        {
            if (myTrendLine == null)
            {
                // Create the trend line
                myTrendLine = DrwTrendLine.Create(
                    new ChartPoint(Bars.FullSymbolData.Time[30], 
                        Bars.FullSymbolData.Close[30]), 
                    new ChartPoint(Bars.Time[0], Bars.Close[0])
                    );
            }
            else
            {
                // Adjust the trend line's location
                myTrendLine.End = new ChartPoint(
                    Bars.Time[0], Bars.Close[0]);

                myTrendLine.Begin = new ChartPoint(
                    Bars.FullSymbolData.Time[30],
                    Bars.FullSymbolData.Close[30]);
            }

            myTrendLine.Size = 3;
        }
    }
}

We start by setting the SameAsSymbol attribute to true so that the indicator is plotted on the data series and not in a separate subchart. Then we declare an ITrendLineObject variable named myTrendLine, which will hold a reference to the created trend line afterwards.

Creating a trend line programmatically in MultiCharts .NET

The CalcBar() method begins with an if statement that checks whether the current bar is the last (then Bars.LastBarOnChart returns true) and if the script calculation is performed on bar close. In that latter case, Bars.Status equals (==) EBarState.Close (MultiCharts, 2014).

With that if statement the trend line is drawn or updated once per bar, at bar close. This prevents the default behaviour of removing intra-bar generated drawings on the next script calculation (see MultiCharts, 2014), which can be prevented with the RecoverDrawings attribute, by the way.

When both if statement conditions evaluate to true, an if/else statement begins with checking if myTrendLine equals null. Such a value is the default value of reference variables (Sempf, Sphar, & Davis, 2010), and means that the variable doesn’t refer to an object in memory (Sharp, 2013). That is, when myTrendLine equals null, it isn’t associated with a trend line object on the chart.

So we first create a trend line by calling the DrwTrendLine.Create() method and then assign this method’s returned value to the myTrendLine variable (which makes it different than null).

We define the line’s begin and end points with two ChartPoint structs. The starting point is set to 30 bars ago with the Bars.FullSymbolData property, with which we can access any price bar (see PowerLanguage .NET Help, n.d.). The line’s ending point is set to the current bar’s time (Bars.Time[0]) and close (Bars.Close[0]).

Adjusting the location of a MultiCharts .NET trend line

When the trend line is already drawn, the if/else statement’s else portion is executed. In that code block we set the line’s End and Begin properties, which both are accessible through the myTrendLine variable. The line’s ending point is set to the current bar, while the starting point is updated to 30 bars ago. This way the trend line moves along with the new bars on the chart.

Finally, to make the trend line more visible, its visual appearance is changed by setting the Size property to 3 for a thicker line. To learn more about modifying an existing trend line see extending a trend line, locking a trend line, and removing a trend line.

Summary

DrwTrendLine.Create() is a method that draws a trend line and returns a reference to the line made. When we store that reference in an ITrendLineObject variable, we can access and change the trend line through that variable. A line’s Begin and End properties return the trend line’s begin and end points. But those properties can also change a line’s location by assigning them a new ChartPoint value. When a line is relocated, its End property needs to be changed before the Begin property is adjusted.

Complete MultiCharts .NET indicator example

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

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true)]
    public class Example_ChangeTrendLineLocation : IndicatorObject
    {
        public Example_ChangeTrendLineLocation(object _ctx) : base(_ctx) { }

        ITrendLineObject myTrendLine;

        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart && Bars.Status == EBarState.Close)
            {
                if (myTrendLine == null)
                {
                    // Create the trend line
                    myTrendLine = DrwTrendLine.Create(
                        new ChartPoint(Bars.FullSymbolData.Time[30], 
                            Bars.FullSymbolData.Close[30]), 
                        new ChartPoint(Bars.Time[0], Bars.Close[0])
                        );
                }
                else
                {
                    // Adjust the trend line's location
                    myTrendLine.End = new ChartPoint(
                        Bars.Time[0], Bars.Close[0]);

                    myTrendLine.Begin = new ChartPoint(
                        Bars.FullSymbolData.Time[30],
                        Bars.FullSymbolData.Close[30]);
                }

                myTrendLine.Size = 3;
            }
        }
    }
}

References

Henry MultiCharts (2014, September 15). Simple drawing – forum discussion. Retrieved on February 15, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=19&t=47177#p108243

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.

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