Trend lines can highlight an opening range’s high and low and can connect pivot swing points. But how do we make a triangle that has its tip attached to the recent high?

Drawing a price-based triangle with MultiCharts .NET trend lines

Trend lines in MultiCharts .NET are made with the DrwTrendLine.Create() method, which requires at least two ChartPoint structs that specify the line’s begin and end point (see PowerLanguage .NET Help, n.d.). This method returns a reference (MultiCharts, 2014), that, when stored in an ITrendLineObject variable, provides access to the trend line’s properties and methods. With those we can work with the trend line, like relocating, changing its appearance, or removing the line.

To create a triangle in MultiCharts .NET we need to draw three trend lines between as many points (A, B, and C):

Example of triangle

We’ll define these three locations in the example with ChartPoint struct variables that hold the chart point’s price and time coordinates.

When drawing a trend line or updating a line’s location, it’s important to know whether the line is already drawn or not. That’s because, when the line exists, we can update its location. But if it doesn’t exist, we first need to draw it. One way to do this is assigning the value returned by DrwTrendLine.Create() to an ITrendLineObject interface variable.

We can then check if that variable holds a reference to a trend line or not. The default, empty value for reference variables (which ITrendLineObject variables are also) is null (Sempf, Sphar, & Davis, 2010), which means the variable doesn’t refer to an object in memory (Sharp, 2013). For trend lines, this means that when an ITrendLineObject variable equals null, it isn’t connected with a trend line object on the chart. So either we didn’t draw the trend line yet or we forgot to assign the value returned by DrwTrendLine.Create() to this variable. And when a trend line variable is different than null, we know it’s associated with a trend line and can then access the trend line’s properties to change its location. Let’s consider the programming example to see how.

Example: drawing a triangle on a forex chart in MultiCharts .NET

With the example indicator applied to an EUR/CAD chart, it draws the following triangle with point B (see previous image) set to the recent high:

Drawing a triangle with MultiCharts .NET trend lines - 1

When new bars are formed, the triangle is updated on the close of each bar and develops as follows:

Drawing a triangle with MultiCharts .NET trend lines - 2 Drawing a triangle with MultiCharts .NET trend lines - 3

Programmatically creating triangles in MultiCharts .NET

The programming code looks as follows:

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

    private ITrendLineObject lineAtoB, lineAtoC, lineBtoC;

    protected override void CalcBar()
    {
        if (Bars.LastBarOnChart)
        {
            DrawTriangle();
        }
    }

    private void DrawTriangle()
    {
        // Define the triangle's points
        ChartPoint pointA = new ChartPoint(
            Bars.Time[30], Bars.Close[30]);

        ChartPoint pointB = new ChartPoint(
            Bars.Time[Bars.High.HighestBar(20)], 
            Bars.High.Highest(20));

        ChartPoint pointC = new ChartPoint(
            Bars.Time[0], Bars.Close[0]);

        // Create or relocate the line between A and B
        if (lineAtoB == null)
        {
            lineAtoB = DrwTrendLine.Create(pointA, pointB);
        }
        else
        {
            lineAtoB.End   = pointB;
            lineAtoB.Begin = pointA;
        }

        // Create or relocate the line between B and C
        if (lineBtoC == null)
        {
            lineBtoC = DrwTrendLine.Create(pointB, pointC);
        }
        else
        {
            lineBtoC.End   = pointC;
            lineBtoC.Begin = pointB;
        }

        // Create or relocate the line between A and C
        if (lineAtoC == null)
        {
            lineAtoC = DrwTrendLine.Create(pointA, pointC);
        }
        else
        {
            lineAtoC.End   = pointC;
            lineAtoC.Begin = pointA;
        }

        // Adjust the appearance of the lines
        lineAtoB.Color = Color.Red;
        lineBtoC.Color = Color.YellowGreen;
        lineAtoC.Color = Color.Orange;

        lineAtoB.Size = 3;
        lineBtoC.Size = 3;
        lineAtoC.Size = 3;
    }
}

We start with defining two MultiCharts .NET class attributes. With SameAsSymbol set to true the indicator is displayed on the data series and not in a separate subchart. And UpdateOnEveryTick set to false will calculate the indicator on bar close only and not with every real-time tick. That way the triangle will not be moved with every price update, which can give a ‘flashing’ effect.

We then declare three ITrendLineObject variables: lineAtoB, lineAtoC, and lineBtoC. These will hold the references to the trend lines we’re going to make. Without these variables, we wouldn’t be able to easily access the trend lines to change their appearance or location.

Next in the example is the CalcBar() method. This method contains an if statement that verifies if the Bars.LastBarOnChart property is true, which it is when the current bar is the last (PowerLanguage .NET Help, n.d.). When that’s the case, the DrawTriangle() method is called to create or update the triangle.

Creating a triangle in MultiCharts .NET

The DrawTriangle() method starts with creating three ChartPoint struct variables. The first (pointA) is set to the time and close of 30 bars ago (Bars.Time[30] and Bars.Close[30], respectively). Another point (pointC) is set to the current bar’s time (Bars.Time[0]) and close (Bars.Close[0]).

The second triangle point (pointB) is set to the highest high of the last 20 bars. That price is retrieved with the Bars.High.Highest(20) method. To fetch that bar’s time, we use Bars.Time and place within its square brackets ([ and ]) the Bars.High.HighestBar(20) method, which returns how many bars ago the highest high of the last 20 bars occurred.

Now that we have the triangle’s coordinates defined, three similar if/else statements evaluate each trend line variable. The first checks if lineAtoB equals (==) null. When it does, this variable’s trend line hasn’t been created, and so we call the DrwTrendLine.Create() method to draw the trend line. Inside this method we pass the pointA and pointB ChartPoint variables to define the line’s begin and end point, respectively. We assign the value returned by DrwTrendLine.Create() to the lineAtoB so that this variable can be used to access the trend line later on.

Updating the triangle’s location

The else part of this first if/else statement deals with the situation in which the lineAtoB variable is unequal to (!=) null. In that case the trend line is already on the chart, and so we’ll relocate it. To adjust a trend line’s location we need to assign a ChartPoint struct value to the line’s Begin and End properties (see PowerLanguage .NET Help, n.d.), with the End property updated before the Begin property is changed (Henry MultiCharts, 2014). And so we update the line’s location by setting its End property to the pointB ChartPoint value and its Begin property to the pointA chart location.

The two subsequent if/else statements are highly similar to the first and make or relocate the lines between point B and C and point A and C. Once all three lines have been created or updated, we use the three trend line variables to change the lines’ visual appearance. We do that by assigning new values to their Color and Size properties.

To learn more about using trend lines to highlight price action, see drawing trend lines between pivot swings and highlighting an instrument’s opening range with trend lines. There’s also an example that draws rectangles around price action.

Summary

Trend lines are made with the DrwTrendLine.Create() method, which returns a reference to the line made. When that reference is assigned to an ITrendLineObject variable, we can use that variable to check if the line is on the chart. When this variable is null, it hasn’t been associated with a trend line object yet; otherwise, it refers to a trend line object on the chart. Drawing a triangle requires three trend lines with as many ChartPoint struct values. Updating a line’s location is done by first assigning its End and then its Begin property to different values.

Complete MultiCharts .NET indicator example

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

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

        private ITrendLineObject lineAtoB, lineAtoC, lineBtoC;

        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart)
            {
                DrawTriangle();
            }
        }

        private void DrawTriangle()
        {
            // Define the triangle's points
            ChartPoint pointA = new ChartPoint(
                Bars.Time[30], Bars.Close[30]);

            ChartPoint pointB = new ChartPoint(
                Bars.Time[Bars.High.HighestBar(20)], 
                Bars.High.Highest(20));

            ChartPoint pointC = new ChartPoint(
                Bars.Time[0], Bars.Close[0]);

            // Create or relocate the line between A and B
            if (lineAtoB == null)
            {
                lineAtoB = DrwTrendLine.Create(pointA, pointB);
            }
            else
            {
                lineAtoB.End   = pointB;
                lineAtoB.Begin = pointA;
            }

            // Create or relocate the line between B and C
            if (lineBtoC == null)
            {
                lineBtoC = DrwTrendLine.Create(pointB, pointC);
            }
            else
            {
                lineBtoC.End   = pointC;
                lineBtoC.Begin = pointB;
            }

            // Create or relocate the line between A and C
            if (lineAtoC == null)
            {
                lineAtoC = DrwTrendLine.Create(pointA, pointC);
            }
            else
            {
                lineAtoC.End   = pointC;
                lineAtoC.Begin = pointA;
            }

            // Adjust the appearance of the lines
            lineAtoB.Color = Color.Red;
            lineBtoC.Color = Color.YellowGreen;
            lineAtoC.Color = Color.Orange;

            lineAtoB.Size = 3;
            lineBtoC.Size = 3;
            lineAtoC.Size = 3;
        }
    }
}

References

Henry MultiCharts (2014, September 15). Simple drawing – forum discussion. Retrieved on March 20, 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.