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

How to best structure indicators which are computationally intensive

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

    How to best structure indicators which are computationally intensive

    NT Forum,
    I’m hoping you can assist with an approach to the below problem.
    I have two indicators, for ease of reference IndA and IndB:
    • They are both computationally intensive.
    • They are both have outputs that are used at a Strategy level
    • I now require IndB to access one output from IndA.
    • The output from IndA is updated at a specified frequency (e.g. on bar 200, 400, 600 etc.)

    If my understanding is correct, I have several options:
    1. In IndB, add an instance of IndA.
      IndB could access the required output from IndA. However, where a Strategy references both IndA and IndB, computation time will likely blow out as IndA will effectively calculate twice (once as IndA and again as a part of IndB).
    2. Introduce a third umbrella indicator, IndC, and pass the outputs of IndA and IndB through to IndC.
      IndB could access the required output from IndA. A Strategy would refer only to IndC. However, as IndA and IndB are separate and distinct it seems jamming them into a single indicator for convenience is a poor solution.
    3. In IndA, use StreamWriter to “export” the required data. In IndB, use StreamReader to import the required data (I have found the NT examples but have not used the approach previously).
      IndB could access the required output from IndA. Where a Strategy references both IndA and IndB, computation time should only increase by Stream write / read.
      As a secondary issue,
      • Should IndA write output values once at State.Terminated(?) and IndB read output values once at State.DataLoaded(?)? IndA would be required to effectively calculate twice, once to generate and write the output, then again as IndB reads the output.
      • Should IndA write output values and IndB read output values as they are generated (e.g. on bar 200,400,600)? How could you ensure the IndA StreamWriter is closed and the latest values are present?
    4. A much better option I am not yet aware of.

    I hope the above clearly states my predicament. Given options 1-3 each have significant drawbacks, I am hoping there is a forth option I am not aware of.

    As always any insight, ideas or guidance would be appreciated.

    Thanks
    Shannon

    #2
    Originally posted by Shansen View Post
    NT Forum,
    I’m hoping you can assist with an approach to the below problem.
    [*]They are both computationally intensive.
    How computationally intensive? 30 seconds per call? 5 minutes?

    What are your hardware specs? If you are dual core even with H/T....

    Comment


      #3
      A fair question. Yes, the machine is dual core and parts of the Indicators execute in parallel.

      To your point, I concede a potential solution is to ensure both Indicators execute efficiently. To the best of my ability this is the case, noting a more skilled coder would find ways to improve it.

      I remain happy to to have my understanding corrected or hear suggestions of how to address my predicament..

      Comment


        #4
        Hello Shansen,

        Thank you for your post.

        I would run with the first option you presented. Although, I would instantiate Indicate A in Indicator B to prevent it from running a new instance each time it is called. Below is an example of instantiating another indicator.

        On the third option (if used) you would be unable to read from the file if it is only written during State.Terminate. The Terminated State would not be called if the indicator was being called in another indicator. Terminated would only be called when the indicator is disabled (removed from the chart for example).

        To ensure the file is done being written you can call StreamWriter.Close(): https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx

        Once closed you could create an exposed variable that Indicator B can call to see if the writed has closed. You can find an example of exposed variables at the following link: http://ninjatrader.com/support/forum...ead.php?t=4991

        On when to close the StreamWriter in Indicator A, you could wait until State.RealTime to ensure all historical bars are processed. Or if you have a specific time or event you wish to wait for in OnBarUpdate().

        Code:
        	public class ExampleInstantiateSecondaryIndicator : Indicator
        	{
        		
        		private SMA anotherIndicator;
        		
        		protected override void OnStateChange()
        		{
        			if (State == State.SetDefaults)
        			{
        				Description									= "";
        				Name										= "ExampleInstantiateSecondaryIndicator";
        				Calculate									= Calculate.OnBarClose;
        			}
        			else if (State == State.DataLoaded)
        			{
        				anotherIndicator = SMA(10);
        			}
        		}
        
        		protected override void OnBarUpdate()
        		{
        			Print(anotherIndicator[0]);
        		}
        	}
        Please let me know if you have any questions.

        Comment


          #5
          PatrickH,

          Thank you for your clear explanation.

          Thinking further on your preferred option, option #1, where IndicatorA is instantiated in IndicatorB, is it possible / advisable to break IndicatorA into two components?

          As mentioned previously, IndicatorA is... large. However, the element in IndicatorA that is required by IndicatorB (and other Indicators) while not trivial does not require all of IndicatorA to calculate. With this, would it be possible / advisable to:
          - reduce IndicatorA to the bare essentials, "IndicatorACutDown", to generate the element required by IndicatorB, then
          - re-construct the full IndicatorA, "IndicatorAFullVersion", inheriting from "IndicatorACutdown".

          What would this look like? Would it require a new Indicator or just be contained in the same .cs file:
          Code:
          namespace NinjaTrader.NinjaScript.Indicators
          {
            public class IndicatorACutDown: Indicator
            {
            }
            public class IndicatorAFullVersion : IndicatorACutDown
            {
            }
          }
          Alternatively, would it be better to add a (optional) parameter, "IsFullVersion", to the existing IndicatorA. By littering the various methods with if statements referencing "IsFullVersion", it would be possible to create a CutDown version and speed calculation.

          As always, any ideas / insight is greatly appreciated.
          Shannon

          Comment


            #6
            Originally posted by Shansen View Post
            ...
            Alternatively, would it be better to add a (optional) parameter, "IsFullVersion", to the existing IndicatorA. By littering the various methods with if statements referencing "IsFullVersion", it would be possible to create a CutDown version and speed calculation.

            As always, any ideas / insight is greatly appreciated.
            Shannon
            Along those lines, neater would be to use a public string property, IsCalledFrom which is by default empty or specifically filled. This will be in the called indicator.

            You check this value, and if it is not the default, you do not run the code in that block.

            Any calling indicator should fill the IsCalledFrom property of the called indicator. That way, if you forget to fill the property in the calling indicator, there is "no harm, no foul", but if the calling indicator changes the IsCalledFrom property, you do not call unnecessary code in the called indicator.

            Comment


              #7
              Hello Shansen,

              Thank you for your response.

              You could just add another parameter to your indicatorA that when called from another indicator or strategy you can set the overload to one of two options. A bool would work here as well.

              In your indicatorA code you would check the value of the parameter before processing the rest of the code.

              Please let me know if you have any questions.

              Comment


                #8
                PatrickH & Koganam thank you both for your input.

                Another question on a similar line. I understand the NT8 - Drawing Methods to draw custom shapes, lines, text etc. can be programatically intensive. Happy to have my understanding corrected.

                When a Strategy featuring Drawing methods, or an Indicator featuring Drawing methods, is applied on a Chart the execution of said Drawing methods adds to the total time to calculate the Strategy or Indicator. That is, the execution of Drawing methods exacts a performance hit.

                When the same Strategy featuring Drawing methods is applied via the Control Center window (i.e. not via a Chart), does the execution of Drawing methods still exact a performance hit? Further, when a Strategy featuring Indicators which feature Drawing methods is applied via the Control Center or a Chart, does the execution of Drawing methods still exact a performance hit?

                Where the performance hit exists, I may look to implement another parameter a boolean or public string IsDisplayed in a similar vein to Koganam's IsCalledFrom. Alternatively, would it be possible to ascertain, as part of a Strategy's (or Indicator's) State.Configure or State.DataLoaded, whether it had been applied to a chart and thus required Drawing methods and thus set a public boolean variable (e.g. IsDisplayed) for later reference.

                Again, thank you
                Shannon
                Last edited by Shansen; 05-17-2017, 05:14 AM.

                Comment


                  #9
                  Originally posted by Shansen View Post
                  PatrickH & Koganam thank you both for your input.

                  Another question on a similar line. I understand the NT8 - Drawing Methods to draw custom shapes, lines, text etc. can be programatically intensive. Happy to have my understanding corrected.

                  When a Strategy featuring Drawing methods, or an Indicator featuring Drawing methods, is applied on a Chart the execution of said Drawing methods adds to the total time to calculate the Strategy or Indicator. That is, the execution of Drawing methods exacts a performance hit.

                  When the same Strategy featuring Drawing methods is applied via the Control Center window (i.e. not via a Chart), does the execution of Drawing methods still exact a performance hit? Further, when a Strategy featuring Indicators which feature Drawing methods is applied via the Control Center or a Chart, does the execution of Drawing methods still exact a performance hit?

                  Where the performance hit exists, I may look to implement another parameter a boolean or public string IsDisplayed in a similar vein to Koganam's IsCalledFrom.

                  Again, thank you
                  Shannon
                  I cannot really speak to NT8, as I have not looked too hard at its innards yet, but in NT7, drawing objects checked to be sure that they were being applied to a chart, or they did not run their code. I should hope that it is the same in NT8.

                  Regardless, even in NT7, I always checked that my code was on a chart before I would run code for drawing objects. When I start coding in NT8 in earnest, I shall probably use the same attack.

                  Comment


                    #10
                    Hello Shansen,

                    Thank you for your response.

                    koganam is correct here for NT 7 and this would apply to NT 8 as well.

                    Originally posted by koganam View Post
                    I cannot really speak to NT8, as I have not looked too hard at its innards yet, but in NT7, drawing objects checked to be sure that they were being applied to a chart, or they did not run their code. I should hope that it is the same in NT8.

                    Regardless, even in NT7, I always checked that my code was on a chart before I would run code for drawing objects. When I start coding in NT8 in earnest, I shall probably use the same attack.

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by funk10101, Today, 09:43 PM
                    0 responses
                    6 views
                    0 likes
                    Last Post funk10101  
                    Started by pkefal, 04-11-2024, 07:39 AM
                    11 responses
                    37 views
                    0 likes
                    Last Post jeronymite  
                    Started by bill2023, Yesterday, 08:51 AM
                    8 responses
                    44 views
                    0 likes
                    Last Post bill2023  
                    Started by yertle, Today, 08:38 AM
                    6 responses
                    26 views
                    0 likes
                    Last Post ryjoga
                    by ryjoga
                     
                    Started by algospoke, Yesterday, 06:40 PM
                    2 responses
                    24 views
                    0 likes
                    Last Post algospoke  
                    Working...
                    X