Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

high tick rate freezes chart

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

    high tick rate freezes chart

    I have three indicators that use onrender/SharpDX. I think they are the reason for my chart to completely freeze during high tick rate. What is the recommended way to moderate time spent in onrender? Is using the timer and render every 250ms or so the best option? I wish there was a better profiling tool to see where my code spends the most time and a way to generate high tick rate for testing...

    #2
    Hello MiCe1999,

    There is not a way to limit OnRender, that is called for various rendering purposes. If you developed something which starts to freeze when using onRender that likely means you are doing too much work in the OnRender override. You would have to take a look at what is being done in the override and see what can be offloaded or optimized.

    Comment


      #3
      Originally posted by NinjaTrader_Jesse View Post
      Hello MiCe1999,

      There is not a way to limit OnRender, that is called for various rendering purposes. If you developed something which starts to freeze when using onRender that likely means you are doing too much work in the OnRender override. You would have to take a look at what is being done in the override and see what can be offloaded or optimized.
      What the easiest way to check how long does the indicator spend in onrender?


      I tried to limit onrender rendering frequency, I would be fine with every 60ms, code below, but it sometimes rejects forced refresh after scrolling or scaling and drawing disappears for up to a second.

      PHP Code:
      if (RenderThresholdMs > 0)
      {
      TimeSpan elapsed = DateTime.Now - lastRenderTime;
      if (elapsed.TotalMilliseconds < RenderThresholdMs && !waitingForRender)
      return; // Skip this render call
      
      // Update the last render time
      lastRenderTime = DateTime.Now;
      }&#8203; 
      
      Last edited by MiCe1999; 04-15-2025, 07:52 PM.

      Comment


        #4
        Hello MiCe1999,

        I believe you are approaching this in the wrong way, OnRender is intended to be called very frequently and also when the user interacts with the chart. That makes it so it has consistent rendering. if you are trying to limit the rendering that could end up causing your indicator to blink.

        The best way to approach this to to make sure you are not doing any work in OnRender and only rendering the final result. I am not sure what code you have currently but the general flow would be to do all work in OnBarUpdate and store data to variables or series and then in OnRender you simply render that data and allow the platform to control how frequently OnRender is called.

        Comment


          #5
          Hi Jesse

          Could you point out which parts should be optimized/dropped/done differently?

          PHP Code:
          protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
          {
          // Check if we should skip this render based on timing threshold
          if (RenderThresholdMs > 0)
          {
          TimeSpan elapsed = DateTime.Now - lastRenderTime;
          if (elapsed.TotalMilliseconds < RenderThresholdMs && !waitingForRender)
          return; // Skip this render call
          
          // Update the last render time
          lastRenderTime = DateTime.Now;
          }
          
          // Check if RenderTarget is available
          if (RenderTarget == null || lineBrush == null || oddLevelStrokeStyle == null || evenLevelStrokeStyle == null)
          return;
          
          // Check if ChartPanel is available
          if (ChartPanel == null || !IsVisible || sessions.Count == 0)
          return;
          
          // Get visible bar range
          int firstVisibleBar = ChartBars.FromIndex;
          int lastVisibleBar = ChartBars.ToIndex;
          
          // Panel dimensions
          float panelWidth = (float)ChartPanel.W;
          float panelStartX = (float)ChartPanel.X;
          float panelEndX = panelStartX + panelWidth;
          
          // Get the visible Y-range
          double minVisibleY = chartScale.MinValue;
          double maxVisibleY = chartScale.MaxValue;
          
          // Create chart scale for optimization
          lastScale = chartScale;
          
          // For each session that overlaps with visible range
          foreach (SessionData session in sessions)
          {
          // Skip sessions completely outside visible range
          if (session.EndBarIndex < firstVisibleBar || session.StartBarIndex > lastVisibleBar)
          continue;
          
          // Find the middle index (pivot) for this session
          int middleIndex = session.LevelValues.Count / 2;
          
          // Determine visible X range for this session
          float startX = Math.Max(panelStartX, ChartControl.GetXByBarIndex(ChartBars, Math.Max(firstVisibleBar, session.StartBarIndex)));
          float endX = Math.Min(panelEndX, ChartControl.GetXByBarIndex(ChartBars, Math.Min(lastVisibleBar, session.EndBarIndex)));
          
          // Draw each level for this session
          for (int i = 0; i < session.LevelValues.Count; i++)
          {
          double levelValue = session.LevelValues[i];
          
          // Skip if level is outside visible range
          if (levelValue <= 0 || levelValue < minVisibleY || levelValue > maxVisibleY)
          continue;
          
          // Convert the price to Y coordinate
          float y = chartScale.GetYByValue(levelValue);
          
          // Set line points for just the visible part of this session
          linePoints[0].X = startX;
          linePoints[0].Y = y;
          linePoints[1].X = endX;
          linePoints[1].Y = y;
          
          // Determine line style based on even/odd index
          SharpDX.Direct2D1.StrokeStyle currentStyle = (i % 2 == 0) ?
          evenLevelStrokeStyle : oddLevelStrokeStyle;
          
          // Determine line width - double for pivot if option is enabled
          float currentLineWidth = LineWidth;
          if (i == middleIndex && DoublePivotThickness)
          currentLineWidth = LineWidth * 2;
          
          // Draw the line
          RenderTarget.DrawLine(linePoints[0], linePoints[1], lineBrush, currentLineWidth, currentStyle);
          
          // Draw label if enabled
          if (ShowLabels)
          {
          // Get level name with percentage
          string labelText = GetLevelName(i, levelValue, session.PriorClose);
          
          // Adjust label width based on text length (longer for percentage labels)
          int labelWidth = Math.Max(LABEL_WIDTH, Math.Min(100, labelText.Length * 7));
          
          // Create label rectangle
          SharpDX.RectangleF labelRect = new SharpDX.RectangleF(
          startX + LABEL_OFFSET,
          y - LABEL_HEIGHT / 2.0f,
          labelWidth,
          LABEL_HEIGHT);
          
          // Draw background
          RenderTarget.FillRectangle(labelRect, labelBgBrush);
          
          // Draw border with same color as line
          RenderTarget.DrawRectangle(labelRect, lineBrush, 1f);
          
          // Draw text
          SharpDX.DirectWrite.TextFormat textFormat = new SharpDX.DirectWrite.TextFormat(
          Core.Globals.DirectWriteFactory,
          labelFont.Family.ToString(),
          (float)labelFont.Size);
          
          // Center the text
          textFormat.TextAlignment = SharpDX.DirectWrite.TextAlignment.Center;
          textFormat.ParagraphAlignment = SharpDX.DirectWrite.ParagraphAlignment.Center;
          
          try
          {
          // Draw text
          RenderTarget.DrawText(labelText, textFormat, labelRect, labelTextBrush);
          }
          finally
          {
          // Clean up
          textFormat.Dispose();
          }
          }
          }
          }&#8203; 
          
          Last edited by MiCe1999; 04-18-2025, 07:52 AM.

          Comment


            #6
            Hello MiCe1999,

            The only item I can see is the first condition you made, that is not needed so OnRender can run at its full rate. Which specific part of the code have you found to be the problem?

            Comment


              #7
              Originally posted by NinjaTrader_Jesse View Post
              Hello MiCe1999,

              The only item I can see is the first condition you made, that is not needed so OnRender can run at its full rate. Which specific part of the code have you found to be the problem?
              Given that the chart froze up I assumed OnRender was the issue since it's using UI thread, based on what what I learned since - I'm not so sure that OnRender was the issue.

              Anyway, thanks for the tips, I optimized my indicator to be 3x as efficient. According to the NT Utilization monitor it's only using 30% more time than few line objects.

              Do you think that adding following code to onrender could help figuring out where issue is:

              PHP Code:
                          TimeSpan elapsed = DateTime.Now - lastRenderTime;
                          if(elapsed.Milliseconds>RenderThresholdMs) Print("InfiniteLevelsIndicator: render time loop has taken "+elapsed.Milliseconds+"ms"+ " on "+DateTime.Now);
                          lastRenderTime = DateTime.Now;&#8203; 
              
              Last edited by MiCe1999; 04-18-2025, 03:28 PM.

              Comment


                #8
                I am curious if you have ChartTrader on (Hidden or On). NT8 has a serious bug imho that has yet to be addressed around excessive rendering calls when ChartTrader is active. It calls OnRender for every indicator and object on a chart multiple times for each order (It's an exponential problem) whenever they are adjusted or updated. Details are in my thread here: https://forum.ninjatrader.com/forum/...onrender-calls -- OnRender is frequently being called faster than screen refresh cycles.

                If you try to limit the calls to OnRender in your own scripts, you will see your objects flicker on the chart as they will not be drawn in each cycle.

                If you are doing any "heavy calculations" it would be best to do those outside of OnRender and cache the results for the next render cycle so that you can avoid being a slow OnRender in all the gazillions of OnRenders that need to be called. You could do your calculations in a "as needed" basis in OnBarUpdate as PriceChanges or what have you.

                Comment


                  #9
                  Hello MiCe1999,

                  The chart freezing could be from many different areas or even items that you have applied in addition to your own. Debugging is the best first step to see what is required to see the problem.

                  I am not aware of a chart trader bug as described in the previous message but OnRender can be a source of slowness if your code is not optimized or is doing too much work. It is never a good idea to do heavy calculations in OnRender because that's the rendering loop. It sounds like you got some performance gains by going through the code though.

                  In regard to the code you provided, you could use that, its just limiting the condition to an amount of milliseconds you specify for the offset. That would really only be useful if you are trying to limit something like a print, not your rendering code. If you use that kind of logic to control the rest of the OnRender logic it will likely blink on the chart instead of displaying clearly.




                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                  0 responses
                  580 views
                  0 likes
                  Last Post Geovanny Suaza  
                  Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                  0 responses
                  335 views
                  1 like
                  Last Post Geovanny Suaza  
                  Started by Mindset, 02-09-2026, 11:44 AM
                  0 responses
                  101 views
                  0 likes
                  Last Post Mindset
                  by Mindset
                   
                  Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                  0 responses
                  554 views
                  1 like
                  Last Post Geovanny Suaza  
                  Started by RFrosty, 01-28-2026, 06:49 PM
                  0 responses
                  552 views
                  1 like
                  Last Post RFrosty
                  by RFrosty
                   
                  Working...
                  X