Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

NT making a bogus call on my indicator

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

    NT making a bogus call on my indicator

    Here is the situation:
    • My indicator can have either 1 or 2 plots (value and signal line). Therefore there are two Values[] accessor properties.
    • It is currently compiled to have only the value plot enabled. AddPlot() gets done for the value plot, but no AddPlot() gets done for the signal line plot. Note that this is a static, compiled in, state. It is not some change I am making on the fly. Both Values[] and Plots[] have a length of 1, as they should.
    • My own code knows enough to not call the accesor function for the signal line plot if there is no such plot.
    • Breaking for an exception shows that the accessor property for the signal line is getting called anyway. The call stack shows only two things:
    • (1) [External Code]
    • (2) Signal plot accessor property Get method

    Come on folks! Why is outside code calling my accesor property for a plot that does not exist?

    This is the second sort of such thing I have seen in the last few days. I really need to know just what is going on.

    As far as I am concerned, this is a show-stopping NT bug -- stuff I have no control over is making calls into my code when it should know better. It is calling for information on a plot that does not exist. The basic arrays are fine (Values[] and Plots[]). I really need help understanding what perverse logic is making such a bogus call on my code!

    Perhaps one of the NT support people who monitor this forum could help? Please explain exactly when NT calls the Value[] accessor properties.

    --EV
    Last edited by ETFVoyageur; 08-10-2015, 02:29 PM.

    #2
    Can you strip the code to bare bones with the issue so we can check it out.

    Comment


      #3
      Originally posted by sledge View Post
      Can you strip the code to bare bones with the issue so we can check it out.
      That wold be very difficult. It would be easier to start from scratch and write a test case.

      What I really need is for someone to tell me (us) under just what circumstances NT calls the accessor properties. That seems to me to be a very reasonable piece of information to expect someone at NT to supply.

      I'm not asking anyone to debug my code -- just to tell me when the Values[] accessor properties Get methods can get called.

      A bit of history: I reported a bug in how NT7 handled my indicator dynamically changing the number of plots (in response to a user control enabling/disabling them). NT7 had a baked-in (false) assumption that the number of plots would never change. I have been wondering how NT8 will handle that, but have not gotten that far yet. That's why I stressed that this bug report is about a compiled-in static case. The number of plots is not changing.

      I have a few more tests in mind to try; let me get to those and if they produce any worthwhile information Ill post about them.

      --EV

      Comment


        #4
        Sledge,

        FYI: Part of what is hard is that this bug crashes NT on the way up, making it hard to get Visual Studio attached to see just what happened. It can be done, as I did before my initial posting, but you need to play some tricks.

        Which reminds me -- can someone please tell me how to recompile when NT is not runnable?

        --EV

        Comment


          #5
          My first test is to just comment out the signal line accessor and my call to it. The plot does not exist, so I was not calling that accessor anyway; so nothing should change as far as my code goes.

          When I did that and tried again, in code of mine in Clone() I check CurrentBar. That now gets an exception:
          'CurrentBar' threw an exception of type: 'System.OutOfRangeException'
          =====

          My second test was to have the accessor return Values[0] (instead of Values[1], which does not exist). That provokes the same problem with CurrentBar when trying to Clone() the instance.
          =====

          I guess NT did not like that accessor being missing or invalid.

          --EV

          Comment


            #6
            We wouldn't have the time resources to detail and document every time the getter is called, but at a minimum we'd expect that a public property would be called any time the object would be cloned or e.g., to populate the properties grid.
            MatthewNinjaTrader Product Management

            Comment


              #7
              It jut occurred to me to look at State when I am in Clone() and get the CurrentBar exception. Much to my surprise, State is "Finalized", and the internal state I keep says "TeminationCompleted". Unless I am missing something here, this is another HUGE NT BUG. You cannot call any methods, including Clone(), on an instance that has already been destroyed!

              Someone needs to explain why NT is calling Clone() on an instance that is in State == State.Finalized, and on which OnStateChange() has already been called with State.Terminated. Enough of this calling methods before the constructor has even run (State.SetDefaults) and calling methods after the instance has been destroyed!

              FWIW: my trace printing shows (I can't cut-and-paste right now):
              • OnBarUpdate completed
              • Entry to Transition
              • Exit from Transition
              • Entry to Realtime
              • Exit from Realtime
              • Entry to Terminated
              • Exit from Terminated
              • Then the final line -- a message that is not mine -- presumably NT's:

              Indicator "VsaModelIndicator XXXX": Error on calling 'OnRender' method on bar -1: index outside the bounds of the array ...
              --EV

              Comment


                #8
                Originally posted by NinjaTrader_Matthew View Post
                We wouldn't have the time resources to detail and document every time the getter is called, but at a minimum we'd expect that a public property would be called any time the object would be cloned or e.g., to populate the properties grid.
                • This is not the grid case. The getter will never be put into a grid -- it is marked [Browsable(false)]. Furthermore, it happened as NT was coming up, or when I refreshed the chart -- no grid is involved at those times.
                • I do believe that it is the Clone() case -- see below

                My first thought was that NT was calling a getter for a plot that does not exist, and has never existed. I could not understand why NT would do that, or how it even knew to call the getter.

                I no longer think NT is calling it as a getter (which at least addresses my question of how NT even knew it is a getter) My current thinking at least fits all of the symptoms, including the one the other day. I think the problem is that it is not being called as a getter -- it is being called from Clone(), which is trying to clone an instance that has already been destroyed. (See my post in between yours and this.) That scenario works for now:
                • When I had the getter there, it got an exception on being called from NT, not by me.
                • When I fixed that -- either removed the getter all together, or else had it return a valid value (Values[0]), Clone got further. Either of those allowed it to get to where my Clone() override was trying to access (an already-destroyed) CurrentBar.

                Let's solve the Clone() calling on an already-destrroyed instance first. If I am right, that is the fundamental problem here.

                If I am right, there is another question -- how do I prevent Clone() from trying to clone a getter? Doing so makes no sense. The getter already has [Browsable(false)] and [XmlIgnore()]. Is some further attribute needed? (Those two are all that the wizard puts on the ones it generates.)

                --EV

                Comment


                  #9
                  Note that there are two issues here:
                  1. My discovery of Clone() getting called on an instance that had already been destroyed.
                  2. How to prevent trying to clone a getter. There is no reason to clone one, and no reason to believe that it will necessarily return a valid value if the indicator is not actually using it. In that case, there may, in fact, be no such thing as a valid value for it to return.

                  --EV

                  Comment


                    #10
                    The error makes sense when you realize that the getter just returned a reference to something that does not exist. The exception is "Index was outside the bounds of the array". If CurrentBar was referencing the non-existent data, then throwing an exception when trying to reference it makes perfect sense. Here is the stack for the exception, if that helps.
                    Code:
                       at NinjaTrader.NinjaScript.NinjaScriptBase.get_CurrentBar()
                       at NinjaTrader.NinjaScript.Indicators.VsaIndicatorBase.dateString() in c:\Users\Bob\Documents\NinjaTrader 8\bin\Custom\AddOns\Vsa_IndicatorBase - Debug.cs:line 131
                       at NinjaTrader.NinjaScript.Indicators.VsaIndicatorBase.PrintEntry(String message) in c:\Users\Bob\Documents\NinjaTrader 8\bin\Custom\AddOns\Vsa_IndicatorBase - Debug.cs:line 184
                       at NinjaTrader.NinjaScript.Indicators.VsaIndicatorBase.Clone() in c:\Users\Bob\Documents\NinjaTrader 8\bin\Custom\AddOns\Vsa_IndicatorBase.cs:line 286
                       at NinjaTrader.Gui.Chart.ChartObjectCollection`1.Clone()
                       at NinjaTrader.Gui.Chart.ChartCommands.ReloadNinjaScriptExecuted(Object sender, ExecutedRoutedEventArgs e)
                       at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
                       at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
                       at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
                       at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
                       at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
                       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
                       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
                       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
                       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
                       at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
                       at NinjaTrader.Gui.Chart.ChartControl.<.ctor>b__12a(Object s, EventArgs e, ICommand c)
                       at NinjaTrader.Gui.Chart.ChartControl.OnReloadNinjaScriptHotKey(Object sender, KeyEventArgs e)
                       at NinjaTrader.Gui.HotKeys.HotKeysManager.TryChartHotKey(Object sender, KeyEventArgs e, IInputElement senderWindow, IInputElement ownerWindow)
                       at NinjaTrader.Gui.HotKeys.HotKeysManager.OnPreviewKeyDown(Object sender, KeyEventArgs e)
                       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
                       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
                       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
                       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
                       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
                       at System.Windows.Input.InputManager.ProcessStagingArea()
                       at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
                       at System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
                       at System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
                       at System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
                       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
                       at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
                    I take severe exception myself to having a method called on an already-destroyed instance. It does look as if the proximate problem here is trying to reference non-existent data, though.

                    In this case there is no such thing as valid data for that getter to return. Furthermore, as I have noted previously, cloning a getter makes no sense to begin with. Putting the problems in order:
                    1. How do I prevent cloning a getter property?
                    2. NT needs to fix whatever is allowing it to call Clone() on an already-destroyed object

                    --EV
                    Last edited by ETFVoyageur; 08-10-2015, 05:22 PM.

                    Comment


                      #11
                      Another data point: when the exception occurs Plots[] has two members, while Values[] has only one member. How can that be? As far as I know that is an inconsistency, should not happen, and:
                      • It could be an artifact of the instance being already destroyed
                      • It could be an NT error to get that way (assuming I do not deliberately delete an entry from Values[], which I most certainly do not do).

                      --EV

                      Comment


                        #12
                        Here's an update to the current state of affairs:
                        1. I commented out the contents of my Clone() override, since that is what hit an exception when an already-destroyed instance was called. I added one Print() statement to Print out the State when Clone() got called.
                        2. I thought it might be better if the getter passed back null when there is no valid data, so I changed it to do that (and, of course, adjusted my other code accordingly).

                        Now all seemed good -- my chart output looked like I expected, and there was no exception thrown. But, NOT SO FAST. Take a look at my (annotated) trace output.
                        Code:
                        // Object #1 is being destroyed
                        08/11/14  #1  Entry: VsaModelIndicator.DoStateChange()  (OnStateChange(Terminated) started, State.Terminated)  CurrentBar=248   C (Daily)
                        08/11/14 [B] #1[/B]  Exit:   VsaModelIndicator.DoStateChange()  (OnStateChange([B]Terminated[/B]) completed, [B]State.Terminated[/B])  CurrentBar=248   C (Daily)
                        
                        // The next line is printed by NT, it is not one of mine.  I also have no "OnCalculateMinMax", so I assume this line means there is an internal
                        // NT problem.  There well could be if it is running on a destroyed instance
                        [B]Indicator 'VsaModelIndicator': Error on calling 'OnCalculateMinMax' method on bar -1: Index was outside the bounds of the array.[/B]
                        
                        // At this point I hit "F5" to do a chart refresh.
                        
                        // Constructing a new object.  This is normal
                        19:32:27  #2  Entry: VsaModelIndicator.VsaModelIndicator()  (Constructor started , State.SetDefaults)  CurrentBar=n/a   <no instrument>
                        19:32:27  #2  Exit:   VsaModelIndicator.VsaModelIndicator()  (Constructor completed, State.SetDefaults)  CurrentBar=n/a   <no instrument>
                        19:32:27  #2  Entry: VsaModelIndicator.DoStateChange()  (OnStateChange(SetDefaults) started, State.SetDefaults)  CurrentBar=n/a   <no instrument>
                        19:32:27  #2  Exit:   VsaModelIndicator.DoStateChange()  (OnStateChange(SetDefaults) completed, State.SetDefaults)  CurrentBar=n/a   <no instrument>
                        
                        // In my experience,  it is normal for Clone() to update the new object from the old one at this point
                        // The following statement is from my minimal Clone() override, not risking using member functions
                        //          * The fact it is updating #2 from #1 is completely normal at this point
                        //          * What is[B] NOT NORMAL[/B] is that the object doing the updating has already been destroyed!
                        CLONING #2 from #1     [B]State=Finalized[/B]
                        
                        // #2 carries on normally from here
                        19:32:27  #2  Entry: VsaModelIndicator.DoStateChange()  (OnStateChange(Configure) started, State.Configure)  CurrentBar=n/a   C (Daily)
                        19:32:27  #2  Exit:   VsaModelIndicator.DoStateChange()  (OnStateChange(Configure) completed, State.Configure)  CurrentBar=n/a   C (Daily)
                        19:32:27  #2  Entry: VsaModelIndicator.DoStateChange()  (OnStateChange(DataLoaded) started, State.DataLoaded)  CurrentBar=n/a   C (Daily)
                        19:32:27  #2  Exit:   VsaModelIndicator.DoStateChange()  (OnStateChange(DataLoaded) completed, State.DataLoaded)  CurrentBar=n/a   C (Daily)
                        This would have thrown an exception if I had not gutted my Clone() method, because the code I removed accessed CurrentBar which throws when in this state.

                        Unless someone thinks of something I am missing, this is a HUGE NT BUG.

                        --EV
                        Last edited by ETFVoyageur; 08-10-2015, 10:18 PM.

                        Comment


                          #13
                          Originally posted by ETFVoyageur View Post
                          Here is the situation:
                          • My indicator can have either 1 or 2 plots (value and signal line). Therefore there are two Values[] accessor properties.
                          • It is currently compiled to have only the value plot enabled. AddPlot() gets done for the value plot, but no AddPlot() gets done for the signal line plot. Note that this is a static, compiled in, state. It is not some change I am making on the fly. Both Values[] and Plots[] have a length of 1, as they should.
                          • My own code knows enough to not call the accesor function for the signal line plot if there is no such plot.
                          • Breaking for an exception shows that the accessor property for the signal line is getting called anyway. The call stack shows only two things:
                          • (1) [External Code]
                          • (2) Signal plot accessor property Get method

                          Come on folks! Why is outside code calling my accesor property for a plot that does not exist?

                          This is the second sort of such thing I have seen in the last few days. I really need to know just what is going on.

                          As far as I am concerned, this is a show-stopping NT bug -- stuff I have no control over is making calls into my code when it should know better. It is calling for information on a plot that does not exist. The basic arrays are fine (Values[] and Plots[]). I really need help understanding what perverse logic is making such a bogus call on my code!

                          Perhaps one of the NT support people who monitor this forum could help? Please explain exactly when NT calls the Value[] accessor properties.

                          --EV
                          Sounds like you have detritus from an old compiled state. Did you ever have that second Plot enabled and compiled in?

                          Comment


                            #14
                            I exit an restart NT each time I compile.

                            My most recent, and easily reproducible, scenario is that it is a Clone() issue. The biggest concern at this moment is the traces, such as the one I posted this evening, showing that Clone() is being called on an already-destroyed object. That's not only an intellectual bad thing to do, but it is causing me to get exceptions from such innocent activities as accessing CurrentBar.

                            FWIW: I no longer think that NT is deliberately using the accessor/gettter properties. I believe they are called by Clone. One of the things I want to know is how to keep Clone from calling them, since they do not need cloning.

                            --EV
                            Last edited by ETFVoyageur; 08-11-2015, 12:54 AM.

                            Comment


                              #15
                              Originally posted by ETFVoyageur View Post
                              I exit an restart NT each time I compile.

                              --EV
                              I have come across cases when developing where that has not really gotten rid of the errors that I may have made. You may want to remove the compiled gumball completely and let NT generate a new one when it starts. That is the only sure way that I have found sometimes to get NT back to functioning, especially when I have made a mistake that royally hoses the system, and all my repair efforts are in vain.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by trilliantrader, 04-18-2024, 08:16 AM
                              4 responses
                              18 views
                              0 likes
                              Last Post trilliantrader  
                              Started by mgco4you, Today, 09:46 PM
                              1 response
                              7 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Started by wzgy0920, Today, 09:53 PM
                              0 responses
                              9 views
                              0 likes
                              Last Post wzgy0920  
                              Started by Rapine Heihei, Today, 08:19 PM
                              1 response
                              10 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Started by Rapine Heihei, Today, 08:25 PM
                              0 responses
                              10 views
                              0 likes
                              Last Post Rapine Heihei  
                              Working...
                              X