Search Framework:
LineUtils
Namespace: WealthLab.Core
Parent:

LineUtils is a static class of function that aid with projecting 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 value of a line in linear chart defined by [x1, y1] and [x2, y2] projected to x, usually a chart index (bar).


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 value of a line in log chart defined by [x1, y1] and [x2, y2] projected to x, usually a chart index (bar).


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)

Wrapper method for linear and log methods ExtendLine and ExtendLineLog, controlled by the useLog parameter.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;

namespace WealthScript123
{
	public class GetTroughExample : UserStrategyBase
	{
		PeakTroughCalculator _ptc;

		public override void Initialize(BarHistory bars)
		{
			//control variables
			double swingPct = 8.0;

			//calculate peaks and troughs based on high/lows
			_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); 
					bar = bars.Count - 1;
					
					//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 line created by and opposite to the points, PeakTroughs (usually the same type), or trendLine, and automatically located a point in between (or in between the trendLine indices) that creates the widest channel. The resultant TrendLine's Index values will be the same as the original line passed to the method. Use ExtendLogY to project the resultant Trendline to estimate a price target.

Remarks

  • The trendline is located by finding where more prices are located with respect with the line (or points that create a line) passed to the method.
Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;

namespace WealthScript123
{
	public class ParallelTrendLineDemo : UserStrategyBase
	{
		PeakTroughCalculator _ptc;

		public override void Initialize(BarHistory bars)
		{
			//control variables
			double swingPct = 8.0;

			//calculate peaks and troughs based on high/lows
			_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); 
					bar = bars.Count - 1;
					
					//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);

					//create a channel, first find the opposite line
					TrendLine trendline = LineUtils.ParallelTrendLine(bars, peak1, peak2);

					// extend and draw it to the last bar
					y = LineUtils.ExtendLineY(trendline, bar);
					// alternatively for TrendLine:  y = trendline.ExtendTo(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 the trendline parallel to the line created by two points (or the trendLine) and that pass through the point [atIndex, atValue]. The resultant TrendLine's Index values will be the same as the original line passed to the method. Use ExtendLogY to project the resultant Trendline to estimate a price target.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Data;
using WealthLab.Indicators;
using System.Collections.Generic;

namespace WealthScript2 
{
	public class MyStrategy : UserStrategyBase
	{
		//create indicators and other objects here, this is executed prior to the main trading loop
		public override void Initialize(BarHistory bars)
		{
			// find the range in the recent chart range
			int idx = bars.Count - 1;
			int lookback = Math.Min(250, idx); 
			double H = Highest.Value(idx, bars.High, lookback); 
			double L = Lowest.Value(idx, bars.High, lookback); 

			double pct = 100 * (H / L - 1) / 4.0;
			DrawHeaderText("Percent PeakTroughs: " + pct.ToString("N2"), WLColor.Cyan, 14);
			_ptc = new PeakTroughCalculator(bars, pct, PeakTroughReversalType.Percent);
			
			//find the TrendLine created by the 2 most recent troughs and 
			// then draw a parallel line from the midpoint between the first trough and previous peak
			bool useLog = false;
			TrendLine tL = _ptc.GetLowerTrendLine(idx, 2, useLog);

			// the peak that preceeds the trendline
			PeakTrough peak = _ptc.GetPeak(tL.Index1 - 1); 
			
			// find the midpoint 
			int midX = (peak.XIndex + tL.Index1) / 2;
			double midY = (peak.YValue + tL.Value1) / 2.0;

			DrawDot(midX, midY, WLColor.Blue, 6);
			TrendLine pTL = LineUtils.ParallelTrendLineAt(bars, midX, midY, tL, useLog);
			
			// draw the lines to the last bar
			DrawLine(tL.Index1, tL.Value1, idx, tL.ExtendTo(idx), WLColor.Red, 2);
			DrawLine(midX, midY, idx, pTL.ExtendTo(idx), WLColor.Blue, 2);

		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
		}

		//declare private variables below
		PeakTroughCalculator _ptc;

	}
}


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

Returns the TrendLine formed by the price Highs to the current bar from the anchor bar's High value. Crossings are ignored for ignoreBarsAfterAnchor bars so that incursions near the anchor bar don't influence the trend. The anchor bar is used for TrendLine.Index1, and TrendLine.Index2 will be the bar index that controls the trendline slope. Use TrendLine.ExtendTo() as shown in the example to extend the line to the current or future bar.

Remarks

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Data;
using WealthLab.Indicators;
using System.Collections.Generic;

namespace WealthScript123
{
    public class TrendLineFromHighsDemo : UserStrategyBase
    {
        //create indicators and other objects here, this is executed prior to the main trading loop
        public override void Initialize(BarHistory bars)
        {
			// draw the Trend from the last 5% peak
			PeakTroughCalculator ptc = new PeakTroughCalculator(bars, 5, PeakTroughReversalType.Percent);
			PeakTrough peak = ptc.GetPeak(bars.Count - 1);			
			int anchorbar = peak.XIndex;
			int bar = bars.Count - 1;

			TrendLine tL = LineUtils.TrendLineFromHighs(bars, bar, anchorbar);
			if (tL != null)
				DrawLine(tL.Index1, bars.High[tL.Index1], bar, tL.ExtendTo(bar, false), WLColor.Blue, 2);
        }

        //execute the strategy rules here, this is executed once for each bar in the backtest history
        public override void Execute(BarHistory bars, int idx)
        {
        }

        //declare private variables below

    }
}

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

Returns the TrendLine formed by the price Lows to the current bar from the anchor bar's Low value. Crossings are ignored for ignoreBarsAfterAnchor bars so that incursions near the anchor bar don't influence the trend. The anchor bar is used for TrendLine.Index1, and TrendLine.Index2 will be the bar index that controls the trendline slope. Use TrendLine.ExtendTo() as shown in the example to extend the line to the current or future bar.

Remarks

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Data;
using WealthLab.Indicators;
using System.Collections.Generic;

namespace WealthScript123
{
    public class TrendLineFromLowsDemo : UserStrategyBase
    {
        //create indicators and other objects here, this is executed prior to the main trading loop
        public override void Initialize(BarHistory bars)
        {
			int anchorbar = bars.Low.GetLowestBar(bars.Count - 1, 50);
			int bar = bars.Count - 1;

			TrendLine tL = LineUtils.TrendLineFromLows(bars, bar, anchorbar);
			if (tL != null)
				DrawLine(tL.Index1, bars.Low[tL.Index1], bar, tL.ExtendTo(bar, false), WLColor.Blue, 2);
        }

        //execute the strategy rules here, this is executed once for each bar in the backtest history
        public override void Execute(BarHistory bars, int idx)
        {
        }

        //declare private variables below

    }
}

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 the TrendLine opposite to the TrendLine passed (or points that form a line) to the method that goes through the highest (or lowest) point with inverted slope. The resulting symmetical triangle formed by the lines will be converging or diverging (horn). Use ExtendLogY to project the resultant Trendline to estimate a price target. Remarks

  • TrendLine.Index1 is set to the leftPtIndex and TrendLine.Index2 is the index of the highest (or lowest) point.
  • It's possible that the TrendLine has already been crossed by price after Index2, which may invalidate the triangle.
Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;

namespace WealthScript2
{
	public class ParallelTrendLineDemo : UserStrategyBase
	{
		PeakTroughCalculator _ptc;

		public override void Initialize(BarHistory bars)
		{
			//control variables
			double swingPct = 8.0;
			bool useLog = false;

			//calculate peaks and troughs based on high/lows
			_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);
					bar = bars.Count - 1;

					//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);

					//find the opposite line that forms a converging or diverging triangle
					TrendLine trendline = LineUtils.TriangleTrendLine(bars, peak1, peak2, useLog);

					// extend the line and draw it to the last bar
					y = LineUtils.ExtendLineY(trendline, bar, useLog);
					// alternatively for TrendLine:  y = trendline.ExtendTo(bar);
					DrawLine(trendline.Index1, trendline.Value1, bar, y, WLColor.Cyan, 2);
				}
			}
		}

		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}