Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Question abut State.SetDefaults

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

    Question abut State.SetDefaults

    My understanding is that NT advocates avoiding code in an indicator's constructor -- instead advocating placing that code in the OnStateChange() case for State.SetDefaults. I'm willing to do so (and have done so) just because that is what I was told to do. I still would like to understand why, though.

    About a year back there was a thread in which I was unhappy that SetDefaults got called before my constructor code had run -- it is just wrong to make other function calls before the constructor has run. My error was failing to realize that SetDefaults IS part of the constructor. It is called from the base class constructor before returning to run the derived constructor code. Therefore there is nothing wrong with the SetDefaults call (as long as you realize it is functionally part of the constructor, and will execute prior to the code in the constructor). An interesting idiom, but nothing wrong with doing that.

    What I do not understand is why it is important to put initialization code in SetDefaults instead of in the constructor. The base classes will be at least as initialized by the time the constructor code gets to run, because that comes later than the call to SetDefaults.

    Some have pointed out that callers can get instances from the cache, and the constructor will not run in such a case. True, but neither will SetDefaults, since it is part of construction. What you get from the cache is an already-constructed object with public properties set to the values you specify.

    As far as I can see, the question comes down to whether there is ever a time when SetDefaults will be run, other than when it is called from the base class constructor. To put it another way, is there ever a time when SetDefaults will run, but the constructor code will not? If so, when is that? If not, then why is it better to put initialization code in SetDefaults rather than in the constructor?

    I want to emphasize that I am not trying to be contentious, and I am not trying to claim there is anything wrong. I just want to understand.
    --EV
    Last edited by ETFVoyageur; 08-26-2016, 07:32 PM.

    #2
    Yes in the case where NinjaScript is cloned.

    Basically -> We don't document constructors, don't support them, don't use them. We recommend and use State.SetDefaults.

    Comment


      #3
      Brett,

      Thank you. I had forgotten that NT appears to use MemberwiseClone() to make a shallow copy. Since a shallow copy does not work for me I always override Clone() and provide a deep copy, which involves a constructor. Otherwise the Cancel function of the Indicators dialog is ineffective for my indicators.

      I take your point and will stick to SetDefaults anyway just to be consistent. Thanks for reminding me of that.

      --EV

      Comment


        #4
        Brett,

        I am still trying to understand just how this all happens. I have followed the advice to put everything in SetDefaults (long before this discussion started). I would still like to understand how it all works, though.

        My class overrides Clone()

        I put breakpoints at Clone(), OnStateChange() and the constructor.

        The first line of code in Clone() is "object obj = base.Clone();" Single-stepping over that gets to my OnStateChange() breakpoint, called with State == State.SetDefaults

        Looking at the stack is a surprise, though. Calling base.Clone() ends up calling CreateInstance() internally, which calls my constructor. Going up the constructors, eventually one of them calls OnStateChange(), as expected.

        The surprising fact is that base.Clone() calls my constructor. I thought you said that cloning did not call the constructor? You do not mean that cloning is sometimes done without calling Clone() do you?

        --EV
        Last edited by ETFVoyageur; 08-29-2016, 03:49 PM.

        Comment


          #5
          Sorry about that was thinking about our instanced indicators (which get pooled/reused)and not the c# clone method. For sure I'm incorrect there and clone would generate a new instance.

          Comment


            #6
            Brett,

            Thanks. Let me summarize my understanding, so you can correct anything I still misunderstand: Here are the ways I know of to get a "new" instance of an indicator.

            new() -- calls the constructor and SetDefaults as I have previously described.

            Clone() -- calls the constructor and SetDefaults as I have previously described.

            Magic code caching -- if no cache hit, constructs a new one; both adds it to the cache and returns it. This calls the constructor and SetDefaults. If it is a cache hit, just returns the one from the cache -- in this case what is returned is an already fully-constructed instance so there is no reason to call either a constructor or SetDefaults again.

            Internal pool -- which is what you just mentioned. NT hangs on to some instances it has no present need for. When it does need an instance it expects to get the equivalent of a new object, but with less cost, by taking one of the pooled instances and calling SetDefaults on it. This is the only case where SetDefaults would be called without a constructor being involved.

            Is that right? If so, it sounds as if you expect SetDefaults to restore the instance to its pristine initial state. I doubt that very many indicators do that restoration, because it would mean SetDefaults would have to duplicate all static initialization.

            It sounds to me as if I am still missing something.

            --EV

            Comment


              #7
              That about sums it up. We advise customers to reset indicators to default states in set defaults. Including initializing any objects to blank states as needed in SetDefaults/State.Configure. The common use case in our framework is new DataSeries(). Which needs to be reset before running the next instance and can be done in State.SetDefaults and more appropriately State.Configure.

              Comment


                #8
                As I understand you, that is quite unpleasant news.

                Consider that when an object is initially created there are two kinds of initialization. There is compile time initialization, and there is run time initialization. As I understand you, NT expects that SetDefaults will re-create all compile time initialization as well as the normal run time initialization. Basically that amounts to there being no point in indicators being written with normal compile time initialization of variables. Doing everything as run time initialization would be both tedious and error-prone. Is that really what you mean?

                What guarantees, if any, are there about the state of the object when SetDefaults is called in the pool case? I hope that the state is better defined than my remarks above assume.

                --EV

                Comment


                  #9
                  SetDefault is your way to reset/initialize your NinjaScript. Simply this state will be called as an instance of the NinjaScript is used by NT we will guarantee that we call that state to redefine the default state of your object prior to use. That's the extent we go and its quite simple in design.

                  Comment


                    #10
                    Originally posted by NinjaTrader_Brett View Post
                    SetDefault is your way to reset/initialize your NinjaScript. Simply this state will be called as an instance of the NinjaScript is used by NT we will guarantee that we call that state to redefine the default state of your object prior to use. That's the extent we go and its quite simple in design.
                    I think we shall just agree to disagree on this one, but at least now I understand. Thank you for that.

                    I agree that it is simple from NT's point of view. NT just calls the instance and say "fix this, no matter what state it is in". That's simple for NT.

                    The indicator's story is, however, quite different. In particular, the way it is commonly stated -- just put the constructor's code in SetDefaults -- is false. That is not at all adequate. In the pool case SetDefaults is being asked to do way more than a constructor has to do. Furthermore, SetDefaults has to either detect the pool case and handle that specially, or else it will be unduly heavy in all other cases.

                    The problem is that there is no guarantee of any kind as to what condition the object is in when SetDefaults is called in the pool case. For example, that means there is no assurance that any non-const compile time initialization is intact. That means SetDefaults has to re-create all compile time initialization -- something a constructor does not have to do. That is, in general, not simple and it is error-prone (keeping it up with changes as the indicator evolves). Furthermore, it is sub-optimal programming because one place (SetDefaults) has to have its fingers in things all over the place.

                    Now that I understand how unpleasant SetDefaults' job is I'll have to think of the best way to handle it. Some of the ideas I'm thinking of are a bit heavyweight, but I'd only apply them in the pool case.

                    --EV

                    Comment


                      #11
                      Sure, also the pool case I can only recall 2 cases off the top of my head.Could be more but at least an area to look into that might help you.

                      Strategy Optimizations
                      Indicator calls from an Indicator/Strategy

                      Comment


                        #12
                        Were those two supposed to be URLs?

                        Comment


                          #13
                          no just the two cases I'm aware of.

                          Comment


                            #14
                            Originally posted by ETFVoyageur View Post
                            Magic code caching -- if no cache hit, constructs a new one; both adds it to the cache and returns it. This calls the constructor and SetDefaults. If it is a cache hit, just returns the one from the cache -- in this case what is returned is an already fully-constructed instance so there is no reason to call either a constructor or SetDefaults again.

                            Internal pool -- which is what you just mentioned. NT hangs on to some instances it has no present need for. When it does need an instance it expects to get the equivalent of a new object, but with less cost, by taking one of the pooled instances and calling SetDefaults on it. This is the only case where SetDefaults would be called without a constructor being involved.
                            Aren't these two pools the exact same thing?

                            I mean, the internal pool is the cached instance pool, right?

                            Comment


                              #15
                              The first applies to just Indicators.

                              There is another concept which is for Strategy Optimization runs where a pool of strategies is re-used for maximum performance based on options.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by bortz, 11-06-2023, 08:04 AM
                              47 responses
                              1,603 views
                              0 likes
                              Last Post aligator  
                              Started by jaybedreamin, Today, 05:56 PM
                              0 responses
                              8 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
                              4 views
                              0 likes
                              Last Post Jon17
                              by Jon17
                               
                              Started by Javierw.ok, Today, 04:12 PM
                              0 responses
                              12 views
                              0 likes
                              Last Post Javierw.ok  
                              Working...
                              X