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

Collection was modified

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

    #46
    your welcome

    would this be an appropriate method?


    Code:
    if (DrawObject("PASignalBarBreakoutFailureTick_Test") == 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

    Code:
    namespace NinjaTrader.NinjaScript.Indicators
    {
        public partial class Indicator
        {
            public string DrawObject(string DrawObjectTag)
            {
                foreach (DrawingTool draw in DrawObjects.ToList())
                {
                    if (draw.Tag == DrawObjectTag)
                    {
                        return DrawObjectTag;
                    }
                }
                return null;
            }
        }
    }
    What about this?
    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:
    public[B] static [/B]string DrawObject(string DrawObjectTag)
    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'


    behavior in the test indicator:
    reloading historical data doesn't find the manually drawn object, reload NinjaScript works, probably because of that

    "When reloading NinjaScript, all objects (including manual drawing tools) are reloaded at the same time. There is no guarantee a manually drawn object will be added to the DrawObjects collection before an indicator starts processing data."

    I'll use a workaround in that case
    Last edited by td_910; 04-12-2019, 03:15 PM.

    Comment


      #47
      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.

      I'm trying to release five indicators on the Ecosystem, but don't want to start without the NT8 versions
      the NT7 versions are working flawless since a while, the only problem, that's left is THIS one

      Comment


        #48
        Hello td_910,

        Thanks for your patience.

        It looks like our colleague ChelseaB was able to come to a solution for this in this thread:



        It's likely that the manually drawn objects are not showing up in this list at the time you check for them. Waiting for the first real time bar would resolve this since the script will have accounted for all draw objects by that time.
        Chris L.NinjaTrader Customer Service

        Comment


          #49
          Thanks. Yes, I saw his reply. I made a workaround with a property that can be set by the user.

          But what about "normal" null checks during OBU (on objects drawn by the same indicator, that does the null check) on historical data.
          Are they thread safe? Or do I need to use this workaround?

          e.g. on b200 I check if there is an object on b197 and check it's content
          this is a typical code in all my indicators:

          Code:
                          #region -----------  2nd 1/2/3 tF
                          if (xTF==1 || xTF==2 || xTF==3)
                              for (int i = 2; i <= 4; i++)
                              {
                                  if (DrawObjects[xTF.ToString("N0")+"tF_Long" + (CurrentBar-i)] != null)
                                  {
                                      dynamic Prior_xtF_Text = DrawObjects[xTF.ToString("N0")+"tF_Long" + (CurrentBar-i)];
          
                                      if (Prior_xtF_Text.ToString().Equals("NinjaTrader.NinjaScript.DrawingTools.Text"))
                                          if (Prior_xtF_Text != null)
                                          {
                                              if (Body()[0]>0 && !(Prior_xtF_Text.DisplayText.Contains("2nd")) && !(xtF_Long.Contains("fEB")) && Low[i] < Low[0] && CountIf(delegate {return Low[2] > Low[1];}, i-1) <1)
                                              {
                                                  Draw.Text(this, xTF.ToString("N0")+"tF_Long"+CurrentBar, true, "2nd\n"+xtF_Long, 0, Low[0], -offset, fontColor, myFontSmallBold, TextAlignment.Center, Brushes.Transparent, ChartControl.Properties.ChartBackground, 100);
                                              }
                                          }
                                  }
                                  if (i>=Bars.BarsSinceNewTradingDay && Bars.BarsType.IsIntraday) break;
                              }
                          #endregion


          This share method code compiles without any error, placed in the indicator directory.

          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.NinjaScript.DrawingTools;
          #endregion
          
          // 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;
                  }
              }
          }
          Making that method dynamic should create a new list every time it's called?
          I also want to export my indicators as a DLL

          And can this file reside in the indicator directory?

          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.
          Last edited by td_910; 04-15-2019, 08:08 AM.

          Comment


            #50
            And one funny thing, this code has never thrown an exception, its in all my indicators

            Code:
                        else if (State == State.Configure)
                        {
                            //Label PriceActionIndicators
                            if (ChartControl != null && DrawObjects["PriceActionIndicators"] == null)
                                Draw.TextFixed(this, "PriceActionIndicators", "PriceActionIndicators.com", TextPosition.BottomLeft, ChartControl.Properties.ChartText,
                                  ChartControl.Properties.LabelFont, Brushes.Transparent, Brushes.Transparent, 0);
                        }

            Comment


              #51
              posted in the wrong thread


              I still do not have an answer, regarding the DrawObjects.ToList() question


              and if I have to use that for ANY null check of ANY object type regardless of user drawn or not in OnBarUpdate

              I'm no programmer, that's why I was a bit confused reading this in the code breaking changes:


              for sure that method cannot be static, because then I have the same problem, of being not thread safe

              because, that is what I want to achieve with that workaround of a shared method I posted a bit further up
              having a thread safe DYNAMIC list copy each time I'm doing a null check without getting an exception

              Code:
              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


                #52
                Hello td_910,

                Thanks for your reply. You can make a static class within the Addons namespace and pass in the DrawObject list. When you export the strategy, include the addon that contains the static class/static method that evaluates the DrawObjects array. In the example I posted, I would include "TextExltraMethod" as well as "ExtraMethod when I export".

                The C# compiler will automatically pass the list into the ExtraMethod class by reference, so that will not impact performance if the list is large. Calling ToList() will create a new copy, so if the list is large a slight performance hit will be taken. While executing the "DrawObjectCheck", a performance problem can also occur while looping through the list if the list is large

                To import the sample, go to Tools>Import>NinjaScript addon.

                Please let me know If I can assist any further.
                Attached Files
                Last edited by NinjaTrader_ChrisL; 04-15-2019, 02:25 PM.
                Chris L.NinjaTrader Customer Service

                Comment


                  #53
                  Hi Chris,

                  many thanks for your code. Using the method from the AddOn in a code snippet would look like this?

                  Code:
                  //old code
                  
                  if (DrawObjects[xTF.ToString("N0")+"tF_Short"+(CurrentBar)] == null ||
                      DrawObjects[xTF.ToString("N0")+"tF_Above_Prior_Bar"+(CurrentBar-1)] != null)
                  
                  //translates to:
                  
                  //in var define the list  
                  List<IDrawingTool> theList = new List<IDrawingTool>();
                  
                  //refresh list before each check            
                  theList = DrawObjects.ToList();
                  
                  if (ExtraMethod.DrawObjectCheck(theList, xTF.ToString("N0")+"tF_Short"+(CurrentBar)) == null ||
                      ExtraMethod.DrawObjectCheck(theList, xTF.ToString("N0")+"tF_Above_Prior_Bar"+(CurrentBar-1)) != null)
                  Would it make a difference to have a dynamic method, that re-freshs the list inside the method and has only one argument?
                  (more uncluttered look)

                  Thanks

                  Thomas
                  Last edited by td_910; 04-16-2019, 08:34 AM.

                  Comment


                    #54
                    Hello td_910,

                    Thanks for your reply.

                    I found a way to make the DrawObjects collection available from the custom method. We can still have files whos namespace belongs to the Indicators and hold them in the Addons folder so the NinjaScript generated code does not get generated. You can place the attached file within your NinjaTrader/bin/custom/Addons folder and it will work the same.

                    Attached Files
                    Chris L.NinjaTrader Customer Service

                    Comment


                      #55
                      If I ever make it to Denver, I owe you a beer :-)

                      Comment

                      Latest Posts

                      Collapse

                      Topics Statistics Last Post
                      Started by fx.practic, 10-15-2013, 12:53 AM
                      5 responses
                      5,406 views
                      0 likes
                      Last Post Bidder
                      by Bidder
                       
                      Started by Shai Samuel, 07-02-2022, 02:46 PM
                      4 responses
                      98 views
                      0 likes
                      Last Post Bidder
                      by Bidder
                       
                      Started by DJ888, Yesterday, 10:57 PM
                      0 responses
                      8 views
                      0 likes
                      Last Post DJ888
                      by DJ888
                       
                      Started by MacDad, 02-25-2024, 11:48 PM
                      7 responses
                      160 views
                      0 likes
                      Last Post loganjarosz123  
                      Started by Belfortbucks, Yesterday, 09:29 PM
                      0 responses
                      9 views
                      0 likes
                      Last Post Belfortbucks  
                      Working...
                      X