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

Multiple Instances of an Indicator sharing variable values

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

    Multiple Instances of an Indicator sharing variable values

    I have created a simple Indicator with one class that contains one string variable that is initialized to a value of "initialized." During State.Configure, I check if the value of that variable is equal to "initialized" and if so, I set it to something else. When I add a second instance of the Indicator to the same chart, it changes the variable value in the first instance of the Indicator. I've attached the Indicator. Can you tell me why the second Indicator can do this?

    VariableIssues.zip


    #2
    Hello swcooke,

    it changes the variable value in the first instance of the Indicator
    I don't see how you are currently confirming this, can you detail what you are doing to know the first instance has its variable changed? I see you are printing in State.Configure, however, if the indicator was already applied how are you now determining the second instance has changed the first?

    One observation is that you create the object outside of your OnStateChange in the general class scope, this should likely be moved into OnStateChange to comply with the state system:

    Code:
    public class Foo{
        public string Bar = "initialized";    
    }
    
    private Foo myFoo;
    
    protected override void OnStateChange()
    {
        if (State == State.SetDefaults)
        {
    
    
    
        }
        else if (State == State.Configure){
            myFoo = new Foo();
            if(myFoo.Bar == "initialized"){
                myFoo.Bar = "new value";
                Print(myFoo.Bar);
            }
        }
    }

    Is the overall goal to not share the variable and you are seeing the sharing happen, or are you specifically trying to create a shared value?

    I look forward to being of further assistance.
    JesseNinjaTrader Customer Service

    Comment


      #3
      Take a look at this video:
      https://drive.google.com/file/d/1RFF...ew?usp=sharing

      I guess the question is, why does "new-value" Print to the output window twice when the indicator is added a second time? It should only print once for the newly added instance of the Indicator since the value of the variable in the first instance is already "new value". Instead, it seems the new instance is changing the value of that variable for both instances and then it prints twice.
      Last edited by swcooke; 05-06-2019, 10:20 AM.

      Comment


        #4
        Hello swcooke,

        Thank you for the video that helps explain the problem. In this case, I think the problem is your expectation of what should be happening, both indicator instances will be reloaded when you press OK on the dialog.

        You should see that both instances run through configure and both are set to initialized because you do that at the class level so the condition should generally always be true every time the script runs.

        I would not expect an indicator to retain its values if you open the indicator dialog and add/remove/click OK or use the F5 to reload. What your expectation resembles is how "static modifiers" work in C#, however, I would not suggest using static modifiers, resetting as you have shown is how indicators are intended to operate.

        Another way to visualize this would be to add a print in OnStateChange to see the first instance is terminated when clicking OK before you see your print again. This is also a good way to just see how the scripts states progress when being applied in various locations.


        Code:
        protected override void OnStateChange()
        {
            Print(State);
        }
        I look forward to being of further assistance.
        JesseNinjaTrader Customer Service

        Comment


          #5
          I still don't understand. Take a look at this video which simplifies what I am expecting a little further:

          Comment


            #6
            Hello swcooke,

            I believe to better answer this question, you will need to read both the OnStateChange help guide section for the following comment in addition to Understanding the lifecycle of NinjaScript objects.




            The help guide mentions what you are seeing specifically in this new test:


            Viewing any UI element which lists NinjaScript classes (such as the Indicators or Strategies window, a chart's Chart Style dropdown menu, etc.) will initialize all classes of that Type when it is opened, which causes each script to enter State.SetDefaults, even if it is not actively configured or running in any window. It is important to keep this in mind when adding logic within State.SetDefaults in OnStateChange(), as this logic will be processed each time the script is initialized. For example, opening the Indicators window will trigger State.SetDefaults for all indicators in the system, and closing the Indicators window will trigger State.Terminated for all Indicators. In addition, disconnecting or connecting to a data provider can cause State transitions for any currently active scripts. Further discussion of this aspect of the state change model can be found via Understanding the lifecycle of your NinjaScript objects.


            In the video, you are now demonstrating a different print because this is in SetDefaults which happens at different times than Configure. You are still seeing the expected output here.

            When opening the menu, a new instance of your script is created (not the same as the one on the chart). This is to collect defaults to display in the indicator window. You can ignore this print as this is not a valid test, you are simply letting yourself know when some background instances are created to collect defaults. This really has nothing to do with the applied instance and will only confuse the test you are doing further.

            Going back to the Configure condition you have, every time you click OK on the indicator window after adding or removing an item, the instances that were on the chart are terminated and reapplied. This means a new instance is then created and reloaded which is why you see the print again. Your indicator was removed, a new instance was added and recalculates, this also entails the class level variable you have is reset to the default you have defined.

            There should be no expectation that an indicator will retain its values in this use case, it would recalculate each time it is reapplied or any time any other item is applied.


            I look forward to being of further assistance.

            JesseNinjaTrader Customer Service

            Comment


              #7
              Maybe if I explain what I'm trying to do, it will make things easier to understand. Your help guide mentions that if you're going to do a license check in with a server, to just do it once during State. Configure. So that's what I'm trying to do. I'm making a call during State.Configure to my server and having the script send my server a license code that I issued to the user. Once the license code has been checked I am trying to set a variable on that specific instance of the indicator so that it does not check again if another instance of the indicator is added. I'd rather not use the NT Licensing tool.

              Comment


                #8
                Originally posted by swcooke View Post
                Maybe if I explain what I'm trying to do, it will make things easier to understand. Your help guide mentions that if you're going to do a license check in with a server, to just do it once during State. Configure. So that's what I'm trying to do. I'm making a call during State.Configure to my server and having the script send my server a license code that I issued to the user. Once the license code has been checked I am trying to set a variable on that specific instance of the indicator so that it does not check again if another instance of the indicator is added. I'd rather not use the NT Licensing tool.
                It sounds like you will need a separate boolean flag to gate your operation. As reference, I will post a link to somewhat the same situation that happened to me, albeit in State.Terminated. I was not satisfied with the resolution that NT chose, but I had to concede that it is their product, and they can do whatever they want, my or any other programmer/developer's opinion notwithstanding.

                ref: https://ninjatrader.com/support/foru...ate.Terminated
                https://ninjatrader.com/support/foru...ect-life-cycle

                But, in all truth, at least they finally wrote some pretty thorough explanation, as documentation: ref: https://ninjatrader.com/support/foru...ect-life-cycle
                Last edited by koganam; 05-06-2019, 12:00 PM.

                Comment


                  #9
                  Hello swcooke,

                  If your code is in State.Configure, that would be what it is doing already.

                  You are not affecting other instances variables by adding a second instance. Adding the second instance will refresh the first instance because they are on the same chart and you have updated the indicators collection so now the indicators need to recalculate.

                  Your code will need to be planned to allow for multiple reloads. Your license check will happen once when you apply the first script, and again when you apply the second script but also for the second script as well. You should see 3 checks/prints in this use case of applying 1 instance, then later applying a second.

                  The first instance, although it may have at one point run through configure and set its internal variable, has now been terminated and reapplied. Its variables are no longer set and the instance has started over from SetDefaults. It will proceed like it was just applied for the first time and it will need to run through its OnStateChange and set the variable again.

                  I believe your expectation of what is wanted is getting in the way of how the platform actually operates and keeping you stuck here:

                  Once the license code has been checked I am trying to set a variable on that specific instance of the indicator so that it does not check again if another instance of the indicator is added.
                  This would not be possible, or to have the first instance not react when adding a new indicator to the chart. You are adding a second script to the chart, this means the chart will call all indicators to recalculate. Your script would need to plan on working this way as well and complete the license check in State.Configure to set its variable.

                  Another way to look at this would be if a user has 5 of the same script applied to a chart, you can expect 5 unique calls to the license code because 5 instances were applied. Adding a 6th instances to the chart will terminate the existing 5 scripts an cause them to reload. This will produce the 5 calls again, in addition to the new 6th script.





                  Please let me know if I may be of further assistance.
                  JesseNinjaTrader Customer Service

                  Comment


                    #10
                    Is there anything about the actual instance of the Indicator that remains unique from the time it is initially added until the time it is removed? For instance, if the indicator had some kind of unique id, it could be used as the key of a dictionary and stored in a text file or something. The user koganam commented above that I need to set an additional bool flag. How would I do that if that flag would also not be saved? I am not sure I understand the design pattern that koganam is referring to.

                    Comment


                      #11
                      Hello swcooke,

                      What is the reason that you need a unique value to remain the same for your check?

                      At this point, it may be helpful to provide the specific reason that brought up this question as it seems that your design goal may not work in line with how indicator instances work. Could you explain in more detail why the license check needs to be done one time only for each instance or why a unique value from the indicator is needed here? It would not likely be suggested to try and tie one of the indicators vales in this way, it would instead be suggested to just run this code each time your indicator has its Configure state called.

                      I am not sure what koganam was referring to with the bool idea, rather than putting words in their mouth I will let koganam follow up on that part.


                      I look forward to being of furtehr assistance.
                      JesseNinjaTrader Customer Service

                      Comment


                        #12
                        When a user adds my Indicator, I send an HTTPS post request with a (machine ID that I create) to my server to make sure he is licensed. If so, I respond with a unique ID that is given to the indicator. I store that ID along with the Machine ID on my server and that is what allows me to keep the indicators from being used on multiple machines.This is a very common approach to software licensing. If he opens the Indicator window to add another instance of the indicator, there is no reason for the first indicator, which already has a cookie, to check in again. If he did, what if he had 5 indicators in the chart? Each time he thinks about adding a Volume Indicator I have to checkin 5 times? Only additionally added Indicators need to checkin. Are you saying there is no way for an indicator instance (which is still remaining in the chart and has not been explicitly removed) to maintain the value of a simple string variable when other indicators are added? This seems incredibly inflexible. What do other developers do in this case?

                        To put this even simpler, I need a way to mark an Indicator as having already checked in. I was using a simple string and initializing it to "new-session." When a user added the indicator and I did my license check in, I changed that string to the unique ID the server responds with. This way, in State.Configure, as long as the value of this string was not "new-session", I knew not to send another https request.
                        Last edited by swcooke; 05-06-2019, 01:23 PM.

                        Comment


                          #13
                          Originally posted by swcooke View Post
                          The user koganam commented above that I need to set an additional bool flag. How would I do that if that flag would also not be saved? I am not sure I understand the design pattern that koganam is referring to.
                          Admittedly, the threads are long, but you will see if you read through them, that the protest you are making was the exact same one that I made, about how the State handling code was being run, The long documented explanation of the code life-cylce explains the convolutions that NT chose to use.

                          It is all in the persistent running of that "State" handling code in the indicator and the many clones generated. The only difference is that my code was in State.Terminated, but yours is in State.Configure. Reading the documentation on the matter might just shed some light.

                          I still think that using the boolean flag is a kludgy workaround, but if they (NT) were, as clearly stated in the thread, not willing to reconsider the design when we were in active beta, I am more than certain that they are not going to change the State handling code/method now. Then again, I am always willing to use a kludge if it gets my code to do what I want. I guess that it must be because I started programming many eons ago, when just about everything, required what we would today think of as a kludge. Remember 16-bit assembly language? What about FORTRAN? LOL.Now that I do OOP, I just cringe, comment the code to remind myself of just how kludgy I have been, and get on with it.
                          Last edited by koganam; 05-06-2019, 02:58 PM.

                          Comment


                            #14
                            Thanks for your reply koganam. I read the links that you shared and I see no mention of a bool flag being used as a workaround. I even searched the pages for "bool" and "flag." Can you offer a simple example?

                            Comment


                              #15
                              Originally posted by swcooke View Post
                              Thanks for your reply koganam. I read the links that you shared and I see no mention of a bool flag being used as a workaround. I even searched the pages for "bool" and "flag." Can you offer a simple example?
                              Take a look at this particular post by NT Project Management. As I admit, it is a rather long thread, with a lot of back of forth argments/discussion. It can be hard to see the forest, for the trees.

                              ref: https://ninjatrader.com/support/foru...970#post727970

                              You can always scroll backwards from that post, to get the immediate context.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by pmachiraju, 11-01-2023, 04:46 AM
                              8 responses
                              147 views
                              0 likes
                              Last Post rehmans
                              by rehmans
                               
                              Started by mattbsea, Today, 05:44 PM
                              0 responses
                              5 views
                              0 likes
                              Last Post mattbsea  
                              Started by RideMe, 04-07-2024, 04:54 PM
                              6 responses
                              33 views
                              0 likes
                              Last Post RideMe
                              by RideMe
                               
                              Started by tkaboris, Today, 05:13 PM
                              0 responses
                              4 views
                              0 likes
                              Last Post tkaboris  
                              Started by GussJ, 03-04-2020, 03:11 PM
                              16 responses
                              3,282 views
                              0 likes
                              Last Post Leafcutter  
                              Working...
                              X