Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

How to plot a line

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

    How to plot a line

    How do I go about plotting a line on a separate panel? For example of the candles closes?

    I've searched the documentation here:


    and previous question here:
    Hey guys, this is my first post here so go easy on me. :P I would like to request someone to make a very very simple indicator that I need to reference for a strategy I am currently working on and am sure this would benefit other as well. It is simply plotting a line between the closes of a bar. Probably a simple task for


    but it's not explicit enough.


    I've found the
    Code:
    closeline
    indicator for Ninjatrader 7 in the User App Share here:



    Closeline Ninjatrader 7 Code
    Code:
    #region Using declarations
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Data;
    using NinjaTrader.Gui.Chart;
    #endregion
    
    // This namespace holds all indicators and is required. Do not change it.
    namespace NinjaTrader.Indicator
    {
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    [Description("Enter the description of your new custom indicator here")]
    public class CloseLine : Indicator
    {
    #region Variables
    private bool colorDot = false;
    private Color upColor = Color.Lime;
    private Color dnColor = Color.Red;
    private Color ftColor = Color.Yellow;
    #endregion
    
    /// <summary>
    /// This method is used to configure the indicator and is called once before any bar data is loaded.
    /// </summary>
    protected override void Initialize()
    {
    
    Add(new Plot(Color.FromKnownColor(KnownColor.Yellow), PlotStyle.Dot, "DOT"));
    Add(new Plot(Color.FromKnownColor(KnownColor.Yellow), PlotStyle.Line, "LINE"));
    
    Plots[0].Pen.Width = 2;
    Plots[1].Pen.Width = 2;
    
    CalculateOnBarClose = false;
    PriceTypeSupported = true;
    //PriceType = PriceType.Weighted;
    PaintPriceMarkers = false;
    DisplayInDataBox = false;
    Overlay = true;
    }
    
    /// <summary>
    /// Called on each bar update event (incoming tick)
    /// </summary>
    protected override void OnBarUpdate()
    {
    if(colorDot==true)
    {
    if (Close[0]>Open[0] )
    
    
    {
    PlotColors[0][0] = upColor;
    Values[0].Set(Input[0]);
    
    }
    
    else if (Close[0]<Open[0] )
    
    {
    PlotColors[0][0] = dnColor;
    Values[0].Set(Input[0]);
    
    }
    
    else if (Close[0]==Open[0] )
    
    {
    PlotColors[0][0] = ftColor;
    Values[0].Set(Input[0]);
    
    }
    
    
    
    else
    Values[0].Reset();
    }
    
    else
    Values[0].Set(Input[0]);
    
    Values[1].Set(Input[0]);
    
    
    
    
    }
    
    #region Properties
    
    
    [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
    [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
    public DataSeries DOT
    {
    get { return Values[0]; }
    }
    
    [XmlIgnore()]
    [Description("Up Color")]
    [Category("Color")]
    [Gui.Design.DisplayNameAttribute("01. Up Color")]
    public Color UpColor
    {
    get { return upColor; }
    set { upColor = value; }
    }
    [Browsable(false)]
    public string UpColorSerialize
    {
    get { return NinjaTrader.Gui.Design.SerializableColor.ToString( upColor); }
    set { upColor = NinjaTrader.Gui.Design.SerializableColor.FromStrin g(value); }
    }
    
    [XmlIgnore()]
    [Description("Down Color")]
    [Category("Color")]
    [Gui.Design.DisplayNameAttribute("02. Down Color")]
    public Color DnColor
    {
    get { return dnColor; }
    set { dnColor = value; }
    }
    [Browsable(false)]
    public string DnColorSerialize
    {
    get { return NinjaTrader.Gui.Design.SerializableColor.ToString( dnColor); }
    set { dnColor = NinjaTrader.Gui.Design.SerializableColor.FromStrin g(value); }
    }
    
    [XmlIgnore()]
    [Description("Flat Color")]
    [Category("Color")]
    [Gui.Design.DisplayNameAttribute("02. Flat Color")]
    public Color FTColor
    {
    get { return ftColor; }
    set { ftColor = value; }
    }
    [Browsable(false)]
    public string FtColorSerialize
    {
    get { return NinjaTrader.Gui.Design.SerializableColor.ToString( ftColor); }
    set { ftColor = NinjaTrader.Gui.Design.SerializableColor.FromStrin g(value); }
    }
    
    [Description("Color Dot?")]
    [Category("Color")]
    [Gui.Design.DisplayNameAttribute("00. Color Dot?")]
    public bool ColorDot
    {
    get { return colorDot; }
    set { colorDot = value; }
    }
    
    
    
    #endregion
    }
    }
    
    #region NinjaScript generated code. Neither change nor remove.
    // This namespace holds all indicators and is required. Do not change it.
    namespace NinjaTrader.Indicator
    {
    public partial class Indicator : IndicatorBase
    {
    private CloseLine[] cacheCloseLine = null;
    
    private static CloseLine checkCloseLine = new CloseLine();
    
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    /// <returns></returns>
    public CloseLine CloseLine()
    {
    return CloseLine(Input);
    }
    
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    /// <returns></returns>
    public CloseLine CloseLine(Data.IDataSeries input)
    {
    if (cacheCloseLine != null)
    for (int idx = 0; idx < cacheCloseLine.Length; idx++)
    if (cacheCloseLine[idx].EqualsInput(input))
    return cacheCloseLine[idx];
    
    lock (checkCloseLine)
    {
    if (cacheCloseLine != null)
    for (int idx = 0; idx < cacheCloseLine.Length; idx++)
    if (cacheCloseLine[idx].EqualsInput(input))
    return cacheCloseLine[idx];
    
    CloseLine indicator = new CloseLine();
    indicator.BarsRequired = BarsRequired;
    indicator.CalculateOnBarClose = CalculateOnBarClose;
    #if NT7
    indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
    indicator.MaximumBarsLookBack = MaximumBarsLookBack;
    #endif
    indicator.Input = input;
    Indicators.Add(indicator);
    indicator.SetUp();
    
    CloseLine[] tmp = new CloseLine[cacheCloseLine == null ? 1 : cacheCloseLine.Length + 1];
    if (cacheCloseLine != null)
    cacheCloseLine.CopyTo(tmp, 0);
    tmp[tmp.Length - 1] = indicator;
    cacheCloseLine = tmp;
    return indicator;
    }
    }
    }
    }
    
    // This namespace holds all market analyzer column definitions and is required. Do not change it.
    namespace NinjaTrader.MarketAnalyzer
    {
    public partial class Column : ColumnBase
    {
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    /// <returns></returns>
    [Gui.Design.WizardCondition("Indicator")]
    public Indicator.CloseLine CloseLine()
    {
    return _indicator.CloseLine(Input);
    }
    
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    /// <returns></returns>
    public Indicator.CloseLine CloseLine(Data.IDataSeries input)
    {
    return _indicator.CloseLine(input);
    }
    }
    }
    
    // This namespace holds all strategies and is required. Do not change it.
    namespace NinjaTrader.Strategy
    {
    public partial class Strategy : StrategyBase
    {
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    /// <returns></returns>
    [Gui.Design.WizardCondition("Indicator")]
    public Indicator.CloseLine CloseLine()
    {
    return _indicator.CloseLine(Input);
    }
    
    /// <summary>
    /// Enter the description of your new custom indicator here
    /// </summary>
    /// <returns></returns>
    public Indicator.CloseLine CloseLine(Data.IDataSeries input)
    {
    if (InInitialize && input == null)
    throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");
    
    return _indicator.CloseLine(input);
    }
    }
    }
    #endregion


    I've tried to work from the SMA indicator (below) but not successful either.

    SMA Ninjatrader 8 Code
    Code:
    //
    
    // This namespace holds indicators in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Indicators
    {
    /// <summary>
    /// The SMA (Simple Moving Average) is an indicator that shows the average value of a security's price over a period of time.
    /// </summary>
    public class SMA : Indicator
    {
    private double priorSum;
    private double sum;
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = NinjaTrader.Custom.Resource.NinjaScriptIndicatorDe scriptionSMA;
    Name = NinjaTrader.Custom.Resource.NinjaScriptIndicatorNa meSMA;
    IsOverlay = true;
    IsSuspendedWhileInactive = true;
    Period = 14;
    
    AddPlot(Brushes.Goldenrod, NinjaTrader.Custom.Resource.NinjaScriptIndicatorNa meSMA);
    }
    else if (State == State.Configure)
    {
    priorSum = 0;
    sum = 0;
    }
    }
    
    protected override void OnBarUpdate()
    {
    if (BarsArray[0].BarsType.IsRemoveLastBarSupported)
    {
    if (CurrentBar == 0)
    Value[0] = Input[0];
    else
    {
    double last = Value[1] * Math.Min(CurrentBar, Period);
    
    if (CurrentBar >= Period)
    Value[0] = (last + Input[0] - Input[Period]) / Math.Min(CurrentBar, Period);
    else
    Value[0] = ((last + Input[0]) / (Math.Min(CurrentBar, Period) + 1));
    }
    }
    else
    {
    if (IsFirstTickOfBar)
    priorSum = sum;
    
    sum = priorSum + Input[0] - (CurrentBar >= Period ? Input[Period] : 0);
    Value[0] = sum / (CurrentBar < Period ? CurrentBar + 1 : Period);
    }
    }
    
    
    #endregion

    #2
    Hello Cormick,

    Thanks for your post.

    If I understand correctly you want to direct the plots of an indicator to an indicator panel.

    To direct the plots to an indicator panel, in State.SetDefaults, change IsOverLay from true to false.

    Reference: https://ninjatrader.com/support/help...?isoverlay.htm

    Please note that the plots can only go to one panel from an indicator (you could not plot in both the price panel and the indicator panel from the same indicator) and this is why IsOverLay is the plot director.

    Comment


      #3
      Hello Paul,

      Thanks for the answer.

      I'm trying to plot the candles closes on a separate panel.
      Just the closes. Not from an indicator.

      I don't understand how to do it.

      For example, on a 1 hour chart (or any period chart), just plotting every 1 hour candle's close.

      Here's a Tradingview screenshot of the expected result:


      Click image for larger version  Name:	explorer_qcYU8qI5VC.png Views:	0 Size:	1,023.3 KB ID:	1154727


      How do you do that basic plotting in NT8?

      Thanks.

      Comment


        #4
        Hello Cormick,

        Thanks for clarifying with a screenshot.

        You do not need to create a script to do this.

        Just add another data series to the chart and change the "chartstyle" to "Line on close".

        I've attached an example and shown the dataseries settings of the 2nd panel.

        Click image for larger version

Name:	Cormick-1.PNG
Views:	1773
Size:	99.5 KB
ID:	1154731

        Comment


          #5
          Thanks Paul.
          I asked in order to learn how plotting with a script work.
          I'd like to first try plotting the close with a script the easy way to then plot anything, once I get the basics of plotting.

          I can't find any tutorial or explicit documentation on doing that inn NT8.

          Could you help?
          How do you plot the close with a script?
          How do you do exactly what you have done in your last post but with a script?

          EDIT:
          and do it the simplest way?
          (
          In Tradingview it's just 2 lines:

          Code:
          study("candles close")
          
          closeline = close
          
          plot(close)
          )


          Thanks a lot!
          Last edited by Cormick; 05-05-2021, 08:02 AM.

          Comment


            #6
            Hello Cormick,

            Thanks for your reply.

            As shown you do not need to create a script to get the line on close as it's part of the charting so that, to me, would be the simplest approach.

            From a script perspective, you would need:

            Set the property IsOverlay to false (to direct the plot to its own panel)
            Add a Plot to your indicator
            In OnBarUpdate place this code:

            Value[0] = Close[0];

            From a complete starting point of view, I would suggest using the indicator wizard to create the indicator as this will provide the structure needed and all you would need is to provide the code for OnBarUpdate.

            Reference: https://ninjatrader.com/support/help...?ns_wizard.htm

            You would apply the indicator to the chart and it will use the charts bars to create the plot in its own panel on the chart window.

            Comment


              #7
              Hello Paul,

              Thanks for the reply and suggestions.

              I've found and watched the NinjaScript Editor 401 video



              Add Input and variables (I won't change values):


              Add logic (if, then statements [Conditions and Actions]):


              Ctrl+Shift+Spacebar = Intelliview:


              Close series:


              Time Series = Period (integer) = SMA Number of bar:


              Getting Continuous values (not just one):


              SMA1 Variable (to continue accessing this instance of the indicator/ in memory):


              Plots (only one for the SMA = zero index [0]):


              3 plots (MACD = Plots[0], Plots[1], Plots[2]):


              Brush (color):


              AddChartIndicator(SMA1):


              Commas = supplying multiple things (Series) to a method or array


              Semi-Colons = statement/action/instruction/declaration/call a method line end



              if statement = pre-condition (no semi-colon end) / branching command = works as a switch


              C# Syntax
              Operators (assignment (=) vs Comparison (== | > | < | >= | <= | >+ | <+ | <- | >- | /= | *= | !=):


              Moving the code(attention to scope):


              Private variables (private SMA SMA1:
              private SMA SMA2: )


              In the scope of our class (= meaning within it's curly brackets/ top hierarchy = the 1st opening curly bracket above it = can be moved anywhere within the lop level of the 1st curly bracket above it -> not embedded in any lower level curly brackets pair)


              Properties section = Inputs Variables (at the bottom (don't change t):


              Copy paste private Variables first (within the scope of the class):


              Copy paste Properties (within the scope of the class):


              Copy Paste the Settings of the defaults:


              State.Configure


              State.DataLoaded


              OnBarUpdate (just the logic inside of it)


              Error when putting code snippets in the wrong places / outside of the proper scope/right curly brackets pair (Print(Time[0]); = can't compile:


              Outside of a method (double error = no method call and not the right method) vs Inside of a method (method call ok) but the wrong one (OnStateChange vs OnBarUpdate):
              Satisfying the Syntax and the Logic

              Runtime errors (go to the log tab of the control center) vs Compile error display at the Script editor bottom:


              Error messages (bright color, all scripts have to compile at the same time = C#):



              Quiz (scope error (trigger? compile?):



              Strategy on chart demo:



              Debugging:



              string.format (format = token, labels):



              Comment


                #8
                What's wrong with my script?
                (I added sound alerts as part of the tutorial but what I need most is for the close to plot)
                Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
                Last edited by Cormick; 05-07-2021, 01:05 AM.

                Comment


                  #9
                  Latest code:
                  Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.


                  It compiles but it's not showing up in the indicators list:


                  How to make it show up in the indicators list?

                  Comment


                    #10
                    Hello Cormick,

                    Thanks for your posts.

                    I can't see anything obvious as to why it would not show up in your indicators list. Please post your script source code file and I would be glad to test it on my end. The file will be found in Documents>NinjaTrader8>bin>Custom>Indicators> it will be named as you named it with a .cs for file type.

                    I created a short video of how you can create this with the indicator wizard: https://Paul-ninjaTrader.tinytake.co...M18xNjc4ODA1Nw

                    Comment


                      #11
                      Hello Paul,

                      Thanks for the reply and the great help from the video!
                      I've just learned we can/how we can use the Ninjascript Editor directly to build the Indicators template thanks to your video!

                      My previous script did not show in the list I suspect because I had used the
                      Code:
                      Control Center > Strategy Builder
                      method as seen in the NinjaScript Editor 401 video

                      And the strategy builder did not build the
                      Code:
                      #region Properties
                      nor the ending
                      Code:
                      #region NinjaScript generated code. Neither change nor remove.
                      sections.


                      Versus the
                      Code:
                      Control Center > Ninjascript Editor > '+' bottom button > New Indicator
                      method you demonstrated that does build the
                      Code:
                      #region Properties
                      and the ending
                      Code:
                      #region NinjaScript generated code. Neither change nor remove.
                      sections.


                      Furthermore there's no plot feature in the Strategy Builder, that's why I couldn't find it!


                      Versus the
                      Code:
                      Control Center > Ninjascript Editor > '+' bottom button > New Indicator
                      method that has the
                      Code:
                      Plots and Lines
                      feature.


                      You've been a great help! Thanks a lot!
                      Attached Files
                      Last edited by Cormick; 05-10-2021, 03:39 AM.

                      Comment


                        #12
                        I've another question about the
                        Code:
                        CrossAbove()
                        and
                        Code:
                        CrossBelow()
                        methods with the
                        Code:
                        Draw.HorizontalLine()
                        method and custom variables.

                        Here are errors I ran into when trying to trigger a
                        Code:
                        PlaySound()
                        method upon a crossover of the
                        Code:
                        Closeline plot
                        above/below the
                        Code:
                        previous Close horizontal line plot
                        .

                        Here are the errors:


                        Code:
                        CS1502
                        CS1503
                        CS1502
                        CS1503
                        Here's the full code:
                        Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.


                        Here's the
                        Code:
                        OnBarUpdate
                        Code snippet :
                        Code:
                        [LIST=1][*]protected override void OnBarUpdate()[*]{[*]if (CurrentBars[0] <= 55)[*]return;[*]double CurrClose = Value[0] = Close[0];[*][B]object PrevCloseHLine[/B] = Draw.HorizontalLine(this, "tag1", Close[1], Brushes.Green);[*]if (BarsInProgress != 0)[*]return;[*]if (CurrentBars[0] < 1)[*]return;[*]// Set 1[*]if (CrossAbove(CurrClose, [B]PrevCloseHLine[/B],1))[*]{[*]PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\Alert1.wav");[*]}[*]// Set 2[*]if (CrossBelow(CurrClose, [B]PrevCloseHLine[/B],1))[*]{[*]PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\Alert2.wav");[*]}[*]}[/LIST]

                        I suspect the error is caused by the declaration of the object PrevCloseHLine custom variable.
                        I declared it as an Object
                        Code:
                        data type
                        for lack of knowledge about how to declare a
                        Code:
                        Draw.HorizontalLine
                        'element' in Ninjascript (I just learned we need to add the data type to declare custom variables in C#)

                        I need
                        Code:
                        custom variables
                        to use with the
                        Code:
                        CrossAbove()
                        and
                        Code:
                        CrossBelow()
                        methods to trigger the
                        Code:
                        PlaySound()
                        next.

                        Do you see what's the cause of the error?

                        How to use the
                        Code:
                        CurrClose
                        and
                        Code:
                        PrevCloseHLine
                        as valid custom variables for
                        Code:
                        PlaySound()
                        method use?

                        Thanks a lot for your help. Greatly appreciated!

                        Comment


                          #13
                          Hello Cormick,

                          Thanks for your post.

                          I'm not sure of the point or value of listing each item/line that you do not have questions about as it makes for a lengthy and somewhat unreadable post. If I may suggest, just posting your code will suffice, and referencing the item or line number in your question(s) would be easier for everyone to review. Thanks for understanding.

                          In the case of the CrossAbove() or Crossbelow() methods, if you check the help guide for those methods you will see that they accept as inputs either two data series or one dta series and a double type variable. An object or a Draw object is not a double type variable nor is it a data series.
                          References:



                          When you drew the line you used a double type value to specify the price to draw the line at. That would be the value to pass to the cross methods. Note that High[1] would be a specific value at the time/bar you draw the line so using High[1] later may not be appropriate so in the case where you need a value later you can store the value of High[1] into a double type variable that you create. You can then use that double type variable in the cross methods.




                          Comment


                            #14
                            Hello Paul,

                            Thanks for the reply. Ok for the questions format.

                            I updated the code following your directions, but it still returns the same errors.



                            The documentation isn't explicit enough.

                            https://ninjatrader.com/support/help...t8/?cs1502.htm
                            The best overloaded method match for 'NinjaTrader.NinjaScript.NinjaScriptBase.CrossAbov e(double, NinjaTrader.Ninjascript.ISeries<double>, int)' has some invalid arguments

                            https://ninjatrader.com/support/helpGuides/nt8/?cs1503.htm
                            Argument 2: cannot convert from 'double' to 'NinjaTrader.NinjaScript.ISeries<double>'




                            Here's the Code update:
                            Code:
                             protected override void OnBarUpdate()
                            
                            {
                            if (CurrentBars[0] <= 55)
                            return;
                            
                            if (BarsInProgress != 0)
                            return;
                            
                            if (CurrentBars[0] < 1)
                            return;
                            
                            double CurrClose = Value[0] = Close[0];
                            
                            [B]double PrevHigh = Value[0] = High[1];[/B]
                            
                            Draw.HorizontalLine(this, "tag1", High[1], Brushes.Green);
                            
                            
                            // Set 1
                            if (CrossAbove(CurrClose, [B]PrevHigh[/B],1))
                            {
                            PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\Alert1.wav");
                            }
                            
                            // Set 2
                            if (CrossBelow(CurrClose, [B]PrevHigh[/B],1))
                            {
                            PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\Alert2.wav");
                            }
                            }
                            What's wrong?
                            How to fix it?

                            Thank a lot!

                            Comment


                              #15
                              Hello Cormick,

                              Thanks for your reply.

                              When you assign a value to the variable you do not need to also assign it to Value[0].

                              Just double PrevHigh = High[1]; is fine.

                              For the cross conditions, the first parameter must be a data series. For this, I would suggest using the close price series.

                              For example: if (Crossbove(Close, PrevHigh, 1))

                              Here is a reference to all price series you can choose: https://ninjatrader.com/support/help...riceseries.htm

                              ​​​​​​​


                              Comment

                              Latest Posts

                              Collapse

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