By extending a trend line we can make horizontal and vertical trend lines. But how do we create vertical trend lines that continue in the indicator’s subchart?

Drawing vertical price and indicator lines in MultiCharts .NET

The DrwTrendLine.Create() method draws trend lines and returns a reference to the line made (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). When this reference is assigned to an ITrendLineObject variable, we can access the line’s properties and methods through that variable. That way we can change the trend line after it has been made.

Trend lines are drawn between two chart coordinates, which are specified with ChartPoint structs that hold the coordinates’ time and price values (PowerLanguage .NET Help, n.d.). Vertical trend lines have chart locations with the same DateTime value but different price values. For a vertical trend line that continues to the chart’s top and bottom we set the line’s ExtLeft and ExtRight properties to true so that it extends in both directions (MultiCharts, 2014).

But a trend line cannot be extended from the price chart onto the indicator’s subchart (or vice versa). A workaround for this is drawing two trend lines: one on price data and the other line on the indicator’s subchart. That requires an overloaded version of DrwTrendLine.Create() with three arguments: two ChartPoint struct values for the line’s begin and end point and a Boolean that causes the line to be drawn on the subchart (when true) or price chart (false) (PowerLanguage .NET Help, n.d.). Let’s examine the programming example to see how to do this.

Example: extended vertical trend lines in MultiCharts .NET

The example script draws three vertical trend lines on both the price chart as well as the indicator’s subchart. For example when added to an Euro Bund future chart:

MultiCharts .NET trend line extended to subchart - 1

These extended trend lines continue indefinitely beyond the visible chart area. We can see that by changing the chart’s and subchart’s price axis:

MultiCharts .NET trend line extended to subchart - 2

Programmatically drawing vertical lines that extend to the subchart

The indicator’s programming code is the following:

[UpdateOnEveryTick(false)]
public class Example_VerticalTrendLineSubchart : IndicatorObject
{
    public Example_VerticalTrendLineSubchart(object _ctx) : base(_ctx) { }

    private XAverage ema;
    private VariableSeries<double> emaValues;
    private IPlotObject emaPlot;
    private bool linesAlreadyDrawn;

    protected override void Create()
    {
        emaPlot = AddPlot(new PlotAttributes("EMA", 
            EPlotShapes.Line, Color.Red));

        ema       = new XAverage(this);
        emaValues = new VariableSeries<double>(this);
    }

    protected override void StartCalc()
    {
        // Specify the EMA settings
        ema.Price  = Bars.Close;
        ema.Length = 7;

        linesAlreadyDrawn = false;
    }

    protected override void CalcBar()
    {
        emaValues.Value = ema[0];

        emaPlot.Set(emaValues[0]);

        if (Bars.LastBarOnChart && !linesAlreadyDrawn)
        {
            // Draw the vertical trend lines
            DrawVerticalLine(5, Color.DarkMagenta);

            DrawVerticalLine(15, Color.Red);

            DrawVerticalLine(25, Color.LimeGreen);

            linesAlreadyDrawn = true;
        }
    }

    private void DrawVerticalLine(int barsBack, Color lineColour)
    {
        DateTime timeOfBar = Bars.Time[barsBack];

        // Draw the vertical line on the price chart
        ChartPoint priceBegin = new ChartPoint(
            timeOfBar, Bars.High[barsBack]);

        ChartPoint priceEnd = new ChartPoint(
            timeOfBar, Bars.Low[barsBack]);

        ITrendLineObject priceTrendLine =
            DrwTrendLine.Create(priceBegin, priceEnd, false);

        // Draw the vertical line on the indicator's subchart
        ChartPoint emaBegin = new ChartPoint(
            timeOfBar, emaValues[barsBack] * 1.01);

        ChartPoint emaEnd = new ChartPoint(
            timeOfBar, emaValues[barsBack] * 0.99);

        ITrendLineObject emaTrendLine = 
            DrwTrendLine.Create(emaBegin, emaEnd, true);

        // Adjust the lines' appearance
        emaTrendLine.ExtLeft  = true;
        emaTrendLine.ExtRight = true;
        emaTrendLine.Size     = 2;
        emaTrendLine.Color    = lineColour;

        priceTrendLine.ExtLeft  = true;
        priceTrendLine.ExtRight = true;
        priceTrendLine.Size     = emaTrendLine.Size;
        priceTrendLine.Color    = lineColour;
    }
}

The example begins with setting the UpdateOnEveryTick attribute to false so that the indicator is calculated on bar close only. Because we only draw the trend lines once, the script doesn’t need to calculate on every tick.

Declaring and setting the plot and EMA function

We then declare a XAverage function variable named ema that’s used to calculate the EMA values. The values it computes will be stored in a variable series consisting out of double variables, which we declare here with the emaValues name. To plot those EMA values in the indicator’s subchart we create an IPlotObject variable named emaPlot. The last variable we declare in the top of this indicator’s class is the linesAlreadyDrawn variable; a Boolean that’s used to prevent the lines from being drawn repeatedly.

In the Create() method we use AddPlot() to create a plot that’s set to a red line named “EMA”. Instances of the EMA function (XAverage) and the variable series that holds the EMA values (VariableSeries<double>) are also created here.

Then in the StartCalc() method we specify the EMA function settings: the data on which it’s calculated is set to the close of each bar (Bars.Close) and its length is set to 7. We also assign linesAlreadyDrawn a value of false here so that this variable is reset at the start of each script calculation. That ensures the trend lines are redrawn each time the script fully calculates again.

Setting the EMA plot values and calling DrawVerticalLine()

Next is the CalcBar() method. In it we set the variable series’ current value (emaValues.Value) to the value calculated by the EMA function for that bar (ema[0]). By doing this on every bar the emaValues variable series will hold the values of previous bars over time. To create the EMA line (emaPlot), we use its Set() method to set its value to the variable series’ current value (emaValues[0]).

An if statement then checks two conditions. First, whether the current bar is the last, which is the case when Bars.LastBarOnChart returns true (see PowerLanguage .NET Help, n.d.). Second, if linesAlreadyDrawn is false, which we check with the logical not operator (!). This operator returns true when the expression it precedes is false and vice versa (Liberty & MacDonald, 2009).

When both conditions are true we call the DrawVerticalLine() method. This method accepts two arguments: an integer specifying the number of bars ago to draw the line and a Color value that sets the trend line’s colour. We call DrawVerticalLine() three times to create a magenta line 5 bars ago, a red line 15 bars ago, and 25 bars ago a lime green vertical trend line.

Then we set the linesAlreadyDrawn variable to true. Because that invalidates the preceding if statement, that if statement’s code block is only executed once and so each vertical trend line is only drawn once. This also clarifies why we reset linesAlreadyDrawn in StartCalc(); otherwise, the if statement code block is not executed again when the script recalculates after it’s already added to the chart (since linesAlreadyDrawn is false after calculating the script the first time).

Drawing a vertical trend line on the price chart

The vertical trend lines are drawn in the DrawVerticalLine() method. This method has two parameters: the barsBack integer that sets how many bars ago to draw the line and the lineColour Color value for the line’s colour.

For convenience, we first put the time of the bar that the line is drawn on (Bars.Time[barsBack]) in the timeOfBar variable. Then we create two ChartPoint struct variables (priceBegin and priceEnd) to define the chart coordinates for the vertical line on the price chart. Their price value is set to the high and low of barsBack ago (Bars.High[barsBack] and Bars.Low[barsBack]) while both have their DateTime value set to the timeOfBar value.

With the ChartPoint values defined, we call the DrwTrendLine.Create() method and pass in the priceBegin and priceEnd variables to draw a trend line between them. The third argument we provide is the Boolean false value to specify that the line shouldn’t be drawn on the indicator’s subchart (PowerLanguage .NET Help, n.d.).

The value returned by DrwTrendLine.Create() is assigned to the priceTrendLine variable of type ITrendLineObject. We can then use that variable to access the line’s properties and methods.

Drawing a vertical trend line on the indicator’s subchart

The next part of DrawVerticalLine() draws a vertical trend line in the indicator’s subchart. First we create two ChartPoint variables (emaBegin and emaEnd) with the coordinates that the line is drawn between. As we did with the trend line on the price chart, both have their DateTime value set to the timeOfBar variable.

But instead of price bar data we define these ChartPoint variables with historical EMA values retrieved with emaValues[barsBack]. For emaBegin we multiply the EMA value with 1.01 and for emaEnd with 0.99. With these slightly different EMA price coordinates we’re able to draw a vertical trend line between them.

We do that by calling the DrwTrendLine.Create() method and pass in the emaBegin and emaEnd variables alongside a Boolean true value to draw the trend line in the indicator’s subchart (see PowerLanguage .NET Help, n.d.). With this method’s returned value assigned to the emaTrendLine variable we can adjust this line later on.

Changing the vertical lines’ visual appearance

In the last part of DrawVerticalLine() we extend both trend lines beyond the chart’s top and bottom by setting their ExtLeft and ExtRight properties to true. And so the initially small vertical trend lines are extended indefinitely in both directions (see MultiCharts, 2014).

The trend lines’ visual appearance is then changed by adjusting their Size and Color properties. The lines’ Color is set to the method’s lineColour parameter, while their Size is set to 2. For this latter we first set the emaTrendLine line’s Size property to 2 and then use that trend line’s property (emaTrendLine.Size) when setting the size of the priceTrendLine line.

See drawing a price line and creating an indicator line to learn more about drawing trend lines in an indicator’s subchart. Other applications of a line’s ExtLeft and ExtRight properties are creating horizontal trend lines and drawing vertical trend lines.

Summary

The DrwTrendLine.Create() method creates trend lines. One version of this method accepts two ChartPoint struct arguments (for the line’s begin and end point) and a Boolean variable: false draws on the price chart, true creates the line in the indicator’s subchart. Drawing a vertical trend line requires two ChartPoint structs with the same DateTime value but different price values. Assigning DrwTrendLine.Create()’s returned value to an ITrendLineObject variable allows us to access the line’s properties and methods with that variable. We can extend a vertical trend line to the chart’s top and bottom by setting the line’s ExtLeft and ExtRight properties to true.

Complete MultiCharts .NET indicator example

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

namespace PowerLanguage.Indicator
{
    [UpdateOnEveryTick(false)]
    public class Example_VerticalTrendLineSubchart : IndicatorObject
    {
        public Example_VerticalTrendLineSubchart(object _ctx) : base(_ctx) { }

        private XAverage ema;
        private VariableSeries<double> emaValues;
        private IPlotObject emaPlot;
        private bool linesAlreadyDrawn;

        protected override void Create()
        {
            emaPlot = AddPlot(new PlotAttributes("EMA", 
                EPlotShapes.Line, Color.Red));

            ema       = new XAverage(this);
            emaValues = new VariableSeries<double>(this);
        }

        protected override void StartCalc()
        {
            // Specify the EMA settings
            ema.Price  = Bars.Close;
            ema.Length = 7;

            linesAlreadyDrawn = false;
        }

        protected override void CalcBar()
        {
            emaValues.Value = ema[0];

            emaPlot.Set(emaValues[0]);

            if (Bars.LastBarOnChart && !linesAlreadyDrawn)
            {
                // Draw the vertical trend lines
                DrawVerticalLine(5, Color.DarkMagenta);

                DrawVerticalLine(15, Color.Red);

                DrawVerticalLine(25, Color.LimeGreen);

                linesAlreadyDrawn = true;
            }
        }

        private void DrawVerticalLine(int barsBack, Color lineColour)
        {
            DateTime timeOfBar = Bars.Time[barsBack];

            // Draw the vertical line on the price chart
            ChartPoint priceBegin = new ChartPoint(
                timeOfBar, Bars.High[barsBack]);

            ChartPoint priceEnd = new ChartPoint(
                timeOfBar, Bars.Low[barsBack]);

            ITrendLineObject priceTrendLine =
                DrwTrendLine.Create(priceBegin, priceEnd, false);

            // Draw the vertical line on the indicator's subchart
            ChartPoint emaBegin = new ChartPoint(
                timeOfBar, emaValues[barsBack] * 1.01);

            ChartPoint emaEnd = new ChartPoint(
                timeOfBar, emaValues[barsBack] * 0.99);

            ITrendLineObject emaTrendLine = 
                DrwTrendLine.Create(emaBegin, emaEnd, true);

            // Adjust the lines' appearance
            emaTrendLine.ExtLeft  = true;
            emaTrendLine.ExtRight = true;
            emaTrendLine.Size     = 2;
            emaTrendLine.Color    = lineColour;

            priceTrendLine.ExtLeft  = true;
            priceTrendLine.ExtRight = true;
            priceTrendLine.Size     = emaTrendLine.Size;
            priceTrendLine.Color    = lineColour;
        }
    }
}

References

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. 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