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

Outside actor problem again

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

    Outside actor problem again

    I keep running into this sort of problem. It tells me that I am misunderstanding something fundamental. It could be that the system has a bug, but if so it is unlikely to get fixed so I need to learn how to live with the current situation, buggy or not.

    I have two properties that I do not want to both be true at the same time. They are not radio properties, because it is fine (and in fact normal) for them to both be false at the same time. It is just wrong to both be true at the same time.

    Here is the code that I expect to implement that:
    Code:
                bool showBarNumbers = false;
                [Description("Show the number of each bar.  (Useful for selecting a precise interval or for debugging.)")]
                [GridCategory("\tBar Numbering Parameters")]
                [Gui.Design.DisplayName ("\t\t\t\t\tShow bar numbers")]
                public bool ShowBarNumbers
                {
                    get { return showBarNumbers; }
                    set { 
                        Print("DEBUG: (" + idString() + ")  showBarNumbers=" + showBarNumbers + "  value=" + value);
                        showBarNumbers = value; if (value) ShowBarNumberAtCursor = false;}
                }
                        
                bool showBarNumberAtCursor = false;
                [Description("Show the number of the bar the cursor is on")]
                [GridCategory("\tBar Numbering Parameters")]
                [Gui.Design.DisplayName ("\t\t\t\tShow bar number at cursor")]
                public bool ShowBarNumberAtCursor
                {
                    get { return showBarNumberAtCursor; }
                    set {
                        Print("DEBUG: (" + idString() + ")  showBarNumberAtCursor=" + showBarNumberAtCursor + "  value=" + value);
                        showBarNumberAtCursor = value; if (value) ShowBarNumbers = false;}
                }
    The code works as designed -- except that some outside unwanted actor is also calling in and upsetting the apple cart. Starting from the situation where:
    • ShowBarNumbers = false
    • ShowBarNumberAtCursor = true

    I set ShowBarNumbers true. That is intended to have the effect of both setting it true, and forcing ShowBarNumberAtCursor false. I put Print() statements in the set methods for tracing. The number in parentheses is a unique monotonically increasing object ID. It shows that a new object got created -- not necessarily a problem, although it is one in this case. Here is the trace, with my annotations:
    Code:
    DEBUG: (#54)  showBarNumbers=False  value=False
    DEBUG: (#54)  showBarNumberAtCursor=False  value=True
    DEBUG: (#54)  showBarNumbers=False  value=False
    DEBUG: (#54)  showBarNumbers=False  value=False
    DEBUG: (#54)  showBarNumberAtCursor=True  value=True
    DEBUG: (#54)  showBarNumbers=False  value=False
    [COLOR=Blue]Above here is the final state after the previous action.
    Note that ShowBarNumbers = false, and ShowBarNumberAtCursor=true
    The following output all happened as a result of changing ShowBarNumbers to true in the GUI
    IMPORTANT NOTE: the old object was replaced with a newly constructed object
    [/COLOR]DEBUG: (#62)  showBarNumbers=False  value=True
    [COLOR=Blue]ShowBarNumbers got called and changed its value from false to true, as requested[/COLOR]
    DEBUG: (#62)  showBarNumberAtCursor=False  value=False
    [COLOR=Blue]ShowBarNumbers called ShowBarNumberAtCursor to set it false.
    Note that it was already false -- the default state of the newly constructed object
    The system plans to initialize the new object by calling property set methods
    Unfortunately, that is a big problem because it undoes the side effect of calling ShowBarNumbers
    [/COLOR]DEBUG: (#62)  showBarNumberAtCursor=False  value=True
    [COLOR=Blue]OK -- here it is -- the system now sets ShowBarNumberAtCursor to true
    That is the last value [I]it[/I] knew about, but setting that is a problem because it undoes
    what ShowBarNumbers just did.
    [/COLOR]DEBUG: (#62)  showBarNumbers=True  value=False
    [COLOR=Blue]This is ShowBarNumberAtCursor reacting to the erroneous setting it true
    by forcing ShowBarNumbers false
    ===
    Below here is yet another object being created as the result of that one user GUI action
    [/COLOR]DEBUG: (#70)  showBarNumbers=False  value=False
    [COLOR=Blue]System setting ShowBarNumber false, which is what it ended up after the #62 fiasco[/COLOR]
    DEBUG: (#70)  showBarNumberAtCursor=False  value=True
    [COLOR=Blue]System setting ShowBarNumberAtCursor true, which is [/COLOR][COLOR=Blue]what it ended up after the #62 fiasco[/COLOR]
    DEBUG: (#70)  showBarNumbers=False  value=False
    [COLOR=Blue]This is ShowBarNumberAtCursor setting ShowBarNumbers false
    [/COLOR]DEBUG: (#70)  showBarNumbers=False  value=False
    [COLOR=Blue]I do not know who is makeing this call, or why[/COLOR]
    DEBUG: (#70)  showBarNumberAtCursor=True  value=True
    [COLOR=Blue]I do not know who is makeing this call, or why[/COLOR]
    DEBUG: (#70)  showBarNumbers=False  value=False
    [COLOR=Blue]This is ShowBarNumberAtCursor setting ShowBarNumbers false
    [/COLOR]
    I do not know whether all of that object creation and property calling is due to NT or is inherent in .NET. As Mr. K has previously observed, I am clearly surprised by it. My code expects that if it sets a property that property will remain set, not have some other actor come along with a different idea of what the property value should be. I have previously clearly expressed my view that this is a system bug -- that when I write code I expect any behind-the-scenes stuff, such as unrequested object creation, to be transparent. The above is clearly NOT transparent.

    Last time I brought this issue up, I was asked for code. That case was more complicated, so supplying code was not practical. This case is very simple, though, so I hope the code I have supplied meets that request.

    Now let's get realistic -- it does not matter whether or not the system has a bug, this behavior is unlikely to get changed, at least in V7. Changing it would be a lot of work, introduce a lot of risk, and almost certainly break existing user code. I would not change it if I were an NT developer. Not going to happen, at least in V7.

    So, the real question is how should I write the code to live nicely with V7? Surely it is a reasonable request to be able to set up two properties so that at most one of them is true at any given time.

    One obvious idea is to move the code that enforces the condition elsewhere, such as to OnStartUp(). The problem with that is OnStartUp() has no way to know which of the two should be left true, and which should be forced false.

    --EV
    Last edited by ETFVoyageur; 03-23-2014, 08:33 PM.

    #2
    Hello EV,

    Thank you for your post.

    I am not sure what the work around here would be as I have a few questions on this item. Is the code you listed here outside all methods in the Class as most variables are when defined? Or is this within a method? Are there any other items setting or defining the variables in your code or another script?

    Would you be able to supply the threads where you worked on this before?

    I look forward to your response on this matter.

    Comment


      #3
      Those are conventional indicator properties. They are inside the indicator, but not inside any method. They are not set from anywhere but the GUI. No scripts are involved -- the indicator is just applied to a chart.

      QUESTION: Can you make a suggestion for how to do what I want to do: create two properties such that at most one of them is true at any one time? I'm not wedded to my solution -- I just need one that works.

      Previous thread -- I'll try to locate it. How do I find a list of my previous postings? It was more general and involved more complicated things -- in particular all of this object creation was wiping out values the object had cached.

      QUESTION: Let me ask you another question: what is the approved way for an indicator to retain state (such as a value that needs to be cached) given this constant non-transparent creation of new objects?

      --EV
      Last edited by ETFVoyageur; 03-23-2014, 10:12 PM.

      Comment


        #4
        Patrick,

        Do you agree that the system creates new objects at will, and initializes them by setting the properties?

        If so, can you see why that is a problem when setting a property has a side effect, as in the example this thread gives?

        What I am looking for is how to write code to live in an environment that does such unfriendly things.

        --EV

        Comment


          #5
          I have been thinking about this thread. Let's make it really simple.

          Show me how to make an indicator that has two boolean properties, such that whenever one of those properties is made true the other is forced to be false. Sort of radio-like behavior, except that both can be false at the same time.

          The obvious way -- whenever one property is set true it forces the other false -- does not work, because of how NT operates. That's what I was trying, unsuccessfully, to do with what I posted in the original message in this thread. I do not want to fight the sytem -- I want to work in harmony with it. The problem is that I do not know how to solve this problem, harmoniously or otherwise. I hope there is a reasonable solution that I am just overlooking.

          Thanks,
          EV
          Last edited by ETFVoyageur; 03-23-2014, 11:47 PM.

          Comment


            #6
            Originally posted by ETFVoyageur View Post
            I have been thinking about this thread. Let's make it really simple.

            Show me how to make an indicator that has two boolean properties, such that whenever one of those properties is made true the other is forced to be false. Sort of radio-like behavior, except that both can be false at the same time.

            The obvious way -- whenever one property is set true it forces the other false -- does not work, because of how NT operates. That's what I was trying, unsuccessfully, to do with what I posted in the original message in this thread. I do not want to fight the sytem -- I want to work in harmony with it. The problem is that I do not know how to solve this problem, harmoniously or otherwise. I hope there is a reasonable solution that I am just overlooking.

            Thanks,
            EV
            Unfortunately(?), I actually use code like that, and it seems to work for me, so this is just a suggestion to force an immediate update of properties when either of the properties is changed. Apply the [RefreshProperties(RefreshProperties.All)] attribute to the properties.

            Comment


              #7
              Originally posted by koganam View Post
              Unfortunately(?), I actually use code like that, and it seems to work for me, so this is just a suggestion to force an immediate update of properties when either of the properties is changed. Apply the [RefreshProperties(RefreshProperties.All)] attribute to the properties.
              Thanks for your suggestion. I'm glad to hear it works for you ... that gives hope that I can get it working. I just tried your suggestion, and no joy. Here is the annotated trace:
              Code:
              DEBUG: (#34)  showBarNumbers=False  value=True
              [COLOR=Blue]Called by the GUI action setting ShowBarNumbers = true[/COLOR]
              DEBUG:          showBarNumberAtCursor set to False
              [COLOR=Blue]This is the side effect -- coercing ShowBarNumberAtCursor to false[/COLOR]
              DEBUG: (#34)  showBarNumberAtCursor=False  value=True
              [COLOR=Blue]This is the Outside Actor trying to initialize ShowBarNumberAtCursor.
              Unfortunately, this undoes the side effect, and causes its own unwanted side effect
              [/COLOR]DEBUG:          showBarNumbers set to False
              [COLOR=Blue]This is the unwanted side effect -- resetting ShowBarNumbers back to false[/COLOR]
              DEBUG: (#42)  showBarNumbers=False  value=False
              DEBUG:          showBarNumberAtCursor set to False
              DEBUG: (#42)  showBarNumberAtCursor=False  value=True
              DEBUG:          showBarNumbers set to False
              DEBUG: (#42)  showBarNumbers=False  value=False
              DEBUG:          showBarNumberAtCursor set to True
              DEBUG: (#42)  showBarNumberAtCursor=True  value=True
              DEBUG:          showBarNumbers set to False
              Here is the code, including the Print() statements that produce the above trace. The properties do have the attribute you suggested, but the problem still exists. Can you see what I am doing that is different from your successful code?
              Code:
                          bool showBarNumbers = false;
                          [RefreshProperties(RefreshProperties.All)]
                          [Description("Show the number of each bar.  (Useful for selecting a precise interval or for debugging.)")]
                          [GridCategory("\tBar Numbering Parameters")]
                          [Gui.Design.DisplayName ("\t\t\t\t\tShow bar numbers")]
                          public bool ShowBarNumbers
                          {
                              get { return showBarNumbers; }
                              set { 
                                  Print("DEBUG: (" + idString() + ")  showBarNumbers=" + showBarNumbers + "  value=" + value );
                                  showBarNumbers = value;
                                  if (value) { showBarNumberAtCursor = false; }
                                  Print("DEBUG:          showBarNumberAtCursor set to " + showBarNumberAtCursor );
                              }
                          }
                                  
                          bool showBarNumberAtCursor = false;
                          [RefreshProperties(RefreshProperties.All)]
                          [Description("Show the number of the bar the cursor is on")]
                          [GridCategory("\tBar Numbering Parameters")]
                          [Gui.Design.DisplayName ("\t\t\t\tShow bar number at cursor")]
                          public bool ShowBarNumberAtCursor
                          {
                              get { return showBarNumberAtCursor; }
                              set {
                                  Print("DEBUG: (" + idString() + ")  showBarNumberAtCursor=" + showBarNumberAtCursor + "  value=" + value );
                                  showBarNumberAtCursor = value;
                                  if (value) { showBarNumbers = false; }
                                  Print("DEBUG:          showBarNumbers set to " + showBarNumbers );
                              }
                          }
              --EV

              Comment


                #8
                Originally posted by ETFVoyageur View Post
                Thanks for your suggestion. I'm glad to hear it works for you ... that gives hope that I can get it working. I just tried your suggestion, and no joy. Here is the annotated trace:
                Code:
                DEBUG: (#34)  showBarNumbers=False  value=True
                [COLOR=Blue]Called by the GUI action setting ShowBarNumbers = true[/COLOR]
                DEBUG:          showBarNumberAtCursor set to False
                [COLOR=Blue]This is the side effect -- coercing ShowBarNumberAtCursor to false[/COLOR]
                DEBUG: (#34)  showBarNumberAtCursor=False  value=True
                [COLOR=Blue]This is the Outside Actor trying to initialize ShowBarNumberAtCursor.
                Unfortunately, this undoes the side effect, and causes its own unwanted side effect
                [/COLOR]DEBUG:          showBarNumbers set to False
                [COLOR=Blue]This is the unwanted side effect -- resetting ShowBarNumbers back to false[/COLOR]
                DEBUG: (#42)  showBarNumbers=False  value=False
                DEBUG:          showBarNumberAtCursor set to False
                DEBUG: (#42)  showBarNumberAtCursor=False  value=True
                DEBUG:          showBarNumbers set to False
                DEBUG: (#42)  showBarNumbers=False  value=False
                DEBUG:          showBarNumberAtCursor set to True
                DEBUG: (#42)  showBarNumberAtCursor=True  value=True
                DEBUG:          showBarNumbers set to False
                Here is the code, including the Print() statements that produce the above trace. The properties do have the attribute you suggested, but the problem still exists. Can you see what I am doing that is different from your successful code?
                Code:
                            bool showBarNumbers = false;
                            [RefreshProperties(RefreshProperties.All)]
                            [Description("Show the number of each bar.  (Useful for selecting a precise interval or for debugging.)")]
                            [GridCategory("\tBar Numbering Parameters")]
                            [Gui.Design.DisplayName ("\t\t\t\t\tShow bar numbers")]
                            public bool ShowBarNumbers
                            {
                                get { return showBarNumbers; }
                                set { 
                                    Print("DEBUG: (" + idString() + ")  showBarNumbers=" + showBarNumbers + "  value=" + value );
                                    showBarNumbers = value;
                                    if (value) { showBarNumberAtCursor = false; }
                                    Print("DEBUG:          showBarNumberAtCursor set to " + showBarNumberAtCursor );
                                }
                            }
                                    
                            bool showBarNumberAtCursor = false;
                            [RefreshProperties(RefreshProperties.All)]
                            [Description("Show the number of the bar the cursor is on")]
                            [GridCategory("\tBar Numbering Parameters")]
                            [Gui.Design.DisplayName ("\t\t\t\tShow bar number at cursor")]
                            public bool ShowBarNumberAtCursor
                            {
                                get { return showBarNumberAtCursor; }
                                set {
                                    Print("DEBUG: (" + idString() + ")  showBarNumberAtCursor=" + showBarNumberAtCursor + "  value=" + value );
                                    showBarNumberAtCursor = value;
                                    if (value) { showBarNumbers = false; }
                                    Print("DEBUG:          showBarNumbers set to " + showBarNumbers );
                                }
                            }
                --EV
                So that I can post similar output, where are you declaring and manipulating idString ?

                Comment


                  #9
                  Originally posted by koganam View Post
                  So that I can post similar output, where are you declaring and manipulating idString ?
                  Private "library" -- stuff common to the various indicators I write. It has a base class from which all of my indicators subclass. One of the things in it is as static ID generator. Since it is just for my debugging I did not worry about thread safety. Here is the relevant part:
                  Code:
                      public abstract class VsaIndicator : Indicator, ICustomTypeDescriptor
                      {
                           protected class ObjectID {
                               static int        objectCounter = 0;            // Incremented for each object instance
                               private int      thisCounter;                     // objectCounter value for this object
                               public ObjectID() { thisCounter = ++objectCounter; }
                               public string ToString() { return thisCounter.ToString(); }
                           }
                  
                           protected string idString()   { return "#" + thisObject.ToString(); }
                  
                          ////////////////////////////////////////////////////////////////////////////////////////////////////////////
                          // This will get constructed as part of object construction, guaranteeing a unique instance ID for this object
                          protected ObjectID    thisObject = new ObjectID();
                  }
                  That library and base class work very well for me, but do not make it easy to post code -- they are just too much to ask others to puzzle through. The instance ID part is very helpful (for me, crucial) in understanding just what is happening in this environment where instances are continually getting created and destroyed.

                  --EV
                  Last edited by ETFVoyageur; 03-25-2014, 02:37 AM.

                  Comment


                    #10
                    Originally posted by ETFVoyageur View Post
                    Private "library" -- stuff common to the various indicators I write. It has a base class from which all of my indicators subclass. One of the things in it is as static ID generator. Since it is just for my debugging I did not worry about thread safety. Here is the relevant part:
                    Code:
                        public abstract class VsaIndicator : Indicator, ICustomTypeDescriptor
                        {
                             protected class ObjectID {
                                 static int        objectCounter = 0;            // Incremented for each object instance
                                 private int      thisCounter;                     // objectCounter value for this object
                                 public ObjectID() { thisCounter = ++objectCounter; }
                                 public string ToString() { return thisCounter.ToString(); }
                             }
                    
                             protected string idString()   { return "#" + thisObject.ToString(); }
                    
                            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
                            // This will get constructed as part of object construction, guaranteeing a unique instance ID for this object
                            protected ObjectID    thisObject = new ObjectID();
                    }
                    That library and base class work very well for me, but do not make it easy to post code -- they are just too much to ask others to puzzle through. The instance ID part is very helpful (for me, crucial) in understanding just what is happening in this environment where instances are continually getting created and destroyed.

                    --EV
                    It may be then that your creation of these objects is the perturbating factor? We can arrange for you to see my screen as I set these properties, and we can see that they are sticky. I do not have your object creation code in my setup, so I have removed the idString() call from your debug lines.

                    Comment


                      #11
                      Originally posted by koganam View Post
                      It may be then that your creation of these objects is the perturbating factor? We can arrange for you to see my screen as I set these properties, and we can see that they are sticky. I do not have your object creation code in my setup, so I have removed the idString() call from your debug lines.
                      I'm not following you. The idString() stuff is only called from the debug prints. It has nothing to do with the properties themselves. They have the same problem even with all of the debug printing commented out.

                      I'll look into making a small demo program, but not tonight. That should help isolate the problem.

                      --EV

                      Comment


                        #12
                        Originally posted by ETFVoyageur View Post
                        I'm not following you. The idString() stuff is only called from the debug prints. It has nothing to do with the properties themselves. They have the same problem even with all of the debug printing commented out.

                        I'll look into making a small demo program, but not tonight. That should help isolate the problem.

                        --EV
                        I have a demo program (attached hereto). It does nothing but change those properties. They are sticky.
                        Attached Files

                        Comment


                          #13
                          Originally posted by koganam View Post
                          I have a demo program (attached hereto). It does nothing but change those properties. They are sticky.
                          I thank you for your effort. I'll give it a try and then try to understand what is different in my case.

                          --EV

                          Comment


                            #14
                            Originally posted by koganam View Post
                            I have a demo program (attached hereto). It does nothing but change those properties. They are sticky.
                            Early result: it depends. When I exercise my version, it works just fine in the indicator dialog. I also have control from a dropdown menu with check items I have added to the toolbar. The problem only happens when using the menu. That gives me an interesting avenue to pursue.

                            What I see at a first glance is that when changing the values in the configuration dialog, no one is creating any new objects. So, my code works in that case -- I have always contended that it worked when no one messed with my object.

                            The interesting question is why the extra objects are being created when I change the properties from the drop-down menu. As my previously posted trace made clear, it is the extra objects, and how they are handled, that is the problem. I don't suppose you would have any idea why the menu track causes those extra objects to get created?

                            --EV

                            Comment


                              #15
                              I do not know what to think ... it seems likely that something in what I am about to say is mistaken, but I sure do not know what is wrong with it.

                              When I tried my indicator after seeing yours work, I discovered that mine also worked in the configuration dialog, but that it failed when set from the menu. I reproduced the failure. So, I started by looking at the callbacks from the menu items. I noticed each had a RefreshChart() call, so I said "Aha!" and commented those out. Well, the property interaction now worked so I thought I had found the problem.

                              The calls are needed, so I re-enabled them one-by-one, checking the property interaction after each re-enable. It worked each time. In fact, I now have them all re-enabled and all is working. In other words, as far as I can tell the code is now back to its original state and all is working just fine. So what's the answer? Beats me. I can think of only two possibilities:
                              • I a not remembering accurately what I did ... definitely possible, although the actions were simple enough I would hope that is not the case.
                              • Something was cached somewhere, and my actions got it flushed out. That does not seem very likely either.

                              Bottom line is that it works fine now. Black Magic, I guess.
                              =====
                              I had another weirdness earlier this evening -- using this indicator got into a state where the data box would not come up. Neither ^D nor the menu entry would fetch it. I had to exit and restart NT to get it back. I saved the workspace on exit, and when I restarted the data box was shown -- evidently it had come up but not been visible on the screen. Also no toolbar icon -- I checked. That happened several times. I finally got annoyed enough to try to reproduce the problem, and I have not seen it since. Black Magic.
                              =====
                              I guess I'll just move ahead -- nothing I can do about either issue since all appears to be fine now. I'm just very uncomfortable with Black Magic -- when problems just vanish for no known reason.

                              --EV

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Lumbeezl, 01-11-2022, 06:50 PM
                              31 responses
                              817 views
                              1 like
                              Last Post NinjaTrader_Adrian  
                              Started by xiinteractive, 04-09-2024, 08:08 AM
                              5 responses
                              14 views
                              0 likes
                              Last Post NinjaTrader_Erick  
                              Started by swestendorf, Today, 11:14 AM
                              2 responses
                              6 views
                              0 likes
                              Last Post NinjaTrader_Kimberly  
                              Started by Mupulen, Today, 11:26 AM
                              0 responses
                              6 views
                              0 likes
                              Last Post Mupulen
                              by Mupulen
                               
                              Started by Sparkyboy, Today, 10:57 AM
                              1 response
                              6 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Working...
                              X