#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion
//This namespace holds Indicators in this folder and is required. Do not change it.
namespace NinjaTrader.NinjaScript.Indicators
{
/// <summary>
/// Trend lines automatically plots recent trends by connect high points together for high trends and connecting low points together for low trends.
/// </summary>
public class zzztrendhigh : Indicator
{
private int lastHighBar = -1;
private int lastLowBar = -1;
private double lastHighPrice = double.MinValue;
private double lastLowPrice = double.MaxValue;
private bool? highTrendIsActive = null;
private bool alertIsArmed;
private TrendRay highTrend;
private TrendRay lowTrend;
private TrendQueue trendLines;
private Swing swing;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = NinjaTrader.Custom.Resource.NinjaScriptIndicatorDescriptionTrendLines;
Name = "zzztrendhigh";
Calculate = Calculate.OnBarClose;
IsOverlay = true;
DisplayInDataBox = false;
DrawOnPricePanel = false;
PaintPriceMarkers = false;
Strength = 5;
NumberOfTrendLines = 1;
OldTrendsOpacity = 25;
AlertOnBreak = false;
AlertOnBreakSound = System.IO.Path.Combine(NinjaTrader.Core.Globals.InstallDir, "sounds", "Alert2.wav");
TrendLineHighStroke = new Stroke(Brushes.DarkCyan, 1f);
TrendLineLowStroke = new Stroke(Brushes.Goldenrod, 1f);
}
else if (State == State.Configure)
AddPlot(Brushes.White, NinjaTrader.Custom.Resource.TrendLinesCurrentTrendLine);
else if (State == State.DataLoaded)
{
swing = Swing(Input, Strength);
trendLines = new TrendQueue(this, NumberOfTrendLines);
if (ChartPanel == null)
Draw.TextFixed(this, "zzztrendhigh", Custom.Resource.TrendLinesNotVisible, TextPosition.BottomRight);
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < 0)
return;
// High Trend Line
int swingHighBar = swing.SwingHighBar(0, 1, Strength + 1);
if (swingHighBar != -1)
{
double swingHighPrice = !(Input is PriceSeries || Input is Bars) ? Input[swingHighBar] : High[swingHighBar];
if (swingHighPrice < lastHighPrice && lastHighBar > -1)
{
highTrend = new TrendRay(lastHighBar, lastHighPrice, CurrentBar - swingHighBar, swingHighPrice) { IsHigh = true };
trendLines.Enqueue(highTrend);
highTrendIsActive = true;
alertIsArmed = true;
}
lastHighBar = CurrentBar - swingHighBar;
lastHighPrice = swingHighPrice;
}
// Low Trend Line
int swingLowBar = swing.SwingLowBar(0, 1, Strength + 1);
if (swingLowBar != -1)
{
double swingLowPrice = !(Input is PriceSeries || Input is Bars) ? Input[swingLowBar] : Low[swingLowBar];
if (swingLowPrice > lastLowPrice && lastLowBar > -1)
{
lowTrend = new TrendRay(lastLowBar, lastLowPrice, CurrentBar - swingLowBar, swingLowPrice);
trendLines.Enqueue(lowTrend);
highTrendIsActive = false;
alertIsArmed = true;
}
lastLowBar = CurrentBar - swingLowBar;
lastLowPrice = swingLowPrice;
}
if (highTrendIsActive.HasValue)
{
if (ChartControl == null || ChartControl.BarSpacingType == BarSpacingType.TimeBased)
{
if (highTrendIsActive.Value)
{
double slope = (highTrend.EndPrice - highTrend.StartPrice) / (highTrend.EndBar - highTrend.StartBar);
Values[0][0] = slope * CurrentBar - (slope * highTrend.StartBar - highTrend.StartPrice);
}
else
{
double slope = (lowTrend.EndPrice - lowTrend.StartPrice) / (lowTrend.EndBar - lowTrend.StartBar);
Values[0][0] = slope * CurrentBar - (slope * lowTrend.StartBar - lowTrend.StartPrice);
}
}
else
{
if (highTrendIsActive.Value)
{
double startSlotIndex = ChartControl.GetSlotIndexByTime(ChartBars.GetTimeByBarIdx(ChartControl, highTrend.StartBar));
double endSlotIndex = ChartControl.GetSlotIndexByTime(ChartBars.GetTimeByBarIdx(ChartControl, highTrend.EndBar));
double curSlotIndex = ChartControl.GetSlotIndexByTime(Time[0]);
double slope = (highTrend.EndPrice - highTrend.StartPrice) / (endSlotIndex - startSlotIndex);
Values[0][0] = slope * curSlotIndex - (slope * startSlotIndex - highTrend.StartPrice);
}
else
{
double startSlotIndex = ChartControl.GetSlotIndexByTime(ChartBars.GetTimeByBarIdx(ChartControl, lowTrend.StartBar));
double endSlotIndex = ChartControl.GetSlotIndexByTime(ChartBars.GetTimeByBarIdx(ChartControl, lowTrend.EndBar));
double curSlotIndex = ChartControl.GetSlotIndexByTime(Time[0]);
double slope = (lowTrend.EndPrice - lowTrend.StartPrice) / (endSlotIndex - startSlotIndex);
Values[0][0] = slope * curSlotIndex - (slope * startSlotIndex - lowTrend.StartPrice);
}
}
if (State == State.Realtime && AlertOnBreak && alertIsArmed)
{
if (CrossAbove(Input, Values[0][0], 1) || CrossBelow(Input, Values[0][0], 1))
{
Alert(string.Empty, Priority.High, string.Format(NinjaTrader.Custom.Resource.TrendLinesTrendLineBroken,
highTrendIsActive.Value ? NinjaTrader.Custom.Resource.TrendLinesTrendLineHigh: NinjaTrader.Custom.Resource.TrendLinesTrendLineLow),
AlertOnBreakSound, 0, Brushes.Transparent, highTrendIsActive.Value ? TrendLineHighStroke.Brush : TrendLineLowStroke.Brush);
alertIsArmed = false;
}
}
}
}
public override void OnCalculateMinMax()
{
double minValue = double.MaxValue;
double maxValue = double.MinValue;
foreach (TrendRay trend in trendLines)
AutoScalePerRay(trend.Ray, ref minValue, ref maxValue);
MinValue = minValue;
MaxValue = maxValue;
}
protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { /* Don't Render Plots */ }
#region Helpers
private void AutoScalePerRay(Ray ray, ref double minValue, ref double maxValue)
{
// Do not do anything if there is no Ray (Strategy Analyzer chart)
if (ray == null)
return;
int startIdx = ChartBars.GetBarIdxByTime(ChartControl, ray.StartAnchor.Time);
if (startIdx >= ChartBars.FromIndex - Displacement && startIdx <= ChartBars.ToIndex - Displacement)
{
if (ray.StartAnchor.Price < minValue)
minValue = ray.StartAnchor.Price;
if (ray.StartAnchor.Price > maxValue)
maxValue = ray.StartAnchor.Price;
}
int endIdx = ChartBars.GetBarIdxByTime(ChartControl, ray.EndAnchor.Time);
if (endIdx >= ChartBars.FromIndex - Displacement && endIdx <= ChartBars.ToIndex - Displacement)
{
if (ray.EndAnchor.Price < minValue)
minValue = ray.EndAnchor.Price;
if (ray.EndAnchor.Price > maxValue)
maxValue = ray.EndAnchor.Price;
}
}
private class TrendRay
{
public int StartBar;
public double StartPrice;
public int EndBar;
public double EndPrice;
public Ray Ray;
public bool IsHigh;
public TrendRay(int startBar, double startPrice, int endBar, double endPrice)
{
StartBar = startBar;
StartPrice = startPrice;
EndBar = endBar;
EndPrice = endPrice;
}
}
private class TrendQueue : Queue<TrendRay>
{
private zzztrendhigh instance;
private TrendRay lastTrend;
public new void Enqueue(TrendRay trend)
{
if (instance.ChartControl != null)
{
string rayName = string.Format("{0}_{1}", trend.IsHigh ? NinjaTrader.Custom.Resource.TrendLinesTrendLineHigh : NinjaTrader.Custom.Resource.TrendLinesTrendLineLow, trend.StartBar);
trend.Ray = Draw.Ray(instance,
rayName,
false,
instance.CurrentBar - trend.StartBar - instance.Displacement,
trend.StartPrice,
instance.CurrentBar - trend.EndBar - instance.Displacement,
trend.EndPrice,
trend.IsHigh ? instance.TrendLineHighStroke.Brush : instance.TrendLineLowStroke.Brush,
trend.IsHigh ? instance.TrendLineHighStroke.DashStyleHelper : instance.TrendLineLowStroke.DashStyleHelper,
(int)(trend.IsHigh ? instance.TrendLineHighStroke.Width : instance.TrendLineLowStroke.Width));
trend.Ray.Stroke.Opacity = trend.IsHigh ? instance.TrendLineHighStroke.Opacity : instance.TrendLineLowStroke.Opacity;
if (lastTrend != null)
lastTrend.Ray.Stroke.Opacity = instance.OldTrendsOpacity;
}
lastTrend = trend;
base.Enqueue(trend);
// Make it into a circular buffer
if (Count > instance.NumberOfTrendLines)
{
TrendRay toRemove = base.Dequeue();
// Ray will be null if no ChartControl
if (toRemove.Ray != null)
instance.RemoveDrawObject(toRemove.Ray.Tag);
}
}
public TrendQueue(zzztrendhigh instance, int capacity) : base(capacity)
{
this.instance = instance;
}
}
#endregion
Announcement
Collapse
No announcement yet.
Partner 728x90
Collapse
NinjaTrader
Trendlines
Collapse
X
-
Trendlines
Without completely reinventing the wheel, I would like to modify the TrendLines indicator so that it will show the high and low rays, basically creating a channel around the price action, so that I may call on it from a strategy. I've included the stock code; I did have to remove some of the code so that it would post. Any advice would be greatly appreciated. Thanks.
Code:Tags: None
-
Hello zrobfrank,
Thanks for your post.
To modify a script you could make a copy of that script by opening the script in a New > NinjaScript Editor window, right-clicking in the code of the script, selecting 'Save as', and naming the copy of the script. Once a copy is made you could make modifications to that copy.
The TrendLines indicator only draws a single trend line at the value calculated within the script. It will also show previous trend lines when the 'Number of trend lines' property is set to 2 or more.
You would need to modify the script by adding your own custom logic to calculate values for and plot a second trend line on the chart so that the indicator displays multiple trend lines as a trend channel
It sounds like instead you might be wanting to draw a trend channel on the chart window with the trend channel lines extending to the right instead of using the TrendLines indicator.
The Draw.TrendChannel() method could be used in a NinjaScript indicator to draw a trend channel on the chart at a specified value. You could manually draw a trend channel on the chart, enable the 'Extend lines right' option, and save the drawing object template.
Then you could use the Draw.TrendChannel() method that allows you to specify a templateName to apply that template to the draw object on the chart.
Draw.TrendChannel(NinjaScriptBase owner, string tag, bool isAutoScale, int anchor1BarsAgo, double anchor1Y, int anchor2BarsAgo, double anchor2Y, int anchor3BarsAgo, double anchor3Y, bool isGlobal, string templateName)
See the help guide documentation below for more information.
Draw.TrendChannel(): https://ninjatrader.com/support/help...endchannel.htm
Saving Drawing Object Templates: https://ninjatrader.com/support/helpGuides/nt8/index.html?working_with_drawing_tools__ob.htm#Unde rstandingDrawingObjectTemplates
In the strategy you could then loop through the DrawObjects collection to get the trend channel draw object anchor values to use for conditions or actions.
DrawObjects: https://ninjatrader.com/support/help...rawobjects.htmLast edited by NinjaTrader_BrandonH; 04-07-2024, 02:52 PM.<span class="name">Brandon H.</span><span class="title">NinjaTrader Customer Service</span><iframe name="sig" id="sigFrame" src="/support/forum/core/clientscript/Signature/signature.php" frameborder="0" border="0" cellspacing="0" style="border-style: none;width: 100%; height: 120px;"></iframe>
Latest Posts
Collapse
| Topics | Statistics | Last Post | ||
|---|---|---|---|---|
|
Started by Geovanny Suaza, 02-11-2026, 06:32 PM
|
0 responses
607 views
0 likes
|
Last Post
|
||
|
Started by Geovanny Suaza, 02-11-2026, 05:51 PM
|
0 responses
353 views
1 like
|
Last Post
|
||
|
Started by Mindset, 02-09-2026, 11:44 AM
|
0 responses
105 views
0 likes
|
Last Post
by Mindset
02-09-2026, 11:44 AM
|
||
|
Started by Geovanny Suaza, 02-02-2026, 12:30 PM
|
0 responses
560 views
1 like
|
Last Post
|
||
|
Started by RFrosty, 01-28-2026, 06:49 PM
|
0 responses
561 views
1 like
|
Last Post
by RFrosty
01-28-2026, 06:49 PM
|

Comment