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

Global Partial Class

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

    Global Partial Class

    Hi!

    I want to have a custom Stop Calculator that I can use across all my strategies. So, in my Strategies I want to use have something like StopCalculator.MoneyValue to return a specific double value and stopCalculator.PercentValue to return another duble value.

    I know there is a CalculationMode Object already built in NinjaScript but I want my custom Stop Calculator to add specific things to it.

    Here is my SampleCustomClass:

    Code:
    #region Using declarations
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Gui.SuperDom;
    using NinjaTrader.Gui.Tools;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.Gui.Tools;
    #endregion
    
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public partial class StopCalculator : Strategy
        {
            double myStopValue;
            public double MoneyValue(double Stop)
            {
                return myStopValue = Stop / Bars.Instrument.MasterInstrument.PointValue;
            }
            public double PercentValue(double Stop)
            {
                return myStopValue = Stop * Bars.Instrument.MasterInstrument.PointValue * TickSize;
            }
        }
    }​
    I then created a Strategy called SampleMACrossOverX and instantiated an object StopCalculator and added a Print statement to print the MoneyValue and the PercentValue.

    Code:
    //
    // Copyright (C) 2022, NinjaTrader LLC <www.ninjatrader.com>.
    // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
    //
    #region Using declarations
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Gui.SuperDom;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.Indicators;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion
    
    //This namespace holds strategies in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public partial class SampleMACrossOverX : Strategy
        {
            private StopCalculator stopCalc;
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description    = NinjaTrader.Custom.Resource.NinjaScriptStrategyDescriptionSampleMACrossOver;
                    Name        = "SampleMACrossOverX";
                    // This strategy has been designed to take advantage of performance gains in Strategy Analyzer optimizations
                    // See the Help Guide for additional information
                    IsInstantiatedOnEachOptimizationIteration = false;
                }
                else if (State == State.Configure)
                {
                    stopCalc = new StopCalculator();
                }
            }
    
            protected override void OnBarUpdate()
            {
                if (CurrentBar < BarsRequiredToTrade)
                    return;
    
                Print(String.Format("{0};{1};{2}", Time[0], stopCalc.MoneyValue(1000), stopCalc.PercentValue(0.01)));
            }
    
        }
    }
    ​
    However I am getting an error when running the strategy: "Strategy 'SampleMACrossOverX': Error on calling 'OnBarUpdate' method on bar 20: Object reference not set to an instance of an object."

    What am I doing wrong?

    Thanks in advance!

    #2
    Hi Kirk, thanks for writing in. You made StopCalculator a partial class but there is no initial declaration of "StopCalculator" to make a partial class included as a Strategy, do:

    Code:
    namespace NinjaTrader.NinjaScript.Strategies
    {
    public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
    {
    double myStopValue;
    public double MoneyValue(double Stop)
    {
    return myStopValue = Stop / Bars.Instrument.MasterInstrument.PointValue;
    }
    }
    }


    Please let me know if this does not resolve.
    Chris L.NinjaTrader Customer Service

    Comment


      #3
      Hi Chris!

      Thanks this worked out. In my Strategy now I can directly access MoneyValue() because the class is as you suggested named "Strategy". However, I would like to have a class "StopCalculator" to bring more structure into it. So I want to call StopCalculator.MoneyValue() in my Strategy. Is there any way I can do this?

      Thank you very much!

      Comment


        #4
        Another suggestion is organize your code using an abstract base class.

        Good reading (with example code) is here and here.

        Comment


          #5
          Hi Kirk, thanks for the follow up. You can make a .cs file in the Documents\NinjaTrader 8\bin\Custom\AddOns, then make a class under the strategy namespace or a custom namespace.

          Take the class you made in the first post, and modify it to be its own class, then pass in the StrategyBase object to use things from the StrategyBase.
          public class StopCalculator
          {
          public double MoneyValue(double Stop, StrategyBase sb)
          {
          return myStopValue = Stop / sb.Bars.Instrument.MasterInstrument.PointValue;
          }

          }
          Chris L.NinjaTrader Customer Service

          Comment


            #6
            Hi!

            @NinjaTrader_ChrisL

            I am sorry, but I didn't get what you mean here. This seems to be different from how inheritance and creating classes in C# usually work, so I am a bit stuck here.

            So I changed my SampleCustomClass as follows:
            Code:
            namespace NinjaTrader.NinjaScript.Strategies
            {
                public class StopCalculator
                {
                    double myStopValue;
                    public double MoneyValue(double Stop, StrategyBase sb)
                    {
                        return myStopValue = Stop / sb.Bars.Instrument.MasterInstrument.PointValue;
                    }
                    public double PercentValue(double Stop, StrategyBase sb)
                    {
                        return myStopValue = Stop * sb.Bars.Instrument.MasterInstrument.PointValue * sb.TickSize;
                    }
                }
            }​
            Then in my Strategy the code is as follows
            Code:
            namespace NinjaTrader.NinjaScript.Strategies
            {
                public class SampleMACrossOverX : Strategy
                {
                    private StopCalculator stopCalc;
            
                    protected override void OnStateChange()
                    {
                        if (State == State.SetDefaults)
                        {
                            Description    = NinjaTrader.Custom.Resource.NinjaScriptStrategyDescriptionSampleMACrossOver;
                            Name        = "SampleMACrossOverX";
                            // This strategy has been designed to take advantage of performance gains in Strategy Analyzer optimizations
                            // See the Help Guide for additional information
                            IsInstantiatedOnEachOptimizationIteration = false;
                        }
                        else if (State == State.Configure)
                        {
                            stopCalc = new StopCalculator();
                        }
                    }
            
                    protected override void OnBarUpdate()
                    {
                        if (CurrentBar < BarsRequiredToTrade)
                            return;
            
                        Print(String.Format("{0};{1};{2}", Time[0], stopCalc.MoneyValue(1000, Bars.Instrument.MasterInstrument.PointValue)));
                    }
            
                }
            }​}​
            But this doesn't work. What should I do in the AddOns folder? And how is this connected to my StopCalculator class? And what do I pass to sb when calling stopCalc.Moneyvalue?

            bltdavid
            How do you structure a lot of different classes? If Iwant to structure code into several classes and use these classes in all my strategies, how do you do this? Make a chain of inheriting abstract classes?

            My point is: I don't want to create a StopCalculator1 double and StopCalculator2 double etc. I want "StopCalculator." to give me the list 1, 2 etc. Do you have a solution here? Other than that abstract classes work very good.

            Comment


              #7
              Hi Kirk, thanks for the follow up.

              You will make a .cs file within the Addons folder to hold the custom class code, then StrategyBase is the strategy object to get the Bars and another context. I posted my test code if you would like to try it. This is not supported code, so I will not be able to go further into this topic unless its directly related to our NinjaScript library.

              CustomClass.cs goes into Documents\NinjaTrader 8\bin\Custom\AddOns
              MyCustomStrategy.cs goes into Documents\NinjaTrader 8\bin\Custom\Strategies.

              Kind regards,
              -ChrisL​
              Attached Files
              Chris L.NinjaTrader Customer Service

              Comment


                #8
                Hi Chris, thank you very much for your help, this works just as expected. I created a constructor with a StrategyBase Parameter in the CustomClass, so it is not necessary to pass "this" in the Strategy for every single method / variable but only when creating the StopCalculator Object in the Strategy.

                So the code looks as follows if someone else is interested how to do it.

                Custom Class (saved like any other Strategy)
                Code:
                #region Using declarations
                using System;
                using System.Collections.Generic;
                using System.ComponentModel;
                using System.ComponentModel.DataAnnotations;
                using System.Linq;
                using System.Text;
                using System.Threading.Tasks;
                using System.Windows;
                using System.Windows.Input;
                using System.Windows.Media;
                using System.Xml.Serialization;
                using NinjaTrader.Cbi;
                using NinjaTrader.Gui;
                using NinjaTrader.Gui.Chart;
                using NinjaTrader.Gui.SuperDom;
                using NinjaTrader.Gui.Tools;
                using NinjaTrader.Data;
                using NinjaTrader.NinjaScript;
                using NinjaTrader.Core.FloatingPoint;
                using NinjaTrader.Gui.Tools;
                #endregion
                
                namespace NinjaTrader.NinjaScript.Strategies
                {
                    public class StopCalculator
                    {
                        double myStopValue;
                        public StrategyBase sb;
                
                        public StopCalculator(StrategyBase myStrategyBase)
                        {
                            sb = myStrategyBase;
                        }
                
                        public double MoneyValue(double Stop)
                        {
                            return myStopValue = Stop / sb.Bars.Instrument.MasterInstrument.PointValue;
                        }
                        public double PercentValue(double Stop)
                        {
                            return myStopValue = Stop * sb.Bars.Instrument.MasterInstrument.PointValue * sb.TickSize;
                        }
                    }
                }​
                CustomStrategy
                Code:
                //
                // Copyright (C) 2022, NinjaTrader LLC <www.ninjatrader.com>.
                // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
                //
                #region Using declarations
                using System;
                using System.Collections.Generic;
                using System.ComponentModel;
                using System.ComponentModel.DataAnnotations;
                using System.Linq;
                using System.Text;
                using System.Threading.Tasks;
                using System.Windows;
                using System.Windows.Input;
                using System.Windows.Media;
                using System.Xml.Serialization;
                using NinjaTrader.Cbi;
                using NinjaTrader.Gui;
                using NinjaTrader.Gui.Chart;
                using NinjaTrader.Gui.SuperDom;
                using NinjaTrader.Data;
                using NinjaTrader.NinjaScript;
                using NinjaTrader.Core.FloatingPoint;
                using NinjaTrader.NinjaScript.Indicators;
                using NinjaTrader.NinjaScript.DrawingTools;
                #endregion
                
                //This namespace holds strategies in this folder and is required. Do not change it.
                namespace NinjaTrader.NinjaScript.Strategies
                {
                    public class SampleMACrossOverX : Strategy
                    {
                        private StopCalculator stopCalc;
                
                        protected override void OnStateChange()
                        {
                            if (State == State.SetDefaults)
                            {
                                Description    = NinjaTrader.Custom.Resource.NinjaScriptStrategyDescriptionSampleMACrossOver;
                                Name        = "SampleMACrossOverX";
                                // This strategy has been designed to take advantage of performance gains in Strategy Analyzer optimizations
                                // See the Help Guide for additional information
                                IsInstantiatedOnEachOptimizationIteration = false;
                            }
                            else if (State == State.Configure)
                            {
                                stopCalc = new StopCalculator(this);
                            }
                        }
                
                        protected override void OnBarUpdate()
                        {
                            if (CurrentBar < BarsRequiredToTrade)
                                return;
                
                            Print(stopCalc.MoneyValue(1000));
                        }
                
                    }
                }​

                Just for my understanding: Why did you suggest to save the CustomClass to the AddOns folder? It works the same when it is in the Strategies folder.

                Thanks a lot for your help again! This was exactly what I was looking for!
                Last edited by KirkHammett; 12-08-2022, 06:48 AM.

                Comment


                  #9
                  Hi Kirk, its just for organization, you can place this file anywhere you would like.
                  Chris L.NinjaTrader Customer Service

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by geddyisodin, Yesterday, 05:20 AM
                  7 responses
                  45 views
                  0 likes
                  Last Post NinjaTrader_Gaby  
                  Started by gbourque, Today, 06:39 AM
                  2 responses
                  5 views
                  0 likes
                  Last Post gbourque  
                  Started by cre8able, Yesterday, 07:24 PM
                  1 response
                  13 views
                  0 likes
                  Last Post NinjaTrader_ChelseaB  
                  Started by cocoescala, 10-12-2018, 11:02 PM
                  6 responses
                  939 views
                  0 likes
                  Last Post Jquiroz1975  
                  Started by cmtjoancolmenero, Yesterday, 03:58 PM
                  1 response
                  18 views
                  0 likes
                  Last Post NinjaTrader_Gaby  
                  Working...
                  X