Announcement
Collapse
No announcement yet.
Partner 728x90
Collapse
NinjaTrader
high tick rate freezes chart
Collapse
X
-
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...Tags: None
-
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?Originally posted by NinjaTrader_Jesse View PostHello 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.
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; }​Last edited by MiCe1999; 04-15-2025, 07:52 PM.
Comment
-
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
-
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(); } } } }​Last edited by MiCe1999; 04-18-2025, 07:52 AM.
Comment
-
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.Originally posted by NinjaTrader_Jesse View PostHello 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?
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;​Last edited by MiCe1999; 04-18-2025, 03:28 PM.
Comment
-
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
-
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
|
||
|
Started by Geovanny Suaza, 02-11-2026, 05:51 PM
|
0 responses
335 views
1 like
|
Last Post
|
||
|
Started by Mindset, 02-09-2026, 11:44 AM
|
0 responses
101 views
0 likes
|
Last Post
by Mindset
02-09-2026, 11:44 AM
|
||
|
Started by Geovanny Suaza, 02-02-2026, 12:30 PM
|
0 responses
554 views
1 like
|
Last Post
|
||
|
Started by RFrosty, 01-28-2026, 06:49 PM
|
0 responses
552 views
1 like
|
Last Post
by RFrosty
01-28-2026, 06:49 PM
|

Comment