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

What does NinjaTrader mean by 'inheritance is not supported'?

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

    What does NinjaTrader mean by 'inheritance is not supported'?

    Originally posted by NinjaTrader_ChelseaB View Post
    This is correct, NinjaTrader does not support inheritance with Indicators or Strategies. This interferes with the optimizer and with the generated code wrappers.
    Ya know, I had an epiphany.

    Chelsea, you talk about 'inheritance not supported' -- and now I'm not even
    sure what the heck you mean.

    When you say 'inheritance', what exactly are you referring to?

    #2
    Hello bltdavid,

    Below is a link to a 3rd party educational site on inheritance.
    W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.


    With the line:

    public class SMA : Indicator

    This means the SMA class being constructed inherits from Indicator and will have all of the properties and methods of the Indicator class.

    Indicators and Strategies must directly inherit only from the base Indicator or Strategy class and are not supported to inherit from a custom class.
    If you have a custom class, like an addon, that is not an Indicator or Strategy, inheriting from a custom class will likely not cause any issues.

    With the line:

    public class MyCustomIndicatorName : SMA

    This would be attempting to inherit from another indicator (in this case the SMA class, but I am meaning any class that inherits from the Indicator class) and not directly from the Indicator class, which is not supported by NinjaTrader to do, and will break the wrappers and cause undesired behavior in optimizations.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Originally posted by NinjaTrader_ChelseaB View Post
      With the line:

      public class MyCustomIndicatorName : SMA

      This would be attempting to inherit from the SMA class, which would not be allowed.
      Right. And I have never advocated for that kind of inheritance.

      I'm talking about inheritance in the middle.
      Let me explain.

      Normally, SMA inherits from class Indicator, denoted by,

      SMA <- Indicator

      But, what if I inserted something in the middle, like this,

      SMA <- MaBase <- Indicator

      This denotes class SMA inherits from class MaBase, which
      inherits from class Indicator. The MaBase is like a middle
      man class, because it sits in the middle in the hierarchy.

      Can we agree this kind of 'middle-man' inheritance is different
      than what you refer to above, right?

      In other words,
      I do not want to extend class SMA.
      I want to extend class Indicator.


      These two statements are both examples of inheritance, but
      they are not doing the same thing.

      There is a huge difference between these two.

      Can we agree on that?

      Comment


        #4
        Originally posted by NinjaTrader_ChelseaB View Post
        Hello bltdavid,

        Below is a link to a 3rd party educational site on inheritance.
        W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.


        With the line:

        public class SMA : Indicator

        This means the SMA class being constructed inherits from Indicator and will have all of the properties and methods of the Indicator class.

        This would be allowed with custom classes.

        With the line:

        public class MyCustomIndicatorName : SMA

        This would be attempting to inherit from the SMA class, which would not be allowed.
        NinjaTrader_ChelseaB, could you please elaborate on what you mean by "would not be allowed"? In additional to what bltdavid is discussing, I don't see why we couldn't extend an existing class as well, subject to certain limitations.

        For instance, here's an indicator I whipped out just now to demonstrate that does exactly what you wrote would not be allowed.

        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
        {
            public class MyCustomSMA : SMA /* inherits the default @SMA.cs to extend the functionality */
            {
                protected override void OnStateChange()
                {
                    base.OnStateChange();
        
                    if (State == State.SetDefaults)
                    {
                        Name                                        = "MyCustomSMA"; // change the name of the indicator
                        IsOverlay                                    = false; // move the indicator to a subgraph
        
                        Period = 15; // change the default length of SMA from 14 to 15
        
                        LinePrice = 4000; // set the default value for the new parameter we added
        
                        Plots[0].Brush = Brushes.Purple; // change the default SMA inbuilt line's default color from Goldenrod to Purple - the user can still change it but we changed the default color
                    }
                    else if (State == State.Configure)
                    {
                        AddLine(Brushes.Blue, LinePrice, "A line at some price"); // add a horizontal line at a user-specified price from a new input that has been added
                    }
                }
        
                protected override void OnBarUpdate()
                {
                    base.OnBarUpdate();
        
                    // we could add some more functionality here
                }
        
                [NinjaScriptProperty]
                [Display(ResourceType = typeof(Custom.Resource), Name = "Line price", GroupName = "NinjaScriptParameters", Order = 1)]
                public double LinePrice
                { get; set; }
            }
        }
        ​
        As you can see, it does all sorts of things to extend the SMA functionality as a demo - it adds an input parameter which works, changes one of the existing input parameters' defaults which works, adds a line, changes an existing plot's default color, etc.

        What I observe is simply that the code decorator does not work to add the caching and instancing code at the bottom, which means it may not be easy to call this from another indicator or strategy and there is no auto-complete in the NinjaScript Editor. But, while these are limitations, is there more you are saying or are you just saying these limitations would exist?

        The indicator does run on the charts and as far as I can tell works correctly in every way except for what I described above. What am I missing?
        Last edited by QuantKey_Bruce; 03-27-2023, 07:54 AM.
        Bruce DeVault
        QuantKey Trading Vendor Services
        NinjaTrader Ecosystem Vendor - QuantKey

        Comment


          #5
          I mean, suppose I wrote an indicator called bltSwing,
          this is the normal inheritance model,

          bltSwing <- Indicator

          but what if I create a class called bltBase, which inherits
          from class Indicator, then I would have this hierarchy,

          bltSwing <- bltBase <- Indicator

          Furthermore, what if I decide to separate some of the
          features of bltBase into two separate classes, then I
          might have this inheritance scenario,

          bltSwing <- bltCore <- bltBase <- Indicator

          Later, I see that bltSwing indicator has features that could
          be used in a new indicator, say, bltDivergence, so I now
          decide to move some of common features of swing tracking
          into it's own class. Then I can create two indicators, and they
          would have this inheritance hierarchy,

          bltSwing <- bltSwingBase <- bltCore <- bltBase <- Indicator
          ​bltDivergence <- bltSwingBase <- bltCore <- bltBase <- Indicator


          In both cases the auto generated wrapper code is only needed
          for the topmost (er, leftmost) class in the hierarchy, which is the
          classes bltSwing and bltDivergence. The 3 classes in
          the middle don't need wrappers.

          I submit the middle-man classes bltSwingBase, bltCore,
          and bltBase are entirely safe and cause absolutely no issues.

          Remember we are not extending the topmost class, we are
          extending the bottom base class into two, and then extending
          those two base classes into three, etc.

          This is still inheritance, but what I'm describing here is not the
          same thing as what you're describing.

          Can you agree?
          Last edited by bltdavid; 03-28-2023, 06:49 PM.

          Comment


            #6
            Hello bltdavid,

            I've modifed my post # 2 to rephrase this. Instead of 'not allowed', I've phrased this as not supported (by the NinjaScript Engineering Support team)

            An indicator must directly inherit from the Indicator class. This is due to pattern matching NinjaTrader does behind the scenes to recognize the indicator.

            A middle base class would not be supported and would break the wrappers and optimizer.
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Originally posted by NinjaTrader_ChelseaB View Post
              I've modifed my post # 2 to rephrase this. Instead of 'not allowed', I've phrased this as not supported (by the NinjaScript Engineering Support team)

              An indicator must directly inherit from the Indicator class. This is due to pattern matching NinjaTrader does behind the scenes to recognize the indicator.

              A middle base class would not be supported and would break the wrappers and optimizer.
              Thank you, Chelsea, for this reply.

              Frankly, I don't believe much of what you said above is true.

              And that makes me feel sad and disheartened.

              -=o=-

              For example, you said 'must' -- this is factually false.

              Support keeps saying 'breaks the wrappers and optimizer'.



              Well, there are workarounds for the wrapper issues, and
              inheritance somehow breaking the optimizer? Come on,
              that is just preposterous. Perhaps even a blatant lie.

              Why should I believe you? Such a super flimsy description,
              which basically implies that C# is broken. Does Support
              think all users are idiot programmers? It's insulting.



              I'd like to see proof for these assertions.

              I'll gladly admit I'm wrong, but I need proof of concept, not
              just wild allegations C# inheritance breaks something in your
              strategy optimization code.

              Do you have such proof?

              Comment


                #8
                Hello bltdavid,

                I am not implying C# is broken.

                I am stating that NinjaTrader developed NinjaScript in a way that Indicators and Strategies are limited to inheriting from the Indicator and Strategy class only.

                This is not a limitation of C#, this is a limitation of what the developers designed specifically with indicators and strategies (and generally does not affect other script types). I can state for sure, that in the past coders have reported issues when using abstract classes as well as inheritance from any other class. Because of these reported issues, our stance is that the Engineering Support team cannot support this.

                Feel fee to use any code you want as long as it does not affect default functionality and is not malicious. We are simply stating we cannot assist with it and will never advise using it. Use unsupported code at your discretion if you want to. If you are not experiencing an issue, then there is no issue. If you are experiencing an issue, this would be why our team does not support it and you will need to work out the solution on your own.

                To confirm, you are wanting proof that our team does not provide support for this?
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  Originally posted by NinjaTrader_ChelseaB View Post
                  I am not implying C# is broken.

                  I am stating that NinjaTrader developed NinjaScript in a way that Indicators and Strategies are limited to inheriting from the Indicator and Strategy class only.

                  This is not a limitation of C#, this is a limitation of what the developers designed specifically with indicators and strategies (and generally does not affect other script types). I can state for sure, that in the past coders have reported issues when using abstract classes as well as inheritance from any other class. Because of these reported issues, our stance is that the Engineering Support team cannot support this.

                  Feel fee to use any code you want as long as it does not affect default functionality and is not malicious. We simply stating we cannot assist with it and will never advise using it. Use unsupported code at your discretion if you want to. If you are not experiencing an issue, then there is no issue. If you are experiencing an issue, this would be why our team does not support it and you will need to work out the solution on your own.

                  To confirm, you are wanting proof that our team does not provide support for this?
                  I understand your position more clearly.
                  Thank you for the clarification.

                  What I meant by 'proof' is that I'd be interested in any sample code
                  that has been collected from past coders who have reported issues
                  using abstract classes or inheritance.

                  These reported issues are held up as barriers by Support, and I'd
                  really like to understand these problems other coders reported. I'd
                  always assumed that your Support dept (or perhaps the Dev dept)
                  had their own samples, but now maybe the sample codes showing
                  issues have all come from others? Can I please have access to
                  these?

                  -=o=-

                  I mean, so far, in my personal experience, on both NT7 and NT8, I
                  found nothing but sweet joy and elegance from my use of abstract
                  base classes. I used them for indicators and strategies, and I've
                  used them in strategies I've run through the optimizer.

                  Let me be clear.
                  My writing tries to be exact and precise as possible. I acknowledge
                  all Support people are smart and quite capable. You, and Emily, and
                  Kate, and Bertrand (where is Bertrand, anyways?), all of you possess
                  a great knowledge about C# and NinjaScript -- that is abundantly clear.

                  So, thank you, for all your help and insights and advice. I sincerely
                  appreciate all your efforts on these forums, and especially your
                  efforts with me.

                  -=o=-

                  Now, let me be even more clear.

                  I love NinjaTrader.
                  And I love programming, and I especially love C# programming.

                  There is no hate or malice in my heart for any of the people and
                  products at NinjaTrader, only a genuine deep sense of respect.

                  Overall, the product shows and large and elegant system, put
                  together with great care.

                  Many aspects I wish were better, many aspects I know could be
                  made much better and more convenient to the user.

                  So, that's where I'm coming from. I am an experienced software
                  engineer, with over 30+ years of experience, and I am quite capable
                  (actually, there are many on this forum who are quite capable) to
                  analyze and take deep dives into C# code.

                  -=o=-

                  Why am I so insistent on this topic?
                  Because I think the simple use case everyone asks for (how to better
                  organize their growing library of NinjaScript code) is best served by
                  a simple abstract base class, used as a common 'middle-man' class
                  for their indicators and strategies.

                  I don't think the most common and most generic uses of abstract
                  base classes tickle any of the issue past coders have reported,
                  but I'd like to know for sure. I've never come across any issue
                  that rises to the level of show-stopper to their use.

                  So, I keep evangelizing, I keep promoting their use. But everyone
                  in Support claims issues exist, but I've never come across these
                  issues and have never seen support adequately explain these
                  issues in-depth, or provide code samples illustrating a problem.

                  It's not clear what nuances should be avoided,
                  so Support says 'best to just avoid all uses of
                  an abstract base class'. I want the nuances.


                  My point is:
                  Support says because of these issues abstract base classes are
                  unsupported, meaning no assistance will be provided. But then
                  you guys hint at actual problems with their use, but these hints
                  are maddening elusive, because you won't clarify any details of
                  what the issues actually are. You won't provide any sample
                  code, any case studies -- nothing. You're a black hole, saying
                  trust us, we've had past coders report issues to us, but we're
                  not going to elaborate, sorry.

                  And, that, my friend, is where all my frustrations started.

                  By not revealing the details of the issues that have been reported,
                  you invite undue speculation and incorrect assumptions.

                  -=o=-

                  I would like you to reveal much more about what past coders have
                  encountered with abstract base classes.

                  Can you do that?

                  Comment


                    #10
                    Hello bltdavid,

                    I have not collected these scripts, and general I do not collect scripts from users.

                    These are also not in our system, as our development will not accept bug reports with sample scripts that have unsupported code. So I don't have a way of being able to fetch these.

                    I absolutely understand where you are coming from. I also agree abstract classes and inheritance would be extremely helpful for organizing code and avoiding code duplication and have many times in the past wanted to use these concepts myself. To date, I have been able to use partial classes to achieve any code sharing I needed to do in my personal scripts.

                    As these concepts are not supported, we would only be able to submit a feature request and track demand until the development team sees a large enough impact and decides to implement.
                    While these may be a huge convenience, especially to prevent code duplication, it is not a blocking issue that prevents users from being able to create working NinjaScripts.

                    I would like you to reveal much more about what past coders have
                    encountered with abstract base classes.

                    Can you do that?
                    From my understanding, issues have stemmed from casting strategy instances to improper types during optimizations that can cause errors and instances to not be included in the final report, and may be related to the collection produced by OptimizationFitness.

                    Unfortunately, I would not be able to provide the proper insight under the hood of the core of NinjaTrader of the specifics of what causes these type of issues. Once we've determined that unsupported code is used in a script, we stop looking into the issue. If development implements the request to fully support abstract classes and inheritance, our support would do further work to identify and report to our development any issues we can reduce and identify.

                    Another example is AddDataSeries() with variables. This works in most cases, but specifically breaks the optimizer. Because of this, using variables in AddDataSeries() is not supported by the NinjaTrader Support staff, even though it works in some cases. With this there is a bit more insight as to why, as the issue stems from all historical data is loaded before the optimization actually begins, which we can see by printing the instance states.

                    With all of that said, why not just give the unsupported code a try and use it you don't find any issues for your use cases?
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Originally posted by NinjaTrader_ChelseaB View Post
                      With all of that said, why not just give the unsupported code a try
                      and use it you don't find any issues for your use cases?
                      Thanks, Chelsea, I appreciate the extra insights you've provided.

                      ​Yep, that's exactly what I've been doing -- and I've seen no
                      issues whatsoever.

                      The only stickler I have is when someone asks a question on
                      the forums about organizing their code, no mention (usually) is
                      ever made of the organizational opportunities afforded by the
                      'middle-man' abstract base class approach.

                      I know, I know, it's unsupported, that's why it's not usually
                      mentioned.

                      Still, it's a shame that with many uses cases, esp when a user just
                      wants to organize a modest amount of personal code, which an
                      abstract base class could handle with ease (and with no issues)
                      the base class concept never even gets an honorable mention.

                      Ok, ok, yes, I know -- that's what unsupported means.

                      Sigh ... oh well, it's a bummer.

                      "I tried, Your Honor, I really really tried."

                      Peace out.

                      Last edited by bltdavid; 03-27-2023, 07:56 PM.

                      Comment


                        #12
                        I have only skimmed the above posts. If the information below is redundant, my apologies.

                        I have successfully done inheritance with my indicators and discovered along the way a few thins about how to get it to generate code wrappers, or how to prevent it from generating code wrappers. I have had no issues thus far when doing this inheritance.

                        *** Disclaimer ***
                        Just because its possible to do this, does not make this supported. The NinjaTrader documentation and support team indicate that these are not supported situations so it is possible that future versions break this functionality or other issues may arise.



                        If you want your indicator to generate the code, it needs to derive from something with the word "Indicator" in the name, and it must be in the same line as the class declaration.

                        Code:
                        class MyIndicator: Indicator   // This will generate the code at the bottom of the file
                        {}
                        
                        class MyIndicatorBase          // This will not. If you don't want generated code.
                           :Indicator
                        {}
                        
                        class MyOtherIndicator: MyIndicatorBase  // This should generate code at the bottom of the file.
                        {}
                        Generated code will only be done for the first class derived from something with the name Indicator in it found in the file. I would not rely on this to prevent code generation however and instead use method 2 above.

                        This is the pattern I have used successfully to have common base classes for multiple indicators. I will name my common base class with the name "Indicator" somewhere in it, and I will use the 2nd example above to declare it. This is especially important if you have any abstract functions, or you do not want that common base class to appear in the Indicators list inside the UI.

                        Since this functionality already exists, it would be nice if it would be kept this way moving forward as this allows for common implementations for things.

                        I have not tried putting NinjaScript properties in the base class. I am not sure if their code generator will handle that scenario. As far as I can tell XmlIgnore and Browsable(false) work as expected.
                        Last edited by ntbone; 03-28-2023, 12:47 AM.

                        Comment


                          #13
                          Thanks, I use that solution, too.

                          To avoid generation of wrappers, another solution is to
                          move those files to the AddOns folder.

                          -=o=-

                          What I really want for Christmas, however, is for the
                          NinjaScript compiler to recognize the 'abstract' keyword
                          for class definitions and become auto-aware that such
                          classes do not get auto-generated wrappers.

                          Even if inheritance remains 'unsupported', this feature is
                          arguably still needed. Why? Because an abstract base
                          class cannot be instantiated (per C# rules) so it is, IMHO,
                          a bug to generate wrappers for an abstract class.

                          Think about it, those wrappers are there only to help with
                          instantiation details (eg, caching) -- so it is a doofus move
                          for the compiler to add wrappers to a class that can never,
                          by definition, become instantiated. Ergo, it's a bug.

                          My point is: everything we're currently doing to avoid wrapper
                          generation is a workaround -- we need something official,
                          something that is a documented part of the product. The
                          only real solution in that direction is for the compiler to be
                          fixed -- it needs to recognize the 'abstract' keyword for
                          class definitions so it can avoid wrapper generation.

                          Unfortunately, this relatively simple check (which is needed
                          now) will probably never be implemented until the larger
                          decision of supporting inheritance is addressed. That is,
                          NT will probably see this small fix as 'enabling' inheritance,
                          and that is something they are currently avoiding. I mean,
                          this simple compiler fix touches on other topics, and is
                          probably larger in scope than just itself.

                          Just my 2˘.

                          Comment


                            #14
                            I'd settle for the current methods available to be supported. It would also be nice if the abstract keyword would prevent generation but sometimes a base class isn't necessarily abstract.

                            The functionality I described above works great. The only situation I have not fully covered is creating indicators in strategies. I have created the indicators that inherit from a common base class from other indicators, and have had them save to files without any issues. I have also used them as columns in the market analyzer.

                            For the NinjaTrader team to support it, they would need to test and have some verification process on their end, which I understand is potentially a not-small amount of work. It would still be great to have this as option.

                            At a minimum, if a feature request hasn't already been created, a feature request should be created to track demand for inheritance.

                            Comment


                              #15
                              I would think if they just scan the class declaration line for the keyword "abstract" and if it's there, don't add wrappers... that doesn't seem like it would require a tremendous amount of work or testing. Sounds like a few minutes to me.
                              Bruce DeVault
                              QuantKey Trading Vendor Services
                              NinjaTrader Ecosystem Vendor - QuantKey

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Tim-c, Today, 02:10 PM
                              1 response
                              7 views
                              0 likes
                              Last Post NinjaTrader_ChelseaB  
                              Started by Taddypole, Today, 02:47 PM
                              0 responses
                              2 views
                              0 likes
                              Last Post Taddypole  
                              Started by chbruno, 04-24-2024, 04:10 PM
                              4 responses
                              50 views
                              0 likes
                              Last Post chbruno
                              by chbruno
                               
                              Started by TraderG23, 12-08-2023, 07:56 AM
                              10 responses
                              399 views
                              1 like
                              Last Post beobast
                              by beobast
                               
                              Started by lorem, Yesterday, 09:18 AM
                              5 responses
                              25 views
                              0 likes
                              Last Post NinjaTrader_ChelseaB  
                              Working...
                              X