Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Trendlines

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    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:
    
    
    #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
    
    
    
    
    
    
    
    
    ​

    #2
    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.htm
    Last 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>

    Comment

    Latest Posts

    Collapse

    Topics Statistics Last Post
    Started by Geovanny Suaza, 02-11-2026, 06:32 PM
    0 responses
    599 views
    0 likes
    Last Post Geovanny Suaza  
    Started by Geovanny Suaza, 02-11-2026, 05:51 PM
    0 responses
    345 views
    1 like
    Last Post Geovanny Suaza  
    Started by Mindset, 02-09-2026, 11:44 AM
    0 responses
    103 views
    0 likes
    Last Post Mindset
    by Mindset
     
    Started by Geovanny Suaza, 02-02-2026, 12:30 PM
    0 responses
    558 views
    1 like
    Last Post Geovanny Suaza  
    Started by RFrosty, 01-28-2026, 06:49 PM
    0 responses
    558 views
    1 like
    Last Post RFrosty
    by RFrosty
     
    Working...
    X