After drawing a MultiCharts .NET trend line, we can change its visual appearance or update its chart coordinates. But how do we retrieve a line’s price values for a certain date and time?

Drawing a trend line and retrieving its values in MultiCharts .NET

The overloaded DrwTrendLine.Create() method can draw trend lines on the script’s data series, on an indicator’s subchart, or on price data from different data series (PowerLanguage .NET Help, n.d.). This method returns a reference to the line made (MultiCharts, 2014; PowerLanguage .NET Help, n.d.) which, when assigned to an ITrendLineObject variable, can be used to access the trend line’s properties and methods. Alternatively, we can retrieve a line’s reference by selecting the active trend line.

One of those trend line methods is PriceValue(), which returns the line’s price value for a given DateTime value (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). With this method we can, for example, get a line’s price value for each of the historical bars it was drawn on. To see how, let’s consider the programming example.

Drawing a trend line and outputting its price values

When the example script (discussed below) is applied to an EuroStoxx 50 future chart, it looks like:

Trend line on historical bars in MultiCharts .NET

The indicator also generates output to the PowerLanguage .NET Editor Output Window, similar to:

Bar time: 20:00, line value: 3591
Bar time: 20:05, line value: 3591,375
Bar time: 20:10, line value: 3591,75
Bar time: 20:15, line value: 3592,125
Bar time: 20:20, line value: 3592,5
Bar time: 20:25, line value: 3592,875
Bar time: 20:30, line value: 3593,25
Bar time: 20:35, line value: 3593,625
Bar time: 20:40, line value: 3594
Bar time: 20:45, line value: 3594,375
Bar time: 20:50, line value: 3594,75
Bar time: 20:55, line value: 3595,125
Bar time: 21:00, line value: 3595,5
Bar time: 21:05, line value: 3595,875
Bar time: 21:10, line value: 3596,25
Bar time: 21:15, line value: 3596,625
Bar time: 21:20, line value: 3597
Bar time: 21:25, line value: 3597,375
Bar time: 21:30, line value: 3597,75
Bar time: 21:35, line value: 3598,125
Bar time: 21:40, line value: 3598,5
Bar time: 21:45, line value: 3598,875
Bar time: 21:50, line value: 3599,25
Bar time: 21:55, line value: 3599,625
Bar time: 22:00, line value: 3600
Average trend line value: 3595,5

Getting trend line values for historical bars programmatically

The indicator’s code looks as follows:

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

    private ITrendLineObject trendLine;

    protected override void StartCalc()
    {
        trendLine = null;
    }

    protected override void CalcBar()
    {
        if (Bars.LastBarOnChart && trendLine == null)
        {
            // Create the trend line
            trendLine = DrwTrendLine.Create(
                new ChartPoint(Bars.Time[24], Bars.Close[24]),
                new ChartPoint(Bars.Time[0], Bars.Close[0])
                );

            trendLine.Size  = 2;
            trendLine.Color = Color.LimeGreen;

            // Get trend line values for the historical bars
            double avgLineValue = 0.0;

            for (int i = 24; i >= 0; i--)
            {
                Output.WriteLine("Bar time: {0}, line value: {1}",
                    Bars.Time[i].ToString("HH:mm"),
                    trendLine.PriceValue(Bars.Time[i]));

                avgLineValue += trendLine.PriceValue(Bars.Time[i]);
            }

            avgLineValue /= 25;

            Output.WriteLine("Average trend line value: {0}",
                avgLineValue);
        }
    }
}

We start with defining two attributes. SameAsSymbol set to true displays the indicator on the data series and not in a subchart. And RecoverDrawings set to false prevents intra-bar generated drawings from begin removed (MultiCharts, 2014).

Then we declare an ITrendLineObject interface variable named trendLine that’s set to null in the StartCalc() method. This resets the variable at the start of each script calculation, and is done so that toggling the indicator on and off will still redraw the trend line.

Creating and modifying a trend line in MultiCharts .NET

Next is the CalcBar() method. We start with an if statement to see whether the current bar is the last, in which case the Bars.LastBarOnChart property returns true (PowerLanguage .NET Help, n.d.).

Another condition evaluated by the if statement is whether the trendLine variable equals, a value of null means it doesn’t point to an object (Stephens, 2014). In this context, it means our trend line variable hasn’t been associated with an actual trend line on the chart yet.

And so when both conditions evaluate to true, we first create a trend line by calling the DrwTrendLine.Create() method. In it, we initialise two ChartPoint structs: one set to the time and close of 24 bars ago (so it starts at the 20:00 o’clock bar in the image above) and the second set to the current bar’s time (Bars.Time[0]) and close (Bars.Close[0]).

The value returned by DrwTrendLine.Create() is assigned to the trendLine variable. We can now access the trend line’s properties through this variable, which we subsequently do by setting its Size and Color properties to new values in order to change the line’s visual appearance.

Retrieving trend line price values in MultiCharts .NET

The second part of the if statement in CalcBar() retrieves the trend line’s price value for each bar that the line was drawn on.

We first declare and initialise a double variable. This avgLineValue variable is used to calculate the line’s average price value. Then a for loop begins that starts at 24 (since the line’s begin point is this many bars ago) and continues till 0 (for the current bar’s values). The postfix decrement operator (--) is used to decrease the i loop variable with one after each loop cycle. That operator is just a shorthand way to write i = i - 1 (see Dorman, 2010).

In the loop, the time and trend line price value for each of these 25 bars are outputted to the Output Window. The time is retrieved with Bars.Time[i], with the i loop variable going from 24 to 0. This DateTime value is formatted to a string with the HH:mm custom format specifier, with HH standing for the hour (using a 24-hour clock, from 00 to 23), and mm marks the minute from 00 to 59 (Dorman, 2010).

The trend line’s price value for each bar is retrieved with the line’s PriceValue() method. To get that price for a specific bar, we pass the bar’s DateTime value (Bars.Time[i]) into this method.

The avgLineValue variable is assigned a running sum of the line’s price values in the loop. It does so by adding the value returned by PriceValue(Bars.Time[i]) to itself with the += compound assignment operator. When the loops ends, the variable is divided by 25 with another compound assignment operator (/=) to get the trend line’s average price value. This value is then outputted with Output.WriteLine().

For more PriceValue() examples, see getting future values of a trend line, extending a trend line to its past and future values, and colouring price bars above or below a trend line. Articles that discuss other ways to work with a trend line’s reference variable are relocating a trend line and changing a line’s visual appearance.

Summary

Trend lines are drawn by the DrwTrendLine.Create() method, which returns a reference to the line created. When stored in an ITrendLineObject variable, the trend line’s properties and methods are accessible through that variable. One of those methods is PriceValue(), which returns the line’s price value for any DateTime value on the chart.

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_TrendLineValue : IndicatorObject
    {
        public Example_TrendLineValue(object _ctx) : base(_ctx) { }

        private ITrendLineObject trendLine;

        protected override void StartCalc()
        {
            trendLine = null;
        }

        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart && trendLine == null)
            {
                // Create the trend line
                trendLine = DrwTrendLine.Create(
                    new ChartPoint(Bars.Time[24], Bars.Close[24]),
                    new ChartPoint(Bars.Time[0], Bars.Close[0])
                    );

                trendLine.Size  = 2;
                trendLine.Color = Color.LimeGreen;

                // Get trend line values for the historical bars
                double avgLineValue = 0.0;

                for (int i = 24; i >= 0; i--)
                {
                    Output.WriteLine("Bar time: {0}, line value: {1}",
                        Bars.Time[i].ToString("HH:mm"),
                        trendLine.PriceValue(Bars.Time[i]));

                    avgLineValue += trendLine.PriceValue(Bars.Time[i]);
                }

                avgLineValue /= 25;

                Output.WriteLine("Average trend line value: {0}",
                    avgLineValue);
            }

            //> Bar time: 20:00, line value: 3591
            //> Bar time: 20:05, line value: 3591,375
            //> Bar time: 20:10, line value: 3591,75
            //> Bar time: 20:15, line value: 3592,125
            //> Bar time: 20:20, line value: 3592,5
            //> Bar time: 20:25, line value: 3592,875
            //> Bar time: 20:30, line value: 3593,25
            //> Bar time: 20:35, line value: 3593,625
            //> Bar time: 20:40, line value: 3594
            //> Bar time: 20:45, line value: 3594,375
            //> Bar time: 20:50, line value: 3594,75
            //> Bar time: 20:55, line value: 3595,125
            //> Bar time: 21:00, line value: 3595,5
            //> Bar time: 21:05, line value: 3595,875
            //> Bar time: 21:10, line value: 3596,25
            //> Bar time: 21:15, line value: 3596,625
            //> Bar time: 21:20, line value: 3597
            //> Bar time: 21:25, line value: 3597,375
            //> Bar time: 21:30, line value: 3597,75
            //> Bar time: 21:35, line value: 3598,125
            //> Bar time: 21:40, line value: 3598,5
            //> Bar time: 21:45, line value: 3598,875
            //> Bar time: 21:50, line value: 3599,25
            //> Bar time: 21:55, line value: 3599,625
            //> Bar time: 22:00, line value: 3600
            //> Average trend line value: 3595,5
        }
    }
}

References

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

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

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