After drawing a trend line, we can call the line’s Delete() method to remove a trend line and use its Exist property to see if the trend line is on the chart. But once we’ve removed a bunch of trend lines, how do we free up their computer memory?

Removing and fully deleting MultiCharts .NET trend lines

Drawing trend lines programmatically is done with DrwTrendLine.Create(), a method that returns a reference to the trend line after drawing it (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). When we store that reference in an ITrendLineObject interface variable, we can access a trend line’s properties and methods to do things like relocating, extending, or adjusting a line’s look.

Removing a trend line is done with its Delete() method (see MultiCharts, 2014) that returns a Boolean value that indicates if that operation succeeded or not (see PowerLanguage .NET Help, n.d.). But Delete() removes the line but not the trend line object (MultiCharts Support, personal communication, April 1, 2015). If we want to free up computer memory, the trend line object also needs to be removed. How to do so?

To delete an object in C# and to make its memory available for reuse, all references to it need to be removed by either setting them to null or to another object (Albahari & Albahari, 2012; Stellman & Greene, 2010). These unreferenced objects will then be removed when a process called the garbage collector runs (Sharp, 2013; Stellman & Greene, 2010).

Exactly when objects are garbage-collected is determined by the system (Liberty & MacDonald, 2009). While it’s possible to call GC.Collect() to suggest to .NET that it should do the garbage collection as soon as possible, this generally isn’t a good idea (Stellman & Greene, 2010). So in our example we’ll just set the reference to the trend line object to null and let MultiCharts .NET and its processes deal with the garbage collection.

Deleting MultiCharts .NET trend line objects

Getting rid of a trend line object once the line has been removed from the chart can be done as follows:

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

    protected override void CalcBar()
    {
        if (Bars.CurrentBar == 100)
        {
            // Create a trend line
            ITrendLineObject trendLine = DrwTrendLine.Create(
                new ChartPoint(Bars.Time[10], Bars.Close[10]),
                new ChartPoint(Bars.Time[1], Bars.Close[1]));

            trendLine.Size  = 2;
            trendLine.Color = Color.Blue;

            Output.WriteLine("Line starts at {0} and ends at {1}",
                trendLine.Begin.Time.ToShortTimeString(),
                trendLine.End.Time.ToShortTimeString());

            // Remove the trend line
            trendLine.Delete();

            if (!trendLine.Exist)
            {
                Output.WriteLine("Trend line is removed from the chart");
            }

            // Access removed trend line
            Output.WriteLine("Trend line's prices: {0}, {1}",
                trendLine.Begin.Price,
                trendLine.End.Price);

            // Remove reference to the trend line object
            trendLine = null;

            //> Line starts at 8:50 and ends at 9:35
            //> Trend line is removed from the chart
            //> Trend line's prices: -2, -2
        }
    }
}

We start off by setting SameAsSymbol to true so that the indicator is plotted on the data series and not in a subchart. Then in the CalcBar() method we use an if statement to verify whether the current bar number (Bars.CurrentBar) equals (==) 100. When it does, the code inside the if statement is executed.

Creating and deleting a trend line in MultiCharts .NET

That if statement’s code starts with drawing a trend line by calling DrwTrendLine.Create() and passing in two ChartPoint structs. The first marks the line’s begin point and is set to the time and close of a arbitrary 10 bars ago (Bars.Time[10] and Bars.Close[10]), while the second sets the line’s end point to the time and close of the previous bar. The value returned by the DrwTrendLine.Create() method is assigned to the ITrendLineObject trendLine variable. We subsequently use that variable to change the line’s visual appearance by setting new values to its Size and Color properties.

To track the indicator we output the line’s time coordinates (accessible through the line’s Begin and End properties; PowerLanguage .NET Help, n.d.) to the Output Window with Output.WriteLine(). Both times are formatted with ToShortTimeString() that converts a DateTime value to a short time string with formatting that depends on the current culture (Microsoft Developer Network, n.d.).

We then remove the trend line with its Delete() method, followed by using its Exist property to see if the trend line is on the chart. In that if statement we precede trendLine.Exist with the logical not operator (!). That operator returns the Boolean’s value opposite of the value its placed for (Sharp, 2013), meaning !trendLine.Exist returns true when Exist itself returns false. When Exist indicates the trend line isn’t on the chart, an accompanying message is printed to the Output Window.

Removing a trend line object in MultiCharts .NET

Even though we’ve just removed the trend line with Delete() (and Exist indicated the line is indeed gone from the chart), the line’s object does still exist. We can see that when we access the ‘removed’ trend line by printing its prices with Output.WriteLine(), which outputs the value of -2 twice. While this these are invalid chart prices, our trend line object is clearly still alive.

To also remove the trend line object, the references to it need to be removed. We do that by setting the trendLine variable to null, which causes this variable to not point to any object anymore (see Albahari & Albahari, 2012). Since all references to our trend line object are now removed, it’s scheduled for garbage collection and its used memory will be released the next time the garbage collector runs (Stellman & Greene, 2010; Sharp, 2013).

Keep in mind that, once a trend line’s reference variable is set to null, it cannot be used to work with the line’s methods and properties anymore. After all, the association between the variable and its (previously existing) trend line object is gone. If we nonetheless try to access the trend line, a NullReferenceException is thrown with the ‘Object reference not set to an instance of an object’ error message:

NullReferenceException in MultiCharts .NET
Tip: If you cannot be sure that an ITrendLineObject variable is associated with a trend line, first verify whether this variable is unequal to (!=) null before accessing the line’s properties and methods.

So the difference between Delete() and setting the trend line reference variable to null is that Delete() removes the trend line from the chart, while setting all of the line’s variables to null schedules the trend line object itself for removal.

To learn more about trend line removal, see removing a trend line and removing all trend lines. Verifying if a trend line exists shows how to programmatically check if a trend line is on the chart.

Summary

Trend lines are drawn by DrwTrendLine.Create() and removed by the line’s Delete() method. Removing a line from the chart, however, doesn’t remove the trend line object itself. To free up memory used by trend line objects that were removed from the chart, all references to them need to be set to null. These unreferenced objects will then be deleted the next time the garbage collector runs.

Complete MultiCharts .NET indicator example

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

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

        protected override void CalcBar()
        {
            if (Bars.CurrentBar == 100)
            {
                // Create a trend line
                ITrendLineObject trendLine = DrwTrendLine.Create(
                    new ChartPoint(Bars.Time[10], Bars.Close[10]),
                    new ChartPoint(Bars.Time[1], Bars.Close[1]));

                trendLine.Size  = 2;
                trendLine.Color = Color.Blue;

                Output.WriteLine("Line starts at {0} and ends at {1}",
                    trendLine.Begin.Time.ToShortTimeString(),
                    trendLine.End.Time.ToShortTimeString());

                // Remove the trend line
                trendLine.Delete();

                if (!trendLine.Exist)
                {
                    Output.WriteLine("Trend line is removed from the chart");
                }

                // Access removed trend line
                Output.WriteLine("Trend line's prices: {0}, {1}",
                    trendLine.Begin.Price,
                    trendLine.End.Price);

                // Remove reference to the trend line object
                trendLine = null;

                //> Line starts at 8:50 and ends at 9:35
                //> Trend line is removed from the chart
                //> Trend line's prices: -2, -2
            }
        }
    }
}

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.

Microsoft Developer Network (n.d.). DateTime.ToShortTimeString Method. Retrieved on April 11, 2015, from https://msdn.microsoft.com/en-us/library/system.datetime.toshorttimestring%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.