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

exposing the wavetrend indicator for strategy builder

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

    exposing the wavetrend indicator for strategy builder


    I'm trying to expose my variables to the strategy builder so everyone can have better use of the WaveTrend indicator (it has a lot of code).
    Explain this to me like I am 5 because this isnt the first time I've tried to figure it out and hit a wall.
    What is Series? I know its like an array that stores bars. Why not just call it an array? (I'm a pascal guy) T is obviously ticks
    What am I doing wrong? thanks


    Code:
    private bool reversal = false;
    added my private bool variable. Should it be Series<T> to expose it?

    Code:
    AddPlot(new Stroke(Brushes.Transparent, 1), PlotStyle.Line, "Reversal");
    Made a transparent plot to try to get something exposed.

    Code:
    Print("The values are " + Values[4][0]);
    Tried to print my reversal variable but I just get an error in the Output. (Not sure if this should be 3 or 4 either? Does AddLine count or just the AddPlots?
    There are 3 AddPlots and 1 AddLine

    Code:
    Values[4][0]    = true;
    added this to my If / Then to determine if theres a reversal or not

    Code:
    [Display(Name="Reversal", Description="Reversal", Order=1, GroupName="Reversal")]
    public bool Reversal
    {
    get { return reversal; }
    set { reversal = value; }
    }
    I honestly dont have a clue if I'm doing any of this correctly. I dont know why its needed, how it works. I just know it gets and sets.
    Last edited by ezrollin; 12-19-2021, 04:15 PM.

    #2
    Are ALL these steps required to be taken to get it exposed? (besides the Print)

    Comment


      #3
      A Series<double> is like a backwards array.

      Let's explain what a series looks like by talking about arrays.

      Suppose you could 'grow' your array by appending new elements to
      the end. If you have an array of 4 elements, like arr[0] through arr[3],
      when you add the 5th element, that element becomes accessible at
      the end
      of the array via arr[4].

      In C#, array indexing starts at 0, but you knew that.

      A Series<double> also grows automatically, but new elements are
      added to the beginning of the array, er, I mean series. That means
      if you have 4 elements in a series, like ser[0] through ser[3], when
      you add the next element to a series, it's always added to the front,
      that is, it is always added at ser[0].

      Woah, woah woah!
      The front?

      Yep! A Series is like an array, but when you add the next element to
      the Series, each and every element needs to move to the next location.
      Why? Well, you need to free up that spot at ser[0], so that the new
      value can go there -- so the value at ser[3] is moved to (new location)
      ser[4], the value at ser[2] is moved to ser[3] -- get it? The Series acts
      like it shifts all elements by 1, so that ser[0] is moved to ser[1], but ser[1]
      must first be moved to ser[2], etc, and so on down the line, so that the
      new value can go into newly freed up slot at ser[0].

      Just like appending an element to the end of an array, you can think of
      a Series as prepending elements to the front. In both cases, the
      total number of elements has increased by 1.

      Ok, so in an array, the youngest newest freshest element is at the end
      of the array, right? When you append a new element, that's where it goes,
      at the end, so the most recently added element is always the very last
      element of the array.

      But with a series, guess what, the youngest newest freshest element
      is always available at ser[0] -- yep, the most recently added element
      in the series is always, by definition, the element at the '[0]' index.

      That's a very cool and useful feature. It means that you are guaranteed
      that the '[0]' index in a series is like a 'well known or static location' and
      always represents the most recently added element.

      Ok, let's talk NinjaTrader.

      NT uses a set of parallel series, named Open, High, Low, Close, Volume,
      etc, for every bar on the chart. When a new bar closes, each of these 5
      series gets a new element added, but where does it go? These are all
      series, so, by definition, new elements are added at the '[0]' index position.

      Yep, NT has to 'adjust' all the other elements by moving them over by 1
      index position, so the 5 previous elements at index '[0]' for all series can
      be freed up for the 5 new values for the new bar that just closed. This all
      happens under the hood, right after the bar close, and just before NT calls
      your OnBarUpdate.

      Ok, so, what do you get when access Close[0]? Well, by definition, you
      get the most recent value added to the Close series, and that value comes
      from the most recently closed bar.

      That's why NT calls the '0' at the '[0]' index position the BarsAgo index.
      Get it? Close[n] is the close value of nth previous bar, so 'n' is an index
      for how many bars 'old' (aka, how many bars ago) you are looking back
      for the close value.

      Make sense?
      Last edited by bltdavid; 12-19-2021, 07:28 PM.

      Comment


        #4
        Hello ezrollin,

        bltdavid is giving great information.

        To simplify, a custom series is like a Data Series, in that this has a slot for every bar on the chart. As new bars appear, the series gets bigger by one bar. These are accessed with barsAgo values (which is what bltdavid is referring to as a 'backwards array').
        https://ninjatrader.com/support/help...t8/seriest.htm

        Specifically to expose values to the Strategy Builder, these must be plots added with AddPlot() and Value or Values[plot index] must be returned with a public Series<double> variable. (The Value/Values series plot series are also Series<double> objects in that they have a slot for every bar, but are specific to indicator plot series, and are created automatically when you call AddPlot()).

        The Plot series will be indexed in the Values collection by the order AddPlot() is called. The first call becomes Values[0], the second call becomes Values[1], etc.
        https://ninjatrader.com/support/help...t8/addplot.htm
        https://ninjatrader.com/support/help...nt8/values.htm

        Below is a link to an example.
        https://ninjatrader.com/support/foru...238#post812238

        In State.SetDefaults or State.Configure add plots to the Values collection with AddPlot():
        Code:
        AddPlot(Brushes.Blue, "MyPlot1");   // <-- this becomes Values[0]
        AddPlot(Brushes.Green, "MyPlot2");  // <-- this becomes Values[1]
        In the scope of the class, return the plot series Values[plot index] with a public variable:
        Code:
        [Browsable(false)]
        [XmlIgnore]
        public Series<double> MyPlot1
        { get { return Values[0]; } }
        
        [Browsable(false)]
        [XmlIgnore]
        public Series<double> MyPlot2
        { get { return Values[1]; } }
        In OnBarUpdate() set the plot values to the calculated value of your choice:
        Code:
        MyPlot1[0] = SMA(5)[0] / 2;
        MyPlot2[0] = (Open[0] > Close[0] ? 1 : 0;
        Last edited by NinjaTrader_ChelseaB; 01-13-2023, 12:50 PM.
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          So yes, series = array. Thanks for the explanation.

          @chelsea I'm not sure which script in that link you're pointing to. There's no mention of "exposing" anywhere. But I'm sure I could see it being done in any script.

          I changed the private to a public now I can see it showing up in strategy builder. But only the color of my plot.
          There seems to be a disconnect between what I'm trying to have be done (whats exposing) and just the color showing up.
          I changed the Value to the [3rd].. I'm guessing thats the right one.
          What am I doing wrong?


          Code:
          public int reversal = 0;
          
          Values[3][0]    = 1;     //  On true condition
          
          AddPlot(Brushes.Transparent, "Reversal");             //Plot 3 or 4????   ######
          
          [Display(Name="Reversal", Description="Reversal", Order=1, GroupName="Reversal")] //###############
          public int Reversal
          {
          get { return reversal; }
          set { reversal = value; }
          }

          Comment


            #6
            Originally posted by ezrollin View Post
            So yes, series = array.
            No.

            Series != Array.

            That was my whole point.
            They seem similar, but they are absolutely not the same.

            Comment


              #7
              Hello ezrollin,

              To expose values to the Strategy Builder, these must be plots added with AddPlot() and the Vales[plot index] must be returned with a public Series<double> variable.


              You have a public int variable not a public Series<double>.
              Last edited by NinjaTrader_ChelseaB; 12-21-2021, 09:25 AM.
              Chelsea B.NinjaTrader Customer Service

              Comment


                #8
                Originally posted by ezrollin View Post
                I'm trying to expose my variables to the strategy builder so everyone can have better use of the WaveTrend indicator (it has a lot of code).
                Explain this to me like I am 5 because this isnt the first time I've tried to figure it out and hit a wall.
                What is Series? I know its like an array that stores bars. Why not just call it an array? (I'm a pascal guy) T is obviously ticks
                What am I doing wrong?
                Answered here and here.
                The 2nd link is for NT7, but the concepts are the same.

                Originally posted by ezrollin View Post
                Code:
                private bool reversal = false;
                added my private bool variable. Should it be Series<T> to expose it?
                No.

                If you want 'reversal' exposed, you should use public, not private.
                [Or better, leave the variable private and define a public property. See below.]

                All class variables and properties that are public are, by definition, exposed and
                accessible to other callers. The type doesn't matter, it could be int, bool, double,
                DateTime, Series<double>, List<string> etc etc etc ... literally any type.

                The act of 'exposing' is done by the keyword public, not by the type.

                Anything marked private is accessible only to the block of code in which it is
                declared. Thus, private means 'not exposed' -- that is, the external world (such
                as the strategy builder, and the callers of your indicator) can only see the things that
                you have marked public.

                Originally posted by ezrollin View Post
                AddPlot(new Stroke(Brushes.Transparent, 1), PlotStyle.Line, "Reversal");
                Made a transparent plot to try to get something exposed.
                Plots are not 'exposed' automatically. A public property is declared later
                that exposes any Plots that need to be accessible by your callers.

                But let's go deeper into what a Plot it. It's not clear you know why you're
                even adding this Plot -- I mean, a transparent plot is invisible on the chart,
                which defeats the whole point of adding it.

                A Plot is a class that contains all the elements needed to draw something on
                the chart for each bar.
                By definition, a Plot also has a Series<double>, because,
                like I said, the Plot maintains one value for each bar, just like Close, Open, etc.

                If you want to calculate a value for each bar without plotting that value, you would
                just declare a variable with type Series<double>. It almost looks like you're adding
                a transparent Plot just to get access to the Plot's internal Series<double>, which,
                if so, is an extreme bit of overkill, and, frankly, just plain wrong. If you think the
                Plot named 'reversal' is exposing your bool variable also named 'reversal', well,
                that, too, is plain wrong. It demonstrates a profound lack of understanding of
                how all the pieces fit together.

                Originally posted by ezrollin View Post
                Print("The values are " + Values[4][0]);
                Tried to print my reversal variable but I just get an error in the Output. (Not sure if this should be 3 or 4 either? Does AddLine count or just the AddPlots?
                There are 3 AddPlots and 1 AddLine
                Your 'reversal' bool variable is not part of the Plot. Just because you named the
                Plot "reversal" doesn't mean anything, and certainly doesn't associate that Plot
                with the bool variable named 'reversal'.

                When you call AddPlot, which accessing the '[4]' index means you must have done at least
                5 times, it adds a new Plot object to the Plots collection, which is just a list of Plot objects.
                The plot's series is actually stored elsewhere, in the Values collection, which is a list of
                Series<double> objects.

                Values[4] is the Series<double> for the 5th Plot, which is available at Plots[4], which
                came from the 5th call to AddPlot. The names of the Plots, specified in the call to AddPlot,
                don't mean anything -- the plot names are useless to programmers -- but those names
                appear in the section named 'Plots' in the property grid. That's it, that's all the plot name
                is used for.

                Values[4][0] is accessing the '[0]' index of the Values[4] series -- which is the most recent
                value for the 5th added Plot stored at Plots[4] -- the '[0]' index is associated with the most
                recently closed bar, just like Close[0] or Volume[0] -- all of which has absolutely nothing to
                do with your bool variable named 'reversal'.

                Remember when I talked about parallel series? Well, every Series in your indicator, not
                just the internal Series for each bar's OHLCV values, but every Series you create, including
                all Series created via AddPlot, they are all kept in parallel together.

                For ex, Values[4][10] is the value 10 bars ago in the Values[4] data series. My point is,
                accessing series values like Values[4][n] is conceptually the exact same thing as when
                accessing Close[n] -- in both cases, the 'n' is called the BarsAgo index.

                Originally posted by ezrollin View Post
                Values[4][0] = true;
                added this to my If / Then to determine if theres a reversal or not
                This bit of code should have failed. Why? Because the Values collection is a list of
                Series<double> objects. That means only values of type double can be assigned to
                Values[4][0] -- assigning true is an error.

                Again, the Plot which you named 'reversal' has nothing to do with the bool variable
                that is also named 'reversal' -- from NinjaScript's point of view, this is just coincidence.

                Originally posted by ezrollin View Post
                [Display(Name="Reversal", Description="Reversal", Order=1, GroupName="Reversal")]
                public bool Reversal
                {
                get { return reversal; }
                set { reversal = value; }
                }
                I honestly dont have a clue if I'm doing any of this correctly. I dont know why its needed, how it works. I just know it gets and sets.
                This code is correct.
                But if you don't know why it's needed, why are you doing it?

                If you know it 'gets and sets', you're already 80% of the way there in understanding
                what a property is for.

                A property adds a way for you to get inputs from the user. Properties show up in the
                property grid -- unless you prevent that with '[Browsable(false)]' attribute.

                So, are you wanting to give the user a knob to enable/disable reversals? If so, that's
                why you need the bool property, to give the user a knob to set in the property grid.

                The 'Reversal' property does the 'gets and sets' using the 'reversal' variable as its
                backing store.

                Btw, using a variable for a backing store is not strictly necessary. That is, this works,

                Code:
                [Display(Name="Reversal", Description="Reversal", Order=1, GroupName="Reversal")]
                public bool Reversal
                { get; set; }
                And in your case, it does the exact same thing. Why? Because a property with no
                explicit backing store is actually using an automatic implicit invisible backing variable
                initialized to the default value for that type -- which for bool's is false -- which, lo and
                behold, is the same value you assigned in the initialization of the 'reversal' variable.
                Last edited by bltdavid; 12-20-2021, 01:37 PM.

                Comment


                  #9
                  Code:
                  public Series<double> reversal; 
                  
                  [B]reversal    = 1.00;    //on a true event, then pass "1"(true) to strategy builder
                  reversal    = 0.00;    // on a false event, then pass "0"(false) to strategy builder[/B]
                  
                  
                  [Range(1, int.MaxValue)]
                  [NinjaScriptProperty]
                  [Display(Name="Reversal", Description="Reversal", Order=3, GroupName="Reversal")]
                  public bool Reversal
                  { get; set; }
                  Ok, this is ALL the code I have added to it now.
                  I'm getting a "cannot convert double to series(double)" error
                  I highlighted where its saying the error is.
                  Variables and Inputs are not matching.
                  I've been trying to figure this out for months!


                  Comment


                    #10
                    Right now, its just storing the current price.
                    How can I expose whatever I want(bool,int,double,string,etc) to send to strategy builder (not the price).

                    Comment


                      #11
                      ?
                      Originally posted by ezrollin View Post
                      Code:
                      public Series<double> reversal;
                      
                      [B]reversal = 1.00; //on a true event, then pass "1"(true) to strategy builder
                      reversal = 0.00; // on a false event, then pass "0"(false) to strategy builder[/B]
                      
                      [Range(1, int.MaxValue)]
                      [NinjaScriptProperty]
                      [Display(Name="Reversal", Description="Reversal", Order=3, GroupName="Reversal")]
                      public bool Reversal
                      { get; set; }
                      Ok, this is ALL the code I have added to it now.
                      I'm getting a "cannot convert double to series(double)" error
                      I highlighted where its saying the error is.
                      Variables and Inputs are not matching.
                      I've been trying to figure this out for months!
                      If you want to store a different bool value for every bar, then using a
                      Series<bool> is probably what you want.

                      Why use Series<double>?
                      Is that because of Strategy Builder?

                      -=o=-

                      Don't forget, in State.SetDefaults, you have to initialize your Series, like this,

                      Code:
                      reversal = new Series<double>(this);
                      then when you store values, you store one value per bar, and each bar
                      gets it's own slot -- the slot at index '[0]' is always the most recently closed
                      bar.

                      Code:
                      // reversal is a Series<double> so you must use index notation
                      // to assign values to a slot
                      reversal[0] = 1; // you don't need to specify '1.00', you can just use '1'
                      reversal[0] = 0; // you don't need to specify '0.00', you can just use '0'
                      Assignments must use the the '[0]' index notation.

                      Comment


                        #12
                        Originally posted by ezrollin View Post
                        Code:
                        public Series<double> reversal;
                        
                        [Range(1, int.MaxValue)]
                        [NinjaScriptProperty]
                        [Display(Name="Reversal", Description="Reversal", Order=3, GroupName="Reversal")]
                        public bool Reversal
                        { get; set; }
                        Oh, and get rid of that property definition.
                        The variable is public, so the external world should not
                        need a public property to access the series.

                        If you make the variable private, then you'd setup the
                        public property for a Series, like this,

                        Code:
                        [Browsable(false)]
                        [XmlIgnore()]
                        public [B][COLOR=#2980b9]Series<double>[/COLOR][/B] Reversal
                        {
                            get { return [COLOR=#2980b9][B]reversal[/B][/COLOR]; }
                        }
                        Remember, when you code a property, the type of the
                        property needs to match the type of the data being
                        returned -- that's the blue code.

                        If you just want to return the most recent value from
                        the reversal series, try this,

                        Code:
                        [Browsable(false)]
                        [XmlIgnore()]
                        public [B][COLOR=#2980b9]double[/COLOR][/B] Reversal
                        {
                            get { return [COLOR=#2980b9][B]reversal[0][/B][/COLOR]; }
                        }
                        Or, you could morph the return value to a bool, like this,

                        Code:
                        [Browsable(false)]
                        [XmlIgnore()]
                        public [COLOR=#2980b9][B]bool[/B][/COLOR] Reversal
                        {
                            get { return [COLOR=#2980b9][B]reversal[0] > 0[/B][/COLOR]; }
                        }
                        Which one to use?
                        Well, that depends on what you're trying to achieve.




                        Last edited by bltdavid; 12-21-2021, 07:35 AM.

                        Comment


                          #13
                          Hello ezrollin,

                          Originally posted by ezrollin View Post
                          Right now, its just storing the current price.
                          How can I expose whatever I want(bool,int,double,string,etc) to send to strategy builder (not the price).
                          With a plot added with AddPlot and returned with a public Series<double>. See post #4, post #7, and bltdavids post #12.
                          Chelsea B.NinjaTrader Customer Service

                          Comment


                            #14
                            Originally posted by NinjaTrader_ChelseaB View Post
                            Hello ezrollin,
                            With a plot added with AddPlot and returned with a public Series<double>. [/URL].
                            I've heard this so many times. I was trying to do it in the very first post


                            Ok, so all I've got now:
                            Code:
                            public Series<bool> reversal;      
                            reversal = new Series<bool>(this);                  <--in my state.setdefaults
                            reversal[0]    = true;                                            <-- on the true condition   ( it wont let me put reversal[4][0] )
                            reversal[0]  = false;                                             <--- on the false condition
                            Thats it. Now I'm seeing the plot show up in strategy builder (I dont know how thats possible, I removed the plot a long time ago)
                            AND I'm not seeing the parameter of it being True or False in Strategy Builder.
                            What am I doing wrong?

                            Comment


                              #15
                              Hmm,
                              I think you & I have different definitions to what 'exposed' means.

                              'Exposed' is not a technical term, so I was using it in a very generic
                              sense and assumed you meant the 'public' access keyword, vs the
                              'private' access keyword.

                              My essay-like answers may have led you astray. My apologies.

                              Your use case appears to be constrained completely to how your
                              variables and properties in your indicator are able to interact with
                              the Strategy Builder.

                              May I suggest you describe in very specific terms exactly what
                              you're wanting to do?

                              Do you really want every bar to have it's own 'reversal' value
                              associated with it? Or do you want a single global 'reversal'
                              setting, like a knob, that the user can turn on and off?

                              Once NT Support understands how the variable is defined, and
                              how it's used in the code, they can advise you if that indicator
                              variable can be 'exposed' for use inside Strategy Builder.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by jaybedreamin, Today, 05:56 PM
                              0 responses
                              2 views
                              0 likes
                              Last Post jaybedreamin  
                              Started by DJ888, 04-16-2024, 06:09 PM
                              6 responses
                              18 views
                              0 likes
                              Last Post DJ888
                              by DJ888
                               
                              Started by Jon17, Today, 04:33 PM
                              0 responses
                              1 view
                              0 likes
                              Last Post Jon17
                              by Jon17
                               
                              Started by Javierw.ok, Today, 04:12 PM
                              0 responses
                              6 views
                              0 likes
                              Last Post Javierw.ok  
                              Started by timmbbo, Today, 08:59 AM
                              2 responses
                              10 views
                              0 likes
                              Last Post bltdavid  
                              Working...
                              X