In MultiCharts .NET we can draw trend lines on price data and draw trend lines with mouse clicks. But how do we draw trend lines automatically between the recent highs and lows?

Drawing trend lines between recent highs and lows in MultiCharts .NET

The DrwTrendLine.Create() method draws trend lines and returns a reference to the trend line just created (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). With that reference assigned to an ITrendLineObject variable, the line’s properties and methods are accessible through that variable. And so we can do things like changing a line’s location or adjusting its visual appearance.

For drawing a trend line between recent highs and lows, we first need to figure out on which price bars those highs and lows occurred. One way to do that is with the built-in PivotHighVS and PivotLowVS functions, which return -1 by default or the price of a swing high or low otherwise. Since swing points can only be determined once the price has moved away from that point, they do introduce a small lag.

Examples: MultiCharts .NET trend lines between pivot points

Let’s look at what the example does before examining its code. The indicator draws an extended trend line between two recent pivot high and low points. To show the point through which the line is drawn, I’ve also added the ‘Pivot_High’ (blue dots) and ‘Pivot_Low’ (green dots) indicators to the chart:

Trend lines between swing pivots - 1

The trend lines are moved with each new swing high or low point. The Euro Bund chart that’s displayed above continued as follows:

Trend lines between swing pivots - 2 MultiCharts .NET trend lines between pivots MultiCharts .NET trend lines between swing pivots

Without the additional ‘Pivot_High’ and ‘Pivot_Low’ indicators, the example indicator looks like this when applied to an EUR/USD chart:

MultiCharts .NET trend lines between swing points example

Drawing MultiCharts .NET trend lines between pivot points

The programming code for this script is the following:

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

    private ITrendLineObject pivotHighLine, pivotLowLine;
    private int barNumPivotHigh, barNumPivotLow;
    private PivotHighVS pivotHigh;
    private PivotLowVS pivotLow;

    protected override void Create()
    {
        pivotHigh = new PivotHighVS(this);
        pivotLow  = new PivotLowVS(this);
    }

    protected override void StartCalc()
    {
        // Specify function settings
        pivotHigh.instance      = 1;
        pivotHigh.price         = Bars.High;
        pivotHigh.leftstrength  = 3;
        pivotHigh.rightstrength = 3;
        pivotHigh.length        = 4;

        pivotLow.instance      = 1;
        pivotLow.price         = Bars.Low;
        pivotLow.leftstrength  = 3;
        pivotLow.rightstrength = 3;
        pivotLow.length        = 4;

        // Reset variables
        barNumPivotHigh = 0;
        barNumPivotLow  = 0;

        pivotHighLine = null;
        pivotLowLine  = null;
    }

    protected override void CalcBar()
    {
        // Draw the trend line for the pivot high
        if ((pivotHigh[0] != -1) && (barNumPivotHigh != 0))
        {
            int barsAgo = Bars.CurrentBar - barNumPivotHigh;

            ChartPoint beginPoint = new ChartPoint(
                Bars.Time[barsAgo], 
                pivotHigh[barsAgo - 3]);

            ChartPoint endPoint = new ChartPoint(
                Bars.Time[3], pivotHigh[0]);

            // Create trend line or change its location
            if (pivotHighLine == null)
            {
                pivotHighLine = DrwTrendLine.Create(
                    beginPoint, endPoint);
            }
            else
            {
                pivotHighLine.End   = endPoint;
                pivotHighLine.Begin = beginPoint;
            }

            // Format trend line
            pivotHighLine.Color    = Color.ForestGreen;
            pivotHighLine.Size     = 1;
            pivotHighLine.ExtRight = true;
        }

        // Similarly as with pivot high, but now for the pivot low line
        if ((pivotLow[0] != -1) && (barNumPivotLow != 0))
        {
            int barsAgo = Bars.CurrentBar - barNumPivotLow;

            ChartPoint beginPoint = new ChartPoint(
                Bars.Time[barsAgo],
                pivotLow[barsAgo - 3]);

            ChartPoint endPoint = new ChartPoint(
                Bars.Time[3], pivotLow[0]);

            // Create trend line or update its location
            if (pivotLowLine == null)
            {
                pivotLowLine = DrwTrendLine.Create(
                    beginPoint, endPoint);
            }
            else
            {
                pivotLowLine.End   = endPoint;
                pivotLowLine.Begin = beginPoint;
            }

            // Change trend line's visual appearance
            pivotLowLine.Color    = Color.Red;
            pivotLowLine.Size     = 1;
            pivotLowLine.ExtRight = true;
        }

        // Update the bar numbers of the current pivot
        // high or low. Used for determining previous pivot.
        if (pivotHigh[0] != -1)
            barNumPivotHigh = Bars.CurrentBar - 3;

        if (pivotLow[0] != -1)
            barNumPivotLow = Bars.CurrentBar - 3;
    }
}

We start with setting two attributes. UpdateOnEveryTick set to false makes the indicator calculate on bar close only. That attribute is added here since the pivots lag price action so there’s little to gain from tick-by-tick calculations. Setting SameAsSymbol to true displays the indicator on the data series instead of a separate subchart.

Declaring variables and specifying functions

Then we declare two ITrendLineObject variables (pivotHighLine and pivotLowLine) which we use to change the trend lines later on. The integer variables barNumPivotHigh and barNumPivotLow will hold the bar number from the previous swing point (needed for determining the line’s coordinates). And the PivotHighVS and PivotLowVS instances will calculate the pivot points for us. They’re named pivotHigh and pivotLow and created in the subsequent Create() method.

In the StartCalc() method we set the options of the pivotHigh and pivotLow functions. These include the price on which they’re calculated (Bars.High and Bars.Low, respectively), and their leftstrength and rightstrength that set how many bars before and after a recent high or low this point is see as a pivot swing level.

We also set barNumPivotHigh and barNumPivotLow to their default value of zero and set pivotHighLine and pivotLowLine to null. This latter value means these reference variables don’t point to an object (Albahari & Albahari, 2012), which in this context means these trend line variables aren’t associate with a trend line object on the chart. By resetting these variables in StartCalc() they’re set to their default values each time the script is fully (re)calculated.

Drawing trend lines on pivot points programmatically

Next is the CalcBar() method. While it looks like there’s a lot of code in it, the line between the pivot highs is created in practically the same way as the one between the pivot lows. So in discussing the example we focus on the trend line between the recent highs.

CalcBar() starts with an if statement that evaluates two conditions. The first is whether the current pivot high value (pivotHigh[0]) is unequal to (!=) -1, which happens when a new pivot high has occurred. The second condition is whether the previous pivot’s bar number (barNumPivotHigh) is unequal to zero. This way we only draw a trend line when we actually have two points to connect.

When both conditions evaluate to true, the if statement’s code first determines how many bars ago the previous pivot happened. For that we subtract the bar number of the previous pivot (barNumPivotHigh) from the current bar number (Bars.CurrentBar), and store that computed value in the barsAgo variable.

Then two ChartPoint struct variables (beginPoint and endPoint) are made. The first is set to the time (Bars.Time[barsAgo]) and price of the previous pivot. The pivot high function is used to retrieve that price with pivotHigh[barsAgo - 3], whereby the minus 3 corrects for the pivot function’s lag of three bars we specified in StartCalc().

The second chart coordinate (endPoint) is set to the time of the pivot high (which lags three bars, so Bars.Time[3]) and the current pivot high value (pivotHigh[0]). Together both ChartPoint variables hold the location of the previous and current swing high.

Drawing a trend line between pivot points

With the chart coordinates defined it’s time to create or relocate the trend line. An if/else statement first checks whether the pivotHighLine interface variable is null, which it is when it isn’t associated with a trend line object (see Albahari & Albahari, 2012). In that case we first need to create a trend line; otherwise, the existing trend line can be adjusted.

With no trend line on the chart, we create one with the DrwTrendLine.Create() method in which we pass the beginPoint and endPoint coordinates. By storing this method’s returned value in the pivotHighLine variable the trend line can be accessed later on in order to change it. This also makes the trend line variable different from null.

When a trend line is already there on the chart (the else portion of the if statement), we change the trend line’s location by setting its End property to the endPoint chart coordinate and its Begin property to beginPoint.

Changing the trend line and creating another one

The trend line’s visual appearance is then changed by setting its Color property to green and its Size property with 1 a bit bigger than the default 0. Setting the ExtRight property to true extends the trend line to the right, causing it to continue endlessly into the future.

The second if statement in the CalcBar() method creates or relocates the trend line between two recent pivot swing lows. This is done in the same way as the trend line between the recent highs.

The very last part of the example are two if statements. These store the current bar number (Bars.CurrentBar) minus 3 (to account for the lag of the pivot functions) when either the current pivot high (pivotHigh[0]) or pivot low (pivotLow[0]) value is unequal to -1, which happens when a new pivot high or pivot low has occurred, respectively. This way, when the next pivot happens, these variables hold the bar number of the previous pivot high or low.

Other MultiCharts .NET examples of trend lines and price action are highlighting an instrument’s opening range with trend lines. An instrument’s price action can also be accentuated with boxes around price movements and a triangle anchored on the recent high.

Summary

The DrwTrendLine.Create() method draws trend lines between two ChartPoint chart coordinates. With the PivotHighVS and PivotLowVS functions we can calculate pivot swing highs and lows, and then use these points to draw a trend line between.

Complete MultiCharts .NET indicator example

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

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

        private ITrendLineObject pivotHighLine, pivotLowLine;
        private int barNumPivotHigh, barNumPivotLow;
        private PivotHighVS pivotHigh;
        private PivotLowVS pivotLow;

        protected override void Create()
        {
            pivotHigh = new PivotHighVS(this);
            pivotLow  = new PivotLowVS(this);
        }

        protected override void StartCalc()
        {
            // Specify function settings
            pivotHigh.instance      = 1;
            pivotHigh.price         = Bars.High;
            pivotHigh.leftstrength  = 3;
            pivotHigh.rightstrength = 3;
            pivotHigh.length        = 4;

            pivotLow.instance      = 1;
            pivotLow.price         = Bars.Low;
            pivotLow.leftstrength  = 3;
            pivotLow.rightstrength = 3;
            pivotLow.length        = 4;

            // Reset variables
            barNumPivotHigh = 0;
            barNumPivotLow  = 0;

            pivotHighLine = null;
            pivotLowLine  = null;
        }

        protected override void CalcBar()
        {
            // Draw the trend line for the pivot high
            if ((pivotHigh[0] != -1) && (barNumPivotHigh != 0))
            {
                int barsAgo = Bars.CurrentBar - barNumPivotHigh;

                ChartPoint beginPoint = new ChartPoint(
                    Bars.Time[barsAgo], 
                    pivotHigh[barsAgo - 3]);

                ChartPoint endPoint = new ChartPoint(
                    Bars.Time[3], pivotHigh[0]);

                // Create trend line or change its location
                if (pivotHighLine == null)
                {
                    pivotHighLine = DrwTrendLine.Create(
                        beginPoint, endPoint);
                }
                else
                {
                    pivotHighLine.End   = endPoint;
                    pivotHighLine.Begin = beginPoint;
                }

                // Format trend line
                pivotHighLine.Color    = Color.ForestGreen;
                pivotHighLine.Size     = 1;
                pivotHighLine.ExtRight = true;
            }

            // Similarly as with pivot high, but now for the pivot low line
            if ((pivotLow[0] != -1) && (barNumPivotLow != 0))
            {
                int barsAgo = Bars.CurrentBar - barNumPivotLow;

                ChartPoint beginPoint = new ChartPoint(
                    Bars.Time[barsAgo],
                    pivotLow[barsAgo - 3]);

                ChartPoint endPoint = new ChartPoint(
                    Bars.Time[3], pivotLow[0]);

                // Create trend line or update its location
                if (pivotLowLine == null)
                {
                    pivotLowLine = DrwTrendLine.Create(
                        beginPoint, endPoint);
                }
                else
                {
                    pivotLowLine.End   = endPoint;
                    pivotLowLine.Begin = beginPoint;
                }

                // Change trend line's visual appearance
                pivotLowLine.Color    = Color.Red;
                pivotLowLine.Size     = 1;
                pivotLowLine.ExtRight = true;
            }

            // Update the bar numbers of the current pivot
            // high or low. Used for determining previous pivot.
            if (pivotHigh[0] != -1)
                barNumPivotHigh = Bars.CurrentBar - 3;

            if (pivotLow[0] != -1)
                barNumPivotLow = Bars.CurrentBar - 3;
        }
    }
}

References

Albahari, J. & Albahari, B. (2012). C# 5.0 in a Nutshell: The Definitive Reference (5th edition). 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