Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Indicator sometimes crashes the program

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

    Indicator sometimes crashes the program

    Hi, I'm looking for some help with indicator that I made and realy realy like but it sometimes crashes whole NT8, not allowing me to even check Error Log or smth.
    It's definitely not optimized well, and I would ask for some advices on that.

    Yesterday it worked without any crash. Today my chart loaded missing part of the bars - I had to reload all historical data, after doing that it crashed the program. Then I had to try to open NT8 4 times until it sucessfuly loaded. Other 3 times it crashed during opening. There was once a time when I had to open NT8 in saf mode and remove this indicator completely.

    The idea of this indicator is - it projects Text symbol "-" above or below bar based on the distance between the close of the bar and Ray Line that is the closest to this bar (it represents support or resistance). It recognizes when the Ray starts.

    It works great, I love it, but sometimes it crashes whole program...

    ***EDIT: Now it crashed after I tried to add Bar Counter indicator to the chart... There was even no Ray on the chart at the moment of crash. No levels projected, plain chart. Tried again after that and no problem this time.

    Code:
    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.Indicators;
    using NinjaTrader.NinjaScript.DrawingTools;
    
    namespace NinjaTrader.NinjaScript.Indicators
    {
        public class AAASR : Indicator
        {
            private SimpleFont symbolFont;
            private DateTime lastRayUpdateTime = DateTime.MinValue;
    
            [NinjaScriptProperty]
            [Range(1, int.MaxValue)]
            [Display(Name = "Max Bars Back", Order = 1)]
            public int MaxBarsBack { get; set; } = 102;
    
            [NinjaScriptProperty]
            [Display(Name = "Require Ray Lines", Order = 2)]
            public bool RequireRayLines { get; set; }
            
            [NinjaScriptProperty]
            [Display(Name = "Use Extremes (Low/High)", Order = 3)]
            public bool UseExtremes { get; set; }
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description = "Support/Resistance Levels with Ray Lines";
                    Name = "AAASR";
                    Calculate = Calculate.OnBarClose;
                    IsOverlay = true;
                    DisplayInDataBox = true;
                    DrawOnPricePanel = true;
                    PaintPriceMarkers = true;
                    ScaleJustification = ScaleJustification.Right;
                    IsSuspendedWhileInactive = true;
                    UseExtremes = false;
                }
                else if (State == State.Configure)
                {
                    symbolFont = new SimpleFont("Arial", 8) { Bold = false };
                }
                else if (State == State.Historical)
                {
                    ClearOutputWindow();
                }
            }
    
            protected override void OnBarUpdate()
            {
                try
                {
                    if (CurrentBar < 1) return;
                    
                    // Only process recent bars to improve performance
                    if (CurrentBar < Count - Math.Min(256, MaxBarsBack)) return;
    
                    DateTime barTime = Time[0];
                    double referencePriceUp = UseExtremes ? Low[0] : Close[0];  // Use low for projection Up
                    double referencePriceDown = UseExtremes ? High[0] : Close[0]; // Use High for projection down
    
                    // Check if any Ray lines have been moved
                    bool raysChanged = CheckForRayLineChanges();
                    
                    // Find relevant Ray lines for this specific bar
                    double refLow = FindRelevantRayBelow(referencePriceUp, barTime, out bool hasRayBelow);
                    double refHigh = FindRelevantRayAbove(referencePriceDown, barTime, out bool hasRayAbove);
    
                    if (RequireRayLines)
                    {
                        // Only draw UP levels if there's a Ray below the reference price
                        DrawUpLevels(referencePriceUp, refLow, hasRayBelow);
                        
                        // Only draw DOWN levels if there's a Ray above the reference price
                        DrawDownLevels(referencePriceDown, refHigh, hasRayAbove);
                    }
                    else
                    {
                        // When not requiring Ray lines, use previous bar's high/low as reference
                        if (refLow <= 0) refLow = Low[0];
                        if (refHigh <= 0) refHigh = High[0];
                        
                        DrawUpLevels(referencePriceUp, refLow, true);
                        DrawDownLevels(referencePriceDown, refHigh, true);
                    }
    
                    if (raysChanged)
                    {
                        lastRayUpdateTime = DateTime.Now;
                    }
                }
                catch (Exception ex)
                {
                    Log("Error in OnBarUpdate: " + ex.Message, LogLevel.Error);
                }
            }
    
    [ATTACH=JSON]{"data-align":"none","data-size":"full","data-attachmentid":1340284}[/ATTACH]
            private double FindRelevantRayBelow(double price, DateTime barTime, out bool found)
            {
                found = false;
                double nearest = 0;
    
                foreach (var obj in DrawObjects)
                {
                    if (obj is Ray ray && ray.Tag?.StartsWith("Ray") == true &&
                        ray.StartAnchor.Price == ray.EndAnchor.Price)
                    {
                        double rayPrice = ray.StartAnchor.Price;
                        DateTime rayTime = ray.StartAnchor.Time;
                        
                        if (rayPrice < price && rayPrice > nearest && rayTime <= barTime)
                        {
                            nearest = rayPrice;
                            found = true;
                        }
                    }
                }
                return nearest;
            }
    
            private double FindRelevantRayAbove(double price, DateTime barTime, out bool found)
            {
                found = false;
                double nearest = double.MaxValue;
    
                foreach (var obj in DrawObjects)
                {
                    if (obj is Ray ray && ray.Tag?.StartsWith("Ray") == true &&
                        ray.StartAnchor.Price == ray.EndAnchor.Price)
                    {
                        double rayPrice = ray.StartAnchor.Price;
                        DateTime rayTime = ray.StartAnchor.Time;
                        
                        if (rayPrice > price && rayPrice < nearest && rayTime <= barTime)
                        {
                            nearest = rayPrice;
                            found = true;
                        }
                    }
                }
                return found ? nearest : 0;
            }
    
            private void DrawUpLevels(double referencePrice, double refLow, bool shouldDraw)
            {
                try
                {
                    double oneRup = referencePrice + (referencePrice - refLow);
                    double twoRup = referencePrice + 2 * (referencePrice - refLow);
    
                    Brush up1RBrush = shouldDraw ? Brushes.Lime : Brushes.Transparent;
                    Brush up2RBrush = shouldDraw ? Brushes.White : Brushes.Transparent;
    
                    Draw.Text(this, "UP_1R" + CurrentBar, false, "—", 0, oneRup, 0, up1RBrush, symbolFont, TextAlignment.Center, null, null, 0);
                    Draw.Text(this, "UP_2R" + CurrentBar, false, "—", 0, twoRup, 0, up2RBrush, symbolFont, TextAlignment.Center, null, null, 0);
                }
                catch (Exception ex)
                {
                    Log("Error in DrawUpLevels: " + ex.Message, LogLevel.Error);
                }
            }
    
            private void DrawDownLevels(double referencePrice, double refHigh, bool shouldDraw)
            {
                try
                {
                    double oneRdown = referencePrice - (refHigh - referencePrice);
                    double twoRdown = referencePrice - 2 * (refHigh - referencePrice);
    
                    Brush down1RBrush = shouldDraw ? Brushes.Red : Brushes.Transparent;
                    Brush down2RBrush = shouldDraw ? Brushes.White : Brushes.Transparent;
    
                    Draw.Text(this, "DOWN_1R" + CurrentBar, false, "—", 0, oneRdown, 0, down1RBrush, symbolFont, TextAlignment.Center, null, null, 0);
                    Draw.Text(this, "DOWN_2R" + CurrentBar, false, "—", 0, twoRdown, 0, down2RBrush, symbolFont, TextAlignment.Center, null, null, 0);
                }
                catch (Exception ex)
                {
                    Log("Error in DrawDownLevels: " + ex.Message, LogLevel.Error);
                }
            }
    
            private bool CheckForRayLineChanges()
            {
                foreach (var obj in DrawObjects)
                {
                    if (obj is Ray ray && ray.Tag?.StartsWith("Ray") == true)
                    {
                        if (ray.StartAnchor.Time > lastRayUpdateTime ||
                            ray.EndAnchor.Time > lastRayUpdateTime)
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
    
            private void ClearOutputWindow()
            {
                foreach (var drawObject in DrawObjects.ToList())
                {
                    if (drawObject is DrawingTools.Text text &&
                        (text.Tag.StartsWith("UP_") || text.Tag.StartsWith("DOWN_")))
                    {
                        RemoveDrawObject(text.Tag);
                    }
                }
            }
        }
    }​
    Click image for larger version  Name:	image.png Views:	0 Size:	5.0 KB ID:	1340283
    Last edited by Pabulon; 04-11-2025, 03:39 AM.

    #2
    It seems that your primary issue might be resource usage. Personally, I would probably start by using my own collection rather than DrawObjects.You don't need to iterate over it for every bar update, especially if you just need a subset.

    Comment


      #3
      Hello Pabulon,

      As a tip, to export a NinjaTrader 8 NinjaScript so this can be shared and imported by the recipient do the following:
      1. Click Tools -> Export -> NinjaScript Add-on...
      2. Click the 'add' link -> check the box(es) for the script(s) and reference(s) you want to include
      3. Click the 'Export' button
      4. Enter the script name in the value for 'File name:'
      5. Choose a save location -> click Save
      6. Click OK to clear the export location message
      By default your exported file will be in the following location:
      • (My) Documents/NinjaTrader 8/bin/Custom/ExportNinjaScript/<export_file_name.zip>
      Below is a link to the help guide on Exporting NinjaScripts.




      I see that there is a possibility of a lot of brushes and drawing objects that may be causing the system to run out of memory.

      I recommend that you assign brushes to class level variables assigned from State.DataLoaded, and then re-use these to conserve memory.

      Further, if there is going to be a large amount of drawing objects, it is recommend to custom render these in OnRender() instead to save on the overhead of generating drawing tool script instances.

      From the help guide:
      "Using DrawObjects vs custom graphics in OnRender()
      When using Draw methods, a new instance of the Draw object is created including its custom rendering and calculation logic. These methods are convenient in many situations, but can quickly introduce performance issues if used too liberally. In some situations, you may see better performance for rendering via SharpDX in OnRender().​"
      Join the official NinjaScript Developer Community for comprehensive resources, documentation, and community support. Build custom indicators and automated strategies for the NinjaTrader platforms with our extensive guides and APIs.


      Examples can be found here.

      Chelsea B.NinjaTrader Customer Service

      Comment


        #4
        Thanks for advices. I tried to assign brushes to class level variables but it didn't work, I immediately bricked NT8 after this, had to use Safe Mode again and remove the indicator.
        I'm afraid this is beyond my capabilties. Is there some possibilty of official paid service or something? Functionality is there, the only issue are those crashes.

        PS. The crashed happen of plain chart, where there are levels to be projected from like 10 bars. Those crashes seem random for me.
        Last edited by Pabulon; 04-11-2025, 11:14 AM.

        Comment


          #5
          Hello Pabulon,

          You are declaring a private brush variable in the scope of the class?

          You are assigning the variable to a Brush object in State.DataLoaded?

          May I have an export of the updated script to confirm?


          You can also contact a professional NinjaScript Consultant who would be eager to create or modify this script at your request or assist you with your script. The NinjaTrader Ecosystem has affiliate contacts who provide educational as well as consulting services.

          You can search our extensive library of NinjaScript consultants through the link below. Simply enter a consultant name or search by using our filter categories. Once you have identified your consultants of choice, please visit each consultant's site for more information or contact them directly to learn more!
          Programming Services - https://ninjatraderecosystem.com/sea...mming-services
          Educators - https://ninjatraderecosystem.com/sea...ures=education

          You can locate the contact information for the consultants on their direct websites for any additional questions you may have. Since these consultants are third party services for NinjaTrader all pricing and support information will need to be obtained through the consultant.

          This NinjaTrader Ecosystem website is for educational and informational purposes only and should not be considered a solicitation to buy or sell a futures contract or make any other type of investment decision. The companies and services listed on this website are not to be considered a recommendation and it is the reader's responsibility to evaluate any product, service, or company. NinjaTrader Ecosystem LLC is not responsible for the accuracy or content of any product, service or company linked to on this website.
          Attached Files
          Chelsea B.NinjaTrader Customer Service

          Comment


            #6
            There are many ways to do this even without using OnRender(). Here is an example which will use your same logic.

            private SimpleFont symbolFont;
            private DateTime lastRayUpdateTime = DateTime.MinValue;​
            Brush upBrush1R = Brushes.Lime;
            Brush upBrush2R = Brushes.White;
            Brush downBrush1R = Brushes.Red;
            Brush downBrush2R = Brushes.White;​
            Brush transparentBrush = Brushes.Transparent;

            ...........
            up1RBrush = shouldDraw ? upBrush1R : transparentBrush;
            up2RBrush = shouldDraw ? upBrush2R : transparentBrush;

            Draw.Text(this, "UP_1R" + CurrentBar, false, "—", 0, oneRup, 0, up1RBrush, symbolFont, TextAlignment.Center, null, null, 0);
            Draw.Text(this, "UP_2R" + CurrentBar, false, "—", 0, twoRup, 0, up2RBrush, symbolFont, TextAlignment.Center, null, null, 0);​
            ...........
            down1RBrush = shouldDraw ? downBrush1R : transparentBrush;
            down2RBrush = shouldDraw ? downBrush2R : transparentBrush;

            Draw.Text(this, "DOWN_1R" + CurrentBar, false, "—", 0, oneRdown, 0, down1RBrush, symbolFont, TextAlignment.Center, null, null, 0);
            Draw.Text(this, "DOWN_2R" + CurrentBar, false, "—", 0, twoRdown, 0, down2RBrush, symbolFont, TextAlignment.Center, null, null, 0);​

            There are ways to make this even more efficient but this will give you the rough idea,

            Edited for typos, etc.
            Last edited by eDanny; 04-14-2025, 11:33 AM.
            eDanny
            NinjaTrader Ecosystem Vendor - Integrity Traders

            Comment


              #7
              Dear Chelsea

              There are 2 files as attachements. One is fine - pre private brush change - it works relatively good.
              And the second one immediately kills NT8.

              About onRender - there is realy not a lot Drawings on the chart. This is my only indicator, I try to keep charts clear, I use it for pas several bar usualy, I don't like chart to be cluttered with stuff.
              Attached Files

              Comment


                #8
                Hello Pabulon,

                I am seeing you are still declaring new brushes in OnBarUpdate() on lines 193, and 194. By having the word Brush before the variable name this makes this a variable declaration.

                I'm suggesting that you declare these in the scope of the class.

                Also, ClearOutputWindow() is already a method name used by NinjaTrader. I recommend you give your custom method on line 240 a different name to prevent ambiguity.

                Below is a link to a video of testing the script with some modifications. It seems to work ok, but I haven't let this run in real-time for very long.
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  Hey, I'm very thankful that you found time to record a video.
                  try, catch, ClearOutput (thought it was mistake to call it like that) were me trying to deal with those crashes. I was wondering maybe those drawing are not overwritten somehow.after I refresh the chart.
                  I'm kind of surprised that you said that generating like 100 drawings is a heavy lifting. Previously I've been runing multiple indicator that were showing me all sorts of stuff like overlaped bars, gaps etc. on past 40 days on 5min chart and it was all runing quite smooth despite being like 1000 or slightly less drawings . There was definitely no crashes.
                  I obviously implemented your changes and will keep fingers crossed for them to be enough. I will keep You updated.
                  Thanks once again

                  Comment


                    #10
                    Rough start, I had to try to open NT8 4 times until it finaly launched. Seems like something in this code is still crashing the application
                    Nah, another crash when I removed one of the rays that were on the chart at the time and refreshed the chart for it to update the levels.
                    I can't figure it out what are the criteria on when is it crashing.
                    Attached Files
                    Last edited by Pabulon; 04-14-2025, 02:45 AM.

                    Comment


                      #11
                      Hello Pabulon,

                      If you are certain this is the script causing the issue reduce the script to identify what is causing the behavior.

                      Comment out all logic in OnBarUpdate() and OnStateChange(), comment out all variable declarations.

                      Close all open workspaces, save a new blank workspace, open a new chart with no template. (No scripts at all should be running)

                      Add this one indicator to the chart, save the workspace and restart NinjaTrader.

                      Check for the behavior.

                      If the behavior is not reproduced, uncomment the variable declarations, compile, and restart NinjaTrader.

                      If the behavior again does not reproduce, uncomment the logic in OnStateChange() and check again.

                      Continue by uncommenting one line at a time in OnBarUpdate() until the behavior returns.

                      Make note of the last thing uncommented when the behavior returns.
                      Chelsea B.NinjaTrader Customer Service

                      Comment


                        #12
                        On a clear workspace I can not reproduce this error. I just made 30 lines, plenty other drawing objects, I was moving them around the cart, refreshed like 200 times. No errors. But on my other workspace, they occur randomly, sometimes with 1 line on chart. Can I have somehow corrupted workspace or something?

                        Okay got it ! When there is BarCounter indicator - then it eventualy crashes. Without it - it works!
                        Last edited by Pabulon; 04-14-2025, 09:51 AM.

                        Comment


                          #13
                          Hello Pabulon,

                          You might have another script in the original workspace causing the issue.

                          Or there just might be too much running causing performance issues.
                          Chelsea B.NinjaTrader Customer Service

                          Comment


                            #14
                            Apparently BarCounter is in conflict with this indicator. Both are printing Drawings on each bar on certain sections. Do you maybe have some advice how to deal with it so that I can show bar counter aswell? Maybe some walkaround? Maybe some code that will delay calculations.

                            Comment


                              #15
                              Hello Pabulon,

                              In conflict how?

                              Do you mean you have fixed text in the bottom right corner and this is overlapping the bar counter?

                              If so, you could choose another corner.

                              Or you can add some new lines to the string with "\r\n" so the text is above the bar counter.
                              Chelsea B.NinjaTrader Customer Service

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                              0 responses
                              630 views
                              0 likes
                              Last Post Geovanny Suaza  
                              Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                              0 responses
                              364 views
                              1 like
                              Last Post Geovanny Suaza  
                              Started by Mindset, 02-09-2026, 11:44 AM
                              0 responses
                              105 views
                              0 likes
                              Last Post Mindset
                              by Mindset
                               
                              Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                              0 responses
                              564 views
                              1 like
                              Last Post Geovanny Suaza  
                              Started by RFrosty, 01-28-2026, 06:49 PM
                              0 responses
                              568 views
                              1 like
                              Last Post RFrosty
                              by RFrosty
                               
                              Working...
                              X