Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Help with simple plot based on calculation

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

    Help with simple plot based on calculation

    Hi,

    Just want to say this forum is such a wonderful resource. I've been referencing it quite a bit but now looks like I need some help...

    I'm trying create an indicator on the lower panel to have three input parameters with the following default values that can be user adjusted as follows...

    1. Period = 22
    2. BTD_Value = 0.005
    3. ShowArrows = true

    I would also like to plot two lines, a zero line and a value line. The value line is is calculated as follows...

    Value = ((High - Close[LowestBar(Close, Period)] / Close[LowestBar(Close, Period)]) * 100

    I'm not sure about the syntax but the calculation of the Value is based on the High minus the lowest Close within the input Period divided by the lowest Close within the same period multiplied by 100.

    I want to plot the Value with the zero line and when the Value is less than the BTD_Value then also plot an up arrow where it occurrs. I have zero experience in this and I've tried the Indicator Wizard but it didn't help me define the calculation for 'Value' so I'm just left with some of my user defined inputs and nothing else.

    In addition, is there a way to plot an arrow under the price bar in when the signal occurs in the indicator? If so, that would be nice with the option to turn it on/off.


    Last edited by Tai Nguyen; 09-17-2020, 09:13 AM.

    #2
    Hello Tai Nguyen,

    Thanks for your post.

    To create an indicator panel, use IsOverLay in OnStateChange() Set.defaults, set to false
    To draw arrows on the price panel, make sure that DrawOnpricePanel in OnStateChange() Set.defaults, is set to true.
    References:



    It looks like you would have one actual plot and the zero line can be added with the AddLine() method.
    Here is a link to AddPlot and AddLine



    When you add a plot, it will be associated with Value. While you can assign current values to Value[0], I prefer to use the name of the plot as it is clearer when reading the code, but you can use Value if you wish.

    If you use the Ninjascript indicator wizard and specify your inputs, plot and line, these will all be set-up for you, according to your selections. It sounds like one input would be a bool type that you can use to draw arrows or not.


    Paul H.NinjaTrader Customer Service

    Comment


      #3
      Not sure if syntax is correct or I"m putting this in the right section but I'm getting...

      "Operator '-' cannot be applied to operands of type 'NinjaTrader.NinjaScript.ISeries<double>' and "double'
      "Operator '<' cannot be applied to operands of type 'NinjaTrader.NinjaScript.ISeries<double>' and "double'

      In referencing to this...

      Code:
      protected override void OnBarUpdate()
      {
      //Add your custom indicator logic here.
      BTD = ((High - Close[LowestBar(Close, Length)]) / Close[LowestBar(Close, Length)]) * 100;
      if (BTD < BTD_Value)
           Draw.ArrowUp(this, "tag"+CurrentBar, true, 0, Close[0], Brushes.White);
      }
      I have 'BTD_Value = 0.005;' under State == State.SetDefaults section.
      Last edited by Tai Nguyen; 09-17-2020, 10:40 AM.

      Comment


        #4
        Hello Tai Nguyen,

        Thanks for your reply.

        If BTD is the name of the plot, you would need to be using BTD[0] = to assign a value to it. Also, for the High you would need to specify High[0].

        In the if statement you need BTD[0] < BTD_Value

        You may want to offset your arrow from the bar, typically I will use the High or the Low of the bar and add or subtract x number of ticks, for example Low[0] - 4 * TickSize or High[0]+ 3 *TickSize
        TickSize holds the value of the smallest movement of that instrument.
        Paul H.NinjaTrader Customer Service

        Comment


          #5
          Paul,

          No errors now but I loaded the indicator and it doesn't plot anything. I've added the AddPlot and defined the value of BTD but how do I have the AddPlot reference BTD and actually plots it along with the ZeroLine and then add the arros when BTD is less than BTD_Value which is set default to 0.005?

          I've included the code so far..

          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>
          /// The BuyTheDip is an indicator that shows buy only signals.
          /// </summary>
          public class BuyTheDip : Indicator
          {
          protected override void OnStateChange()
          {
          if (State == State.SetDefaults)
          {
          Description = @"Shows signals to buy the dip";
          Name = "BuyTheDip";
          Calculate = Calculate.OnEachTick;
          IsOverlay = false;
          DisplayInDataBox = true;
          DrawOnPricePanel = true;
          DrawHorizontalGridLines = true;
          DrawVerticalGridLines = false;
          PaintPriceMarkers = true;
          ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
          //Disable this property if your indicator requires custom values that cumulate with each new market data event.
          //See Help Guide for additional information.
          IsSuspendedWhileInactive = true;
          Length = 22;
          BTD_Value = 0.005;
          ShowArrows = true;
          AddLine(Brushes.DimGray, 0, "ZeroLine");
          AddPlot(new Stroke(Brushes.Orange, DashStyleHelper.Solid,1), PlotStyle.Line, "BTD");
          
          }
          else if (State == State.Configure)
          {
          //AddLine(MyBrush, 0, "zeroline");
          }
          }
          
          protected override void OnBarUpdate()
          {
          //Add your custom indicator logic here.
          BTD[0] = ((High[0] - Close[LowestBar(Close, Length)]) / Close[LowestBar(Close, Length)]) * 100;
          if (BTD[0] < BTD_Value)
          Draw.ArrowUp(this, "tag"+CurrentBar, ShowArrows, 0, Close[0], Brushes.White);
          }
          
          #region Properties
          [NinjaScriptProperty]
          [Range(1, int.MaxValue)]
          [Display(Name="Length", Order=1, GroupName="Parameters")]
          public int Length
          { get; set; }
          
          [NinjaScriptProperty]
          [Range(0.0001, double.MaxValue)]
          [Display(Name="BTD_Value", Order=2, GroupName="Parameters")]
          public double BTD_Value
          { get; set; }
          
          [NinjaScriptProperty]
          [Display(Name="ShowArrows", Description="Show signal arrows", Order=3, GroupName="Parameters")]
          public bool ShowArrows
          { get; set; }
          
          
          [Browsable(false)]
          [XmlIgnore]
          public Series<double> BTD
          {
          get { return Values[0]; }
          }
          #endregion
          
          }
          }
          
          #region NinjaScript generated code. Neither change nor remove.
          
          namespace NinjaTrader.NinjaScript.Indicators
          {
          public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
          {
          private BuyTheDip[] cacheBuyTheDip;
          public BuyTheDip BuyTheDip(int length, double bTD_Value, bool showArrows)
          {
          return BuyTheDip(Input, length, bTD_Value, showArrows);
          }
          
          public BuyTheDip BuyTheDip(ISeries<double> input, int length, double bTD_Value, bool showArrows)
          {
          if (cacheBuyTheDip != null)
          for (int idx = 0; idx < cacheBuyTheDip.Length; idx++)
          if (cacheBuyTheDip[idx] != null && cacheBuyTheDip[idx].Length == length && cacheBuyTheDip[idx].BTD_Value == bTD_Value && cacheBuyTheDip[idx].ShowArrows == showArrows && cacheBuyTheDip[idx].EqualsInput(input))
          return cacheBuyTheDip[idx];
          return CacheIndicator<BuyTheDip>(new BuyTheDip(){ Length = length, BTD_Value = bTD_Value, ShowArrows = showArrows }, input, ref cacheBuyTheDip);
          }
          }
          }
          
          namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
          {
          public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
          {
          public Indicators.BuyTheDip BuyTheDip(int length, double bTD_Value, bool showArrows)
          {
          return indicator.BuyTheDip(Input, length, bTD_Value, showArrows);
          }
          
          public Indicators.BuyTheDip BuyTheDip(ISeries<double> input , int length, double bTD_Value, bool showArrows)
          {
          return indicator.BuyTheDip(input, length, bTD_Value, showArrows);
          }
          }
          }
          
          namespace NinjaTrader.NinjaScript.Strategies
          {
          public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
          {
          public Indicators.BuyTheDip BuyTheDip(int length, double bTD_Value, bool showArrows)
          {
          return indicator.BuyTheDip(Input, length, bTD_Value, showArrows);
          }
          
          public Indicators.BuyTheDip BuyTheDip(ISeries<double> input , int length, double bTD_Value, bool showArrows)
          {
          return indicator.BuyTheDip(input, length, bTD_Value, showArrows);
          }
          }
          }
          
          #endregion

          Comment


            #6
            Hello Tai Nguyen,

            Thanks for your reply.

            Whenever you have an indicator that compiles but does not perform as expected, check the "Log" tab of the NinjaTrader control center as any "run time" type errors will be displayed there.

            I suspect that you will see a bar accessing type error.

            When you apply your indicator, the indicator will load the very first bar of data in the data series and it will perform your code on that bar. I suspect that this code:
            LowestBar(Close, Length) is trying to access previous data (up to 22 bars ago) that does not yet exist.

            What you would need to do is prevent your code from accessing the data until, in your indicator case, "Length" bars (or more) have passed.

            Before your first code line in OnBarUpdate() you could add:

            if (CurrentBar < Length+1) return; // do not process code until length +1 one bars loaded.

            Reference: https://ninjatrader.com/support/help...currentbar.htm

            FYI; When posting code, no need to show anything below: #region NinjaScript generated code. Neither change nor remove. as it would not be relevant in most cases. If we need to see it we will ask!
            Paul H.NinjaTrader Customer Service

            Comment


              #7
              Paul,

              Looks like it's working even though it doesn't quite have the same result as the same indicator on another platform. I suspect it's because the way candles are timestamped differently. Thank so much for your help! One last thing (I think...hehe), how can I have the signal arrows appear both on the price chart AND on the lower indicator panel?

              Comment


                #8
                Hello Tai Nguyen,

                Thanks for your reply.

                If you are not getting the same results, you may want to print out the values being selected/calculated. Here is a link to debugging tips which covers print out information: https://ninjatrader.com/support/help...script_cod.htm

                "how can I have the signal arrows appear both on the price chart AND on the lower indicator panel?". You would have to turn on/off DrawOnPricePanel. For example by default you have it set to true so this first line will draw in on the price panel

                Draw.ArrowUp(this, "tag"+CurrentBar, true, 0, Close[0], Brushes.White);
                DrawOnPricePanel = false; // now draw on indicator panel
                Draw.ArrowUp(this, "tag2"+CurrentBar, true, 0, BTD[0] , Brushes.White); // note different tag name and different price value needed
                DrawOnPricePanel = true; // reset to price panel for next cycle.
                Paul H.NinjaTrader Customer Service

                Comment


                  #9
                  Paul,

                  I managed to get the arrows plotting. I have the arrows on the lower panel appear at -0.05 under the zero line. However, only the top part of the arrow is showing. How can I define a lower margin or how can I set it to where it will fit everything inside the panel?

                  Also, I have to look up using tags because this may have to do with that but how do I have two different toggle on/off for each set of arrows, one for the upper price panel and one for the lower panel?

                  I thought I had to define two (variables?) under State.SetDefaults like...

                  ShowArrowsUpper = true;
                  ShowArrowsLower = true;

                  ..then use "ShowArrowsUpper" and "ShowArrowsLower" as tags but it doesn't seem to work that way. ShowArrows seem to be an assigned default by NT8.

                  Comment


                    #10
                    Hello Tai Nguyen,

                    Thanks for your reply.

                    If you are still using this code: Draw.ArrowUp(this, "tag"+CurrentBar, ShowArrows, 0, Close[0], Brushes.White); please make sure that the bool "ShowArrows" is actually set true. The bool is located in the parameter space that is for setting "Autoscale" true for the draw object. Autoscale true means that the arrow would be included in the charts panel autoscaling.

                    Reference: https://ninjatrader.com/support/help...aw_arrowup.htm

                    Yes, you can use bools to control what Draw statements are executed, would not be related to tag names.
                    Paul H.NinjaTrader Customer Service

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by knighty6508, 05-10-2024, 01:20 AM
                    4 responses
                    25 views
                    0 likes
                    Last Post knighty6508  
                    Started by OllieFeraher, 05-09-2024, 11:14 AM
                    6 responses
                    19 views
                    0 likes
                    Last Post OllieFeraher  
                    Started by PaulMohn, 05-02-2024, 06:59 PM
                    2 responses
                    44 views
                    0 likes
                    Last Post PaulMohn  
                    Started by ETFVoyageur, Today, 02:10 AM
                    0 responses
                    14 views
                    0 likes
                    Last Post ETFVoyageur  
                    Started by rayyyu12, Today, 12:47 AM
                    0 responses
                    9 views
                    0 likes
                    Last Post rayyyu12  
                    Working...
                    X