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:

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



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

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; } } }
To learn more about C# programming, checkout Kodify's C# tutorials.
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
Visit programming tutorials for more helpful coding articles.