Search Framework:
LineUtils
Namespace: WealthLab.Core
Parent:

LineUtils is a static utility class containing methods for projecting trendlines and constructing parallel, channel, and triangle trendlines.

Methods
ExtendLine
public static double ExtendLine(double x1, double y1, double x2, double y2, double x)
public static double ExtendLine(PeakTrough peakTrough1, PeakTrough peakTrough2, double x)
public static double ExtendLine(TrendLine trendline, double x)

Returns the y-axis value of a linear line projected to the x-axis position specified in x. The line can be defined by two x/y coordinates, two PeakTrough instances, or a TrendLine. The x value will typically represent a bar index. The PeakTrough overload returns Double.NaN if either PeakTrough is null or if both have the same XIndex.


ExtendLineLog
public static double ExtendLineLog(double x1, double y1, double x2, double y2, double x)
public static double ExtendLineLog(PeakTrough peakTrough1, PeakTrough peakTrough2, double x)
public static double ExtendLineLog(TrendLine trendline, double x)

Returns the y-axis value of a logarithmic line projected to the x-axis position specified in x. The line can be defined by two x/y coordinates, two PeakTrough instances, or a TrendLine. The x value will typically represent a bar index. The PeakTrough overload returns Double.NaN if either PeakTrough is null or if both have the same XIndex.


ExtendLineY
public static double ExtendLineY(double x1, double y1, double x2, double y2, double x, bool useLog = false)
public static double ExtendLineY(PeakTrough peakTrough1, PeakTrough peakTrough2, double x, bool useLog = false)
public static double ExtendLineY(TrendLine trendline, double x, bool useLog = false)

A convenience method that projects a line to the x-axis position specified in x. If useLog is false, the method uses ExtendLine. If useLog is true, it uses ExtendLineLog.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
namespace WealthScript123
{
	public class GetTroughExample : UserStrategyBase
	{
		PeakTroughCalculator _ptc;
		public override void Initialize(BarHistory bars)
		{
			double swingPct = 8.0;
			//calculate peaks and troughs
			_ptc = new PeakTroughCalculator(
				bars,
				swingPct,
				PeakTroughReversalType.Percent);
			int bar = bars.Count - 1;
			PeakTrough peak1 = _ptc.GetPeak(bar);
			if (peak1 != null)
			{
				DrawDot(peak1.XIndex, peak1.Value, WLColor.Cyan, 6);
				PeakTrough peak2 = _ptc.GetPeak(peak1.XIndex);
				if (peak2 != null)
				{
					DrawDot(peak2.XIndex, peak2.Value, WLColor.Cyan, 6);
					//extend the line created by the two peaks
					//to the last bar
					double y = LineUtils.ExtendLineY(peak1, peak2, bar);
					DrawLine(
						peak2.XIndex,
						peak2.YValue,
						bar,
						y,
						WLColor.Cyan,
						2);
				}
			}
		}
		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}

ParallelTrendLine
public static TrendLine ParallelTrendLine(BarHistory bars, int leftPtIndex, double leftPtValue, int rightPtIndex, double rightPtValue, bool useLog = false)
public static TrendLine ParallelTrendLine(BarHistory bars, PeakTrough peakTrough1, PeakTrough peakTrough2, bool useLog = false)
public static TrendLine ParallelTrendLine(BarHistory bars, TrendLine trendline, bool useLog = false)

Returns a TrendLine parallel to the supplied line and positioned on the opposite side of the price data to form a channel. The source line can be defined by two x/y coordinates, two PeakTrough instances, or a TrendLine. LineUtils examines the prices between the two endpoints to determine which side of the source line contains more price data. It then positions the parallel line at the greatest required offset on the opposite side. If useLog is true, the calculations are performed using logarithmic price scaling. The returned TrendLine has the same endpoint indices as the source line.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
namespace WealthScript123
{
	public class ParallelTrendLineDemo : UserStrategyBase
	{
		PeakTroughCalculator _ptc;
		public override void Initialize(BarHistory bars)
		{
			double swingPct = 8.0;
			_ptc = new PeakTroughCalculator(
				bars,
				swingPct,
				PeakTroughReversalType.Percent);
			int bar = bars.Count - 1;
			PeakTrough peak1 = _ptc.GetPeak(bar);
			if (peak1 != null)
			{
				PeakTrough peak2 = _ptc.GetPeak(peak1.XIndex);
				if (peak2 != null)
				{
					//draw the original trendline
					double y = LineUtils.ExtendLineY(peak1, peak2, bar);
					DrawLine(
						peak2.XIndex,
						peak2.YValue,
						bar,
						y,
						WLColor.Cyan,
						2);
					//create the opposite side of the channel
					TrendLine trendline =
						LineUtils.ParallelTrendLine(bars, peak1, peak2);
					//extend and draw it to the last bar
					y = LineUtils.ExtendLineY(trendline, bar);
					DrawLine(
						trendline.Index1,
						trendline.Value1,
						bar,
						y,
						WLColor.Cyan,
						2);
				}
			}
		}
		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}

ParallelTrendLineAt
public static TrendLine ParallelTrendLineAt(BarHistory bars, int atIndex, double atValue, int leftPtIndex, double leftPtValue, int rightPtIndex, double rightPtValue, bool useLog = false)
public static TrendLine ParallelTrendLineAt(BarHistory bars, int atIndex, double atValue, PeakTrough peakTrough1, PeakTrough peakTrough2, bool useLog = false)
public static TrendLine ParallelTrendLineAt(BarHistory bars, int atIndex, double atValue, TrendLine trendline, bool useLog = false)

Returns a TrendLine parallel to the supplied line and positioned so that it passes through the point specified by atIndex and atValue. The source line can be defined by two x/y coordinates, two PeakTrough instances, or a TrendLine. The returned TrendLine has the same endpoint indices as the source line. If useLog is true, the calculations are performed using logarithmic price scaling.

Example Code
//create a parallel line passing through a specific point
TrendLine parallel = LineUtils.ParallelTrendLineAt(
	bars,
	midX,
	midY,
	trendline,
	false);
//extend it to the last bar
double y = parallel.ExtendTo(bars.Count - 1);
DrawLine(
	parallel.Index1,
	parallel.Value1,
	bars.Count - 1,
	y,
	WLColor.Blue,
	2);

ParallelTrendlineOffset
public static double ParallelTrendlineOffset(BarHistory bars, int bar2, double val2, int bar1, double val1, bool useLog = false)

Calculates the offset required to create the opposite parallel line of a price channel. The line is defined by the two points (bar2, val2) and (bar1, val1). LineUtils examines the price bars between these points to determine whether more prices lie above or below the line, and then finds the greatest required offset on the opposite side. When useLog is false, the returned value is an absolute price offset. When useLog is true, the returned value is a multiplicative price factor. This method is used internally by ParallelTrendLine, but is also available for calculating the channel offset directly.


TrendLineFromHighs
public static TrendLine TrendLineFromHighs(BarHistory bars, int bar, int anchorBar, int ignoreBarsAfterAnchor = 2)

Returns a TrendLine beginning at the High of anchorBar and constrained by the price Highs through bar. The method selects the High that produces the maximum slope from the anchor point. The resulting TrendLine uses anchorBar as Index1, while Index2 identifies the bar that controls the trendline's slope. The optional ignoreBarsAfterAnchor parameter specifies how many bars immediately following the anchor should be ignored. Returns null if no TrendLine can be formed.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
namespace WealthScript123
{
	public class TrendLineFromHighsDemo : UserStrategyBase
	{
		public override void Initialize(BarHistory bars)
		{
			//draw a trendline from the most recent 5% peak
			PeakTroughCalculator ptc =
				new PeakTroughCalculator(
					bars,
					5,
					PeakTroughReversalType.Percent);
			PeakTrough peak = ptc.GetPeak(bars.Count - 1);
			if (peak != null)
			{
				int bar = bars.Count - 1;
				int anchorBar = peak.XIndex;
				TrendLine trendLine =
					LineUtils.TrendLineFromHighs(
						bars,
						bar,
						anchorBar);
				if (trendLine != null)
				{
					DrawLine(
						trendLine.Index1,
						bars.High[trendLine.Index1],
						bar,
						trendLine.ExtendTo(bar, false),
						WLColor.Blue,
						2);
				}
			}
		}
		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}

TrendLineFromLows
public static TrendLine TrendLineFromLows(BarHistory bars, int bar, int anchorBar, int ignoreBarsAfterAnchor = 2)

Returns a TrendLine beginning at the Low of anchorBar and constrained by the price Lows through bar. The method selects the Low that produces the minimum slope from the anchor point. The resulting TrendLine uses anchorBar as Index1, while Index2 identifies the bar that controls the trendline's slope. The optional ignoreBarsAfterAnchor parameter specifies how many bars immediately following the anchor should be ignored. This can prevent price incursions close to the anchor from dominating the resulting trendline. Returns null if no TrendLine can be formed.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
namespace WealthScript123
{
	public class TrendLineFromLowsDemo : UserStrategyBase
	{
		public override void Initialize(BarHistory bars)
		{
			int bar = bars.Count - 1;
			int anchorBar = bars.Low.GetLowestBar(bar, 50);
			TrendLine trendLine =
				LineUtils.TrendLineFromLows(bars, bar, anchorBar);
			if (trendLine != null)
			{
				DrawLine(
					trendLine.Index1,
					bars.Low[trendLine.Index1],
					bar,
					trendLine.ExtendTo(bar, false),
					WLColor.Blue,
					2);
			}
		}
		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}

TriangleTrendLine
public static TrendLine TriangleTrendLine(BarHistory bars, int leftPtIndex, double leftPtValue, int rightPtIndex, double rightPtValue, bool useLog = false)
public static TrendLine TriangleTrendLine(BarHistory bars, PeakTrough peakTrough1, PeakTrough peakTrough2, bool useLog = false)
public static TrendLine TriangleTrendLine(BarHistory bars, TrendLine trendline, bool useLog = false)

Returns a TrendLine on the opposite side of the supplied line with an inverted slope, forming a converging or diverging triangle. The source line can be defined by two x/y coordinates, two PeakTrough instances, or a TrendLine. LineUtils determines which side of the source line contains the price data, finds the appropriate highest or lowest price between the endpoints, and constructs an opposite-sloping TrendLine through that point. If useLog is true, logarithmic price scaling is used when calculating the line. The returned TrendLine's Index1 is the left endpoint of the original line, while Index2 is the index of the price point used to establish the opposite side of the triangle. Remarks

  • The resulting lines can form either a converging triangle or a diverging triangle (horn).
  • Price may already have crossed the resulting TrendLine after its Index2, potentially invalidating the triangle.
Example Code
using WealthLab.Backtest;
using WealthLab.Core;
namespace WealthScript123
{
	public class TriangleTrendLineDemo : UserStrategyBase
	{
		PeakTroughCalculator _ptc;
		public override void Initialize(BarHistory bars)
		{
			double swingPct = 8.0;
			bool useLog = false;
			_ptc = new PeakTroughCalculator(
				bars,
				swingPct,
				PeakTroughReversalType.Percent);
			int bar = bars.Count - 1;
			PeakTrough peak1 = _ptc.GetPeak(bar);
			if (peak1 != null)
			{
				PeakTrough peak2 = _ptc.GetPeak(peak1.XIndex);
				if (peak2 != null)
				{
					//draw the original line
					double y =
						LineUtils.ExtendLineY(
							peak1,
							peak2,
							bar,
							useLog);
					DrawLine(
						peak2.XIndex,
						peak2.YValue,
						bar,
						y,
						WLColor.Cyan,
						2);
					//create the opposite side of the triangle
					TrendLine trendLine =
						LineUtils.TriangleTrendLine(
							bars,
							peak1,
							peak2,
							useLog);
					//extend and draw the triangle line
					y = LineUtils.ExtendLineY(
						trendLine,
						bar,
						useLog);
					DrawLine(
						trendLine.Index1,
						trendLine.Value1,
						bar,
						y,
						WLColor.Cyan,
						2);
				}
			}
		}
		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}