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

MySharedMethods: pass Highs/Lows,..., Instrument

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

    MySharedMethods: pass Highs/Lows,..., Instrument

    Hi, there is a reference to mySharedMethods script that can be placed in AddOns folder. I got that to work https://ninjatrader.com/support/foru...956#post733956

    How do you extend this file to allow it to use things like Highs, Lows without having to pass them like following all the time,
    ISeries<double> high, ISeries<double> low
    tedious to write and as it seems these objects cannot be passed by reference, possibly a performance hit. I like them available automatically without needing to invoke them in every method.

    Also how do I pass other important things like:
    Bars
    Instrument

    Thanks a lot. I created a new topic since the Subject of the referenced topic is non-related.

    #2
    Hello stevenev1,

    Thank you for your post.

    The link provided is a demonstration of using static in C#, this is a concept which you can use to expose items in C#. As this is a C# concept, I generally suggest to also read more about this subject from external C# resources as this is a complex subject. You can use a search engine to look up "static in C#" for some more information.

    This sample does not allow you to use the calling type directly like you are asking so you would need to pass in any objects you want to use as a parameter to that method. This sample is created this way specifically to share between an indicator and a strategy, is that your requirement as well or is this being used to share between two of the same type? The example you have linked cannot be extended to avoid passing in parameters you will need to pass in some values at the least. A partial class could avoid that requirement however that is limited to the same type such as two indicators.

    To pass any other types of objects, you would just need to create a parameter in the methods overloads (.... ) which accept the type you want to pass such as Bars.
    Code:
    MyMethodName(Bars myBars)
    For this question, I would also suggest researching C# Methods and Static in C# from external resources as that will help further explain how this is working along with the structure needed to form methods in C#.

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

    Comment


      #3
      Originally posted by NinjaTrader_Jesse View Post
      Hello stevenev1,

      ... is that your requirement as well or is this being used to share between two of the same type? The example you have linked cannot be extended to avoid passing in parameters you will need to pass in some values at the least. A partial class could avoid that requirement however that is limited to the same type such as two indicators.

      To pass any other types of objects, you would just need to create a parameter in the methods overloads (.... ) which accept the type you want to pass such as Bars.
      Code:
      MyMethodName(Bars myBars)
      Hi Jesse, thank you very much for detailed explanation. I just need to share common methods between indicators (not indicators and strategies).

      1.) Can you please provide a sample of a partial class that allows indicators to call common methods without needing to pass parameters such as High, Low. myPrint below is a good example. I use it in all my scripts and I wish for it to be in a common file.

      2) I very much appreciate the example MyMethodName(Bars myBars)

      I started with NT7. I had UserDefinedMethods and it was a simple matter to write methods in it, and everything was available. In NT8, no one has been able to tell me how I can share a simple method like the following across indicators, so I don't have to rewrite it or pass parameters. I would think I am no alone in needing to store common methods in a shared place without need to pass extensive list of parameters?

      private void myPrint( string Msg ) {
      Print( "[" + Instrument.FullName + "] " + Msg + " " + Time[0] );
      }
      Last edited by stevenev1; 03-15-2019, 12:05 PM.

      Comment


        #4
        Hello stevenev1,

        Thank you for your reply.

        Yes, in this case, using a partial class is much more simple because you can make a partial class of the base Indicator type which inherits the items you are using. UserDefinedMethods is just a partial class, this is the same concept NT8 just doesn't include that file any longer because you can just create this structure in a file named what you want.

        To start, create a new indicator and give it any name.
        Once the file opens, remove all of the code leaving only the namespace and using statements.
        In the namespace define a partial class:

        Code:
        namespace NinjaTrader.NinjaScript.Indicators
        {
            public partial class Indicator {
        
            }
        }
        You can then define methods or other items here:

        Code:
        namespace NinjaTrader.NinjaScript.Indicators
        {
            public partial class Indicator {
                public double MyCalcMethod(){
                    return Close[0];
                }
            }
        }
        In the indicator, you can just call the method:

        Code:
        protected override void OnBarUpdate()
        {
            Print(MyCalcMethod());
        }
        Keep in mind you need to include this file with your exports, and also this can be problematic if you plan to export as compiled assemblies in separate assemblies.

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

        Comment


          #5
          Hi Jesse,

          Your solution worked to perfection. Kudos to you and thank you. FYI, I have been chasing this solution for a year (as one can see from my prior posts), and finally you provided me the perfect answer. This issue was the single reason I was staying with NT7, and now I am fully committed to NT8 - a much improved software I hope others benefit from it as well.

          Comment


            #6
            I try to create a workaround for that:

            Code:
             
             [B][B]if (DrawObject("PASignalBarBreakoutFailureTick_Test") == null)[/B][/B]
            Code:
            // This namespace holds the classes for indicators
            namespace NinjaTrader.NinjaScript.Indicators
            {
                public partial class Indicator
                {
                      // Loops through the DrawObjects collection via a threadsafe list copy
                    public static string DrawObject(string DrawObjectTag)
                    {
                        foreach (DrawingTool draw in DrawObjects.ToList())
                        {
                            if (draw.Tag == DrawObjectTag)
                            {
                                return DrawObjectTag;
                            }
                        }
                        return null;
                    }
                }
            }
            this file MySharedMethods.cs resides in the indicators/My folder, is that correct
            I'm going to export all my indicators into a DLL

            Note: Methods within partial classes should be use the "public" and "static" modifiers, to allow for any other classes to invoke the methods without requiring an instance of the partial class.
            As soon as I add static to

            Code:
             
             [B][B]public[B] static [/B]string DrawObject(string DrawObjectTag)[/B][/B]
            I get the following error:
            An object reference is required for the non-static field, method, or property 'NinjaTrader.Gui.NinjaScript.IndicatorRenderBase.D rawObjects.get'

            and what about this
            From NT website?
            Warning: If a partial class is saved in one of the folders used for specific NinjaScript objects other than AddOns (e.g., Indicators folder), auto-generated NinjaScript code may be appended to the end of the class by the NinjaScript Editor when compiled, which will cause a compilation error. Saving these files in the AddOns folder will ensure they are still accessible and will not generate code which may be cause conflicts.

            Comment


              #7
              Hello td_910,

              this file MySharedMethods.cs resides in the indicators/My folder, is that correct
              Yes if this is an indicator, you can place the partial class inside the folder for its type however it is generally suggested to just place these items in the addons folder. You asked another question about this so I will detail that more in a moment.

              Note: Methods within partial classes should be use the "public" and "static" modifiers, to allow for any other classes to invoke the methods without requiring an instance of the partial class.
              I am not certain off-hand where this comment comes from, however, if this was from one of the Drawing object documentation pages, this would not apply to this situation. The Drawing objects use the Draw class which needs to be made static for that use case, where you call Draw.SomeToolName to create it. The error states the problem in your use case:
              An object reference is required for the non-static field, method, or property 'NinjaTrader.Gui.NinjaScript.IndicatorRenderBase.D rawObjects.get'
              We can read this as:
              An Instance is needed to use the non-static property DrawObjects.
              There is no instance being used here because the method is static, but the DrawObjects property being used require an instance of some indicator to be used.

              If you think about it this way, the partial class will assume the properties of the indicator calling it but when you make this method static that tells the compiler we dont need any indicator here to call the method. What would you expect DrawObjects apply to in that case where there is no specific indicator instance being used? You would instead need an indicator instance for an inherited property like DrawObjects or CurrentBar etc.. to be used in that context.

              The solution is just removing static from the method because this use case does not require it. I also suggest reviewing materials surrounding using static in C# to better understand when this should or should not be used if it is still foggy when this is needed, most often it will not be used.


              Warning: If a partial class is saved in one of the folders used for specific NinjaScript objects other than AddOns...
              This is correct although I do not currently see this happening when I test this. This may not occur for every script and is still relevant toward some use cases so I would suggest to heed the help guide warnings. Because you can use namespaces to delegate where a class is in your assembly, you can place the .cs files for most types in any of the folders (aside from indicators) and have it compile. The Addon's folder is a good place to put extra files to ensure NinjaTrader does not try to append indicator code to them. The note is specifically talking about a situation where the indicators NinjaScript generated code is added to your partial class file where it is not needed.

              I look forward to being of further assistance.



              JesseNinjaTrader Customer Service

              Comment


                #8
                Hi Jesse,

                thanks for answering my question and shedding some light onto "static". Yes, I'll always call, that method from inside an indicator.

                This was on the code breaking changes page https://www.screencast.com/t/EGwgWcTn
                I try to workaround this error: https://www.screencast.com/t/ZIRh1dh3

                I've put this code into file in the addon folder and it compiles without any error :-)

                Code:
                // This namespace holds the classes for indicators
                namespace NinjaTrader.NinjaScript.Indicators
                {
                    public partial class Indicator
                    {
                          // Loops through the DrawObjects collection via a threadsafe list copy
                        public string DrawObjectCheck(string DrawObjectTag)
                        {
                            foreach (DrawingTool draw in DrawObjects.ToList())
                            {
                                if (draw.Tag == DrawObjectTag)
                                {
                                    return DrawObjectTag;
                                }
                            }
                            return null;
                        }
                    }
                }

                Comment


                  #9
                  its a old thread but i would like to clarify something. I created a shared method for logging. However if i want to use this from the strategy, should i do another partial class for Strategy or is there a way that the strategy can call the same methods for logging?
                  Code:
                  using System;
                  
                  
                  namespace NinjaTrader.NinjaScript.Indicators
                  {
                  public partial class Indicator {
                  public void LogMessage(Object o){
                  
                  
                  }
                  public void LogException(Exception e){
                  
                  }
                  }
                  }

                  Comment


                    #10
                    Originally posted by stevenev1 View Post
                    I started with NT7. I had UserDefinedMethods and it was a simple matter to write methods in it, and everything was available. In NT8, no one has been able to tell me how I can share a simple method like the following across indicators, so I don't have to rewrite it or pass parameters. I would think I am no alone in needing to store common methods in a shared place without need to pass extensive list of parameters?

                    private void myPrint( string Msg ) {
                    Print( "[" + Instrument.FullName + "] " + Msg + " " + Time[0] );
                    }
                    One way to share a single method across every indicator (or strategy)
                    is by using an abstract base class.

                    Study this thread.

                    Comment


                      #11
                      Hi,
                      I am trying to use the same example a,m. in post # 1 to get information from a custom BarType script to a Strategy. Unfortunately I am not getting it to work.

                      Starting from the same examle, I added to BarType the following:
                      protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask)
                      {

                      double median = NinjaTrader.NinjaScript.BarsTypes.MySharedMethods. Median(high, low, 0);
                      Print("Median value: " + median);
                      etc.


                      and I changed the AddOn script the following way:

                      namespace NinjaTrader.NinjaScript.AddOns
                      {
                      public partial class MySharedMethods : NinjaTrader.NinjaScript.AddOnBase
                      {
                      public static double SharedDouble
                      { get; set; }
                      }
                      }

                      namespace NinjaTrader.NinjaScript.BarsTypes
                      {
                      public partial class BarType
                      {
                      public static double CalculateDelta(double firstPrice, double secondPrice)
                      {
                      return Math.Abs(firstPrice - secondPrice);
                      }

                      public class MySharedMethods
                      {
                      public static double Median(ISeries<double> high, ISeries<double> low, int barsAgo)
                      {
                      return (((high[barsAgo] - low[barsAgo]) / 2) + low[barsAgo]);
                      }
                      }
                      }
                      }​
                      .......
                      ​​

                      Unfortunately I get an error saying that "MySharedMethods" does not exist in the namespace NinjaTrader.NinjaScript.BarTypes.
                      Could you please help me to understand what my mistake is?

                      Thank you
                      Martin

                      Comment


                        #12
                        Hello Martin,

                        Check your namespace paths.

                        You have MySharedMethods declared in NinjaTrader.NinjaScript.Addons. Your call is to a different namespace. 'NinjaTrader.NinjaScript.BarsTypes.MySharedMethods . Median(high, low, 0);,

                        Call the Addons namespace where it is declared and not the BarsTypes namespace where nothing is declared.
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #13
                          Hello Chelsea,
                          thank you for your reply.
                          I understood my mistake.

                          Nevetheless I am not getting it to work.

                          In my custom BarType I put:
                          protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask)
                          {
                          NinjaTrader.NinjaScript.AddOns.MySharedMethods.Sha redDouble = 5;
                          ........


                          I then created a chart with that custom BarType.

                          Next step I run on the chart the strategy provided in the example, that includes
                          protected override void OnBarUpdate()
                          {
                          Print("SharedDouble value: " + NinjaTrader.NinjaScript.AddOns.MySharedMethods.Sha redDouble);

                          The Print value I get is 0, not 5. Could you please help me to get this value passed from my custom BarType?

                          Thank you and best regards
                          ​​​​​​​
                          Martin​




                          Comment


                            #14
                            Hello martin70,

                            I believe there is some confusion on the purpose of the MySharedMethodsAddonExample. That sample is not intended for data sharing, that is intended for the type being used to have the same methods included.

                            A C# partial class is a way to extend an existing class. That sample is extending the following two classes:

                            public partial class Indicator
                            public partial class Strategy

                            If we look at just the Indicator class it has a method CalculateDelta. What that does is makes it so any class that inherits from Indicator has the method CalculateDelta. That won't share data between indicators, that just makes that block of code available to each indicator individually. Its the same if that method was added into the indicators code.

                            For what you are trying to do you should remove the code you made based on MySharedMethodsAddonExample. Then do the following:

                            In the bars type define a new public double:

                            Code:
                            public double MySharedDouble {get;set;}
                            In your strategy access the bars type by casting it to the correct type:

                            Code:
                            NinjaTrader.NinjaScript.BarsTypes.MyBarsType barsType = Bars.BarsSeries.BarsType as
                            NinjaTrader.NinjaScript.BarsTypes.MyBarsType;
                            
                            if (barsType == null)
                            return;​
                            Print(barsType.MySharedDouble);
                            JesseNinjaTrader Customer Service

                            Comment


                              #15
                              That works!!
                              Thank you very much!
                              Martin

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by elirion, Today, 01:36 AM
                              0 responses
                              3 views
                              0 likes
                              Last Post elirion
                              by elirion
                               
                              Started by gentlebenthebear, Today, 01:30 AM
                              0 responses
                              2 views
                              0 likes
                              Last Post gentlebenthebear  
                              Started by samish18, Yesterday, 08:31 AM
                              2 responses
                              9 views
                              0 likes
                              Last Post elirion
                              by elirion
                               
                              Started by Mestor, 03-10-2023, 01:50 AM
                              16 responses
                              389 views
                              0 likes
                              Last Post z.franck  
                              Started by rtwave, 04-12-2024, 09:30 AM
                              4 responses
                              33 views
                              0 likes
                              Last Post rtwave
                              by rtwave
                               
                              Working...
                              X