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

Shared class/method/structure sample

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

    Shared class/method/structure sample

    Hi,

    I have a complex indicator that I need to simplify by separating out a lot of my code into separate files. I am having difficulties separating out the code. Instead of asking partial/pointed questions, I have created a full sample. There are three notable attributes of this sample.
    1. This sample performs some performance calculations passing Price to methods and classes.
    2. I also want to separate my code by placing it in separate folders & namespaces.
    3. I also posted the code on Github and determined a method to version just my folders and not other indicator/addon code.

    - See: https://github.com/eTradeTeam/NinjaSamples or the attached NinjaSamples.zip. You will need to place the code in the Indicators and Addons folder manually. Note, the GitHub files Addons/ExampleAddon/ExIndicShare and Indicators/Example/IndicEx1 and Indicators/Example/IndicEx2 are not part of this sample. I will be creating another post using these for shared objects between indicators.

    Issue #1: I can't create a folder under Indicators and Addons with the same name. i.e. Indicators/Example and Addons/Example. I get an error that a folder with the same name already exists. I am a novice C# programmer. I would think these would be different namespaces. NinjaTrader.NinjaScript.Indicators.Example should be different than NinjaTrader.NinjaScript.Addons/Example. Question #1. So is this normal in C# or is it a nuance of the NinjaScript Editor?

    Issue #2: My indicator can see the methods I enclosed in a class, but not the methods I in the exPerfMethods file.
    Question #2: What am I missing? I think this should work.

    Thanks in advance, JeffCO
    Attached Files
    Last edited by JeffCO7; 08-31-2021, 12:07 AM.

    #2
    Hello JeffCO7,


    Issue #1: I can't create a folder under Indicators and Addons with the same name
    That would be expected and correct, the platform delegates the folders based on how it works with namespaces, at this time only 1 unique folder name can be used throughout all of the NinjaScript types. If you have multiple items from different types I would suggest avoiding folders and just naming them in a similar way so they appear in the lists alphabetically.

    Issue #2: My indicator can see the methods I enclosed in a class, but not the methods I in the exPerfMethods file.
    The classes are stored in the addon namespace but are for indicators. You would generally place any indicator partial classes inside the indicator namespace and also within the indicator folder.

    Code:
    namespace NinjaTrader.NinjaScript.Indicators
    {
    public partial class Indicator // or the indicators specific type
    {
    If you are still having difficulty I would suggest making a more simplified sample. What you provided has multiple files/logical paths/regions/comments etc which may make it more difficult to follow. Creating a new empty indicator with nothing inside and then a new empty file for your partial class omitting anything which is not needed like regions/comments/extra logic etc would be the suggestion for samples.


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

    Comment


      #3
      Thanks Jesse,

      I appreciate the clarifications. The NinjaTrader reference in the "code breaking changes" section directs partial classes to be put in the Addons directory. I am ok if this is not true. However, it does lead to confusion.

      I am still running into issues. I have restructured the code as suggested. I removed the #regions and unnecessary comments. I also put all the files in Indicator/Examples instead of having some in the Addons directory. I am getting the following error:

      Click image for larger version

Name:	Screenshot 2021-09-01 064651.png
Views:	403
Size:	15.4 KB
ID:	1169826

      This is caused by the "public partial class Indicator" section in the exMethods.cs file. If I comment this section out, it all works fine - except that the required methods are not available. Is this a "feature" of the Ninjascript editor?


      Comment


        #4
        Hello JeffCO7,

        I took a look at the sample however with the current complexity I don't see what the problem is. You would need to debug that code to find the error or make a more simple test to find the difference. here is a very simple test demonstrating using a partial class of a type. The partial class could also exist in a separate file based on how C# compiles multiple .cs files at compile time, for the purpose of demonstration its all together.

        Code:
        namespace NinjaTrader.NinjaScript.Indicators
        {
           public partial class TestPartialClassIndicator
           {
              public void SomeMethod(){}
           }
           public partial class TestPartialClassIndicator : Indicator
           {
              protected override void OnStateChange()
              {
                       SomeMethod();
              }
        
              protected override void OnBarUpdate()
              {
        
               }
            }
        }


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

        Comment


          #5
          Thanks Jesse,

          My goals were:
          1. Maintain my indicators separate from other indictor code (indicator subfolders / namespaces)
          2. Pull methods and classes out of my indicators to into common files
          3. Create a sample to implements multiple use cases for future reference.
          I found that some partial classes will not work in a sub namespace. That was my issue. It caused errors that seemed unrelated to the change in the code I made.
          • NinjaTrader.NinjaScript.Indicators.SplitCode.Split CodeIndic.OnStateChange(): no suitable method found to override
          • NinjaTrader.NinjaScript.Indicators.SplitCode.Split CodeIndic.OnBarUpdate(): no suitable method found to override

          Attached is the result. Place the SplitCode folder in Indicators folder.
          Attached Files
          Last edited by JeffCO7; 09-01-2021, 10:37 PM.

          Comment


            #6
            Here are my performance comparisons.

            Calling an indicator takes about 50 times as long as calling a method or even a method within another class. A Series cannot be declared in a class. But passing a Series is possible. A series can be passed by reference in a method but not in a class. See the attached examples for more clarity.

            CODE]
            ---------------------------------- End Summary: 50Bars -----------------------------------
            Method A ------- pass struct -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 49 Bars
            Method B ------- pass Series -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 49 Bars
            Method C ------- pass Series Reference ---- Duration: 19.512us for 50 Iterations/Bar averaged over 49 Bars
            Method C ------- pass ISeries ------------- Duration: 19.992us for 50 Iterations/Bar averaged over 49 Bars
            Class Method A - pass struct -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 49 Bars
            Class Method B - pass Series -------------- Duration: 20.096us for 50 Iterations/Bar averaged over 49 Bars
            Class Method D - pass ISeries ------------- Duration: 19.730us for 50 Iterations/Bar averaged over 49 Bars
            Indicator - unique params/iteration -- Duration: 959.984us for 50 Iterations/Bar averaged over 49 Bars
            Indicator - same params/iteration ---- Duration: 20.050us for 50 Iterations/Bar averaged over 49 Bars
            ---------------------------------- End Summary -----------------------------------

            ---------------------------------- End Summary: 100Bars -----------------------------------
            Method A ------- pass struct -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 99 Bars
            Method B ------- pass Series -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 99 Bars
            Method C ------- pass Series Reference ---- Duration: 39.617us for 50 Iterations/Bar averaged over 99 Bars
            Method C ------- pass ISeries ------------- Duration: 19.522us for 50 Iterations/Bar averaged over 99 Bars
            Class Method A - pass struct -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 99 Bars
            Class Method B - pass Series -------------- Duration: 10.048us for 50 Iterations/Bar averaged over 99 Bars
            Class Method D - pass ISeries ------------- Duration: 50.420us for 50 Iterations/Bar averaged over 99 Bars
            Indicator - unique params/iteration -- Duration: 479.992us for 50 Iterations/Bar averaged over 99 Bars
            Indicator - same params/iteration ---- Duration: 10.025us for 50 Iterations/Bar averaged over 99 Bars
            ---------------------------------- End Summary -----------------------------------

            ---------------------------------- End Summary: 500Bars -----------------------------------
            Method A ------- pass struct -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 499 Bars
            Method B ------- pass Series -------------- Duration: 1.996us for 50 Iterations/Bar averaged over 499 Bars
            Method C ------- pass Series Reference ---- Duration: 21.762us for 50 Iterations/Bar averaged over 499 Bars
            Method C ------- pass ISeries ------------- Duration: 30.043us for 50 Iterations/Bar averaged over 499 Bars
            Class Method A - pass struct -------------- Duration: 2.023us for 50 Iterations/Bar averaged over 499 Bars
            Class Method B - pass Series -------------- Duration: 9.924us for 50 Iterations/Bar averaged over 499 Bars
            Class Method D - pass ISeries ------------- Duration: 35.769us for 50 Iterations/Bar averaged over 499 Bars
            Indicator - unique params/iteration -- Duration: 97.903us for 50 Iterations/Bar averaged over 499 Bars
            Indicator - same params/iteration ---- Duration: 12.665us for 50 Iterations/Bar averaged over 499 Bars
            ---------------------------------- End Summary -----------------------------------

            ---------------------------------- End Summary: 1000Bars -----------------------------------
            Method A ------- pass struct -------------- Duration: 0.000us for 50 Iterations/Bar averaged over 999 Bars
            Method B ------- pass Series -------------- Duration: 5.916us for 50 Iterations/Bar averaged over 999 Bars
            Method C ------- pass Series Reference ---- Duration: 13.955us for 50 Iterations/Bar averaged over 999 Bars
            Method C ------- pass ISeries ------------- Duration: 22.954us for 50 Iterations/Bar averaged over 999 Bars
            Class Method A - pass struct -------------- Duration: 4.100us for 50 Iterations/Bar averaged over 999 Bars
            Class Method B - pass Series -------------- Duration: 12.881us for 50 Iterations/Bar averaged over 999 Bars
            Class Method D - pass ISeries ------------- Duration: 63.875us for 50 Iterations/Bar averaged over 999 Bars
            Indicator - unique params/iteration -- Duration: 53.985us for 50 Iterations/Bar averaged over 999 Bars
            Indicator - same params/iteration ---- Duration: 11.244us for 50 Iterations/Bar averaged over 999 Bars
            ---------------------------------- End Summary -----------------------------------

            ---------------------------------- End Summary: 5000Bars -----------------------------------
            Method A ------- pass struct -------------- Duration: 0.802us for 50 Iterations/Bar averaged over 4999 Bars
            Method B ------- pass Series -------------- Duration: 11.598us for 50 Iterations/Bar averaged over 4999 Bars
            Method C ------- pass Series Reference ---- Duration: 11.339us for 50 Iterations/Bar averaged over 4999 Bars
            Method C ------- pass ISeries ------------- Duration: 24.993us for 50 Iterations/Bar averaged over 4999 Bars
            Class Method A - pass struct -------------- Duration: 2.420us for 50 Iterations/Bar averaged over 4999 Bars
            Class Method B - pass Series -------------- Duration: 15.939us for 50 Iterations/Bar averaged over 4999 Bars
            Class Method D - pass ISeries ------------- Duration: 33.821us for 50 Iterations/Bar averaged over 4999 Bars
            Indicator - unique params/iteration -- Duration: 15.579us for 50 Iterations/Bar averaged over 4999 Bars
            Indicator - same params/iteration ---- Duration: 7.164us for 50 Iterations/Bar averaged over 4999 Bars
            ---------------------------------- End Summary -----------------------------------

            ---------------------------------- End Summary: 5500Bars -----------------------------------
            Method A ------- pass struct -------------- Duration: 0.729us for 50 Iterations/Bar averaged over 5499 Bars
            Method B ------- pass Series -------------- Duration: 10.898us for 50 Iterations/Bar averaged over 5499 Bars
            Method C ------- pass Series Reference ---- Duration: 11.241us for 50 Iterations/Bar averaged over 5499 Bars
            Method C ------- pass ISeries ------------- Duration: 25.458us for 50 Iterations/Bar averaged over 5499 Bars
            Class Method A - pass struct -------------- Duration: 2.200us for 50 Iterations/Bar averaged over 5499 Bars
            Class Method B - pass Series -------------- Duration: 15.777us for 50 Iterations/Bar averaged over 5499 Bars
            Class Method D - pass ISeries ------------- Duration: 33.638us for 50 Iterations/Bar averaged over 5499 Bars
            Indicator - unique params/iteration -- Duration: 14.339us for 50 Iterations/Bar averaged over 5499 Bars
            Indicator - same params/iteration ---- Duration: 7.050us for 50 Iterations/Bar averaged over 5499 Bars
            ---------------------------------- End Summary -----------------------------------
            9/13/2021 12:18:24 PM>>> Indicator: PerformanceTests OnStateChange: 5 BarNum:5600 >>> Current State is State.Transition
            9/13/2021 12:18:24 PM>>> Indicator: PerformanceTests OnStateChange: 6 BarNum:5600 >>> Current State is State.Realtime

            ---------------------------------- End Summary: 5581Bars -----------------------------------
            Duration: 125.423us for 50 Iterations/bar averaged over 5600 Bars
            ---------------------------------- End Summary -----------------------------------



            [/CODE]

            I would appreciate feedback if I really missed the boat on my approach here.
            Attached Files
            Last edited by JeffCO7; 09-23-2021, 12:09 AM.

            Comment


              #7
              Hello JeffCO7,

              I am not certain what you are asking for feedback on here. Are you seeing an error or are you asking about why calling an indicator call takes longer than a custom method call?

              Please let me know if I may be of additional assistance.

              JesseNinjaTrader Customer Service

              Comment


                #8
                Originally posted by JeffCO7 View Post

                I would appreciate feedback ...

                I am new to NinjaTrader and interested in some of the same topics.


                1) At a high level I am not surprised at your results. Though the indicator performance delta can vary greatly dependent upon indicator design.


                2) Possible additional options to test --- ISeries
                I have been wondering and have not yet tested if defining a DataSeries as ISeries<> rather than Series>< with security set to public or even better "protected internal" would allow the the passing of the ISeries interface to a peer or child class? Maybe you have already tested these.



                3) Possible additional options to test --- Parent-Child options, independently or combined.

                I realize "child class" may not be the first phrase that comes to mind when your pursuing a shared data design but thought regardless you might want to see this text.

                .
                3.1) Assuming their "base" class was not an abstract class -- In 2009 & 2011 on a significantly different incarnation of NT it seems that at least two developers saw some parent objects success by including parent indicator or strategy object within a child's constructor which might reduce the size, GC and CPU load of calls between and provide better access to the parent's objects.
                2011 https://ninjatrader.com/support/foru...293#post426293

                2) Just exploring ideas from more recent posts on the forum I saw some success rough prototyping Parent-Child classes where the children each had their own full OnStateChange() initialization process and independent isolated event handlers.
                Fast, incomplete testing of children showed they direct access to at least a subset of the same resources owned by or used by the parent and also had the data object and event management isolation I was seeking to help simplify the code base.

                The children also had some access to execute the parents event handlers. For example in the the last line of the Child's OnBarUpdate() I included calls to the parent's OnBarUpdate() event handler. So I could monitor and act on both the child's and the parent's OBU() events..

                Here is the post that started that exploration https://ninjatrader.com/support/foru...046#post701046




                HedgePlay
                Last edited by hedgeplay; 09-13-2021, 12:25 PM.

                Comment


                  #9
                  Sorry for my absence. Other priorities took me off task for a while.

                  @Jesse,

                  Thank you. I don't require any feedback. I feel it is important to complete my example and post the results instead of taking the nuggets I learned and dropping the thread. So many posts here help only the author with a problem and no one else on the forum. It would be good to see that culture change.

                  @ hedgeplay,
                  1) I used the same code in all methods and the indicator. I should post more results as fewer iterations showed less difference in the results.
                  2) Some of the methods pass Series, others pass ISeries. So the performance results are there. However, I am open to any constructive criticism as to my method for calculating the performance. I will edit the previous post to add more performance results.
                  3) I am interested in this approach. Are you saying this might be a good way to share data between indicators?

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by set2win, 08-04-2021, 09:23 AM
                  39 responses
                  1,001 views
                  0 likes
                  Last Post WaleeTheRobot  
                  Started by md4866, Today, 08:15 PM
                  0 responses
                  8 views
                  0 likes
                  Last Post md4866
                  by md4866
                   
                  Started by mjbatts91, Yesterday, 04:48 PM
                  2 responses
                  23 views
                  0 likes
                  Last Post mjbatts91  
                  Started by pibrew, Today, 06:10 PM
                  1 response
                  22 views
                  0 likes
                  Last Post NinjaTrader_Manfred  
                  Started by actualfacts.2021, 07-25-2021, 03:11 PM
                  8 responses
                  1,188 views
                  0 likes
                  Last Post linkcou
                  by linkcou
                   
                  Working...
                  X