Should I expect NT8 to scale things after OnRender returns? Or do I have a way to ask NT8 to re-scale the panel?
Announcement
Collapse
No announcement yet.
Partner 728x90
Collapse
NinjaTrader
Indicator lines drawn during OnRender get clipped until user clicks panel
Collapse
X
-
Indicator lines drawn during OnRender get clipped until user clicks panel
I have an indicator that draws many lines during OnRender. It appears that they are getting clipped. When the user clicks on the panel, NT8 appears to expand the clipping rectangle and scale things so that the lines appear.
Should I expect NT8 to scale things after OnRender returns? Or do I have a way to ask NT8 to re-scale the panel?Tags: None
-
Hello dween,
Thank you for your post.
Based on your description, this may be a symptom of the IsSuspendedWhileInactive property. Please try setting IsSuspendedWhileInactive to false in OnStateChange() when the state is State.SetDefaults or State.Configure and see if this resolves the behavior. For more information:
Please let me know if I may be of further assistance.
-
NinjaTrader_Emily - thanks for the suggestion. I made the change, settingOriginally posted by NinjaTrader_Emily View PostHello dween,
Thank you for your post.
Based on your description, this may be a symptom of the IsSuspendedWhileInactive property. Please try setting IsSuspendedWhileInactive to false in OnStateChange() when the state is State.SetDefaults or State.Configure and see if this resolves the behavior.- I get the same result as before. Just to give you a visual example, I'm including the before and after in a picture below.Code:IsSuspendedWhileInactive = false;
Looking at messages I'm Print()-ing, I see that my code is triggered by calls to OnRender() and I get the first result below.
I see that, once the user clicks the panel, I see a call to OnRenderTargetChanged() and then voila the panel looks right.
* It would make sense to me that, after drawing a bunch of lines into the panel, that the "render target" (the panel) will have changed - it will be rescaled.
* I'm guessing that somehow the internals have not picked up on the changes and have not decided (yet) to rescale what's on the panel.
* I'm finally guessing that once the user touches the panel it finally does decide to rescale the panel - and this is reflected in a call to OnRenderTargetChanged().
You probably see where I'm going
=> is there a way for me to tell NT8 "yo - you probably don't realize it but my indicator's panel has new drawing objects that require the panel's clipping/scaling to change - please compute the new clipping rectangle and scaling and re-call OnRenderTargetChanged()"?
Note: I already have in place logic that waits until OnRender() has been called and then sets a timer for 0.25 - 1.50 seconds and then calls ForceRefresh() - that had been my fix but it stopped working - I note that it triggers calls to OnRender but not to OnRenderTargetChanged.Last edited by dween; 09-28-2023, 04:39 PM.
Comment
-
Hello dween,
Thank you for your reply.
OnRender() is called frequently, especially after the state is State.Realtime. There is information about the marker used to call OnRender() and when it is reset here:There is a check every 250ms that decides if the chart needs to be updated, and typically ForceRefresh() should only be called if it is necessary to queue OnRender() to be called at the end of the next 250ms timer.
How are your drawing objects and their coordinates on the chart being calculated? The platform comes with a SampleCustomRender indicator that renders various shapes that stay within the visible range of the chart. I am not able to get the same behavior with that indicator where if I click away from the chart they do not render as expected; they continuously stay rendered in the same location on the chart, even as new bars are formed.
I look forward to your reply.
Comment
-
Emily, I'm grateful that you're being responsive on this issue I'm wrestling with.Originally posted by NinjaTrader_Emily View PostHello dween,
Thank you for your reply.
OnRender() is called frequently, especially after the state is State.Realtime. There is information about the marker used to call OnRender() and when it is reset here:There is a check every 250ms that decides if the chart needs to be updated, and typically ForceRefresh() should only be called if it is necessary to queue OnRender() to be called at the end of the next 250ms timer.
I have a workaround that waits until after OnRender stops getting called & then calls ForceRefresh() - that isn't helping for some reason.
I suspect that I exceed some limit & that's why my drawn objects appear not to be accounted for in the clipping/scaling that's being done.Originally posted by NinjaTrader_Emily View PostHow are your drawing objects and their coordinates on the chart being calculated? The platform comes with a SampleCustomRender indicator that renders various shapes that stay within the visible range of the chart. I am not able to get the same behavior with that indicator where if I click away from the chart they do not render as expected; they continuously stay rendered in the same location on the chart, even as new bars are formed.
I do a "Draw.Line" call for each bar in the price panel, and then perhaps a dozen additional rectangles and lines.
I'll try an experiment where only a few bars are showing & see whether I see the issue in that scenario.
Comment
-
Originally posted by NinjaTrader_ChelseaB View PostHello dween,
Are there any errors appearing on the Log tab of the Control Center?
(I'm wondering if you are re-using brushes or possibly running out of graphics memory)
https://ninjatrader.com/support/foru...606#post789606
Reasonable questions, Chelsea.
1. I do not see any messages appear in the Log tab of the Control Center when I run this scenario (I can send a screen shot).
2. Referring to your question about re-using brushes - I can confirm that I have code that runs on OnRenderTargetChanged that re-allocates the SharpDx brushes (I could show that code too...).
Finally, looping back to the experiment I proposed during chat with Emily - I tried to tell whether the problem was that I was doing too much during OnRender so that I exceeded some time limit and the framework went on to choose initial scaling/sizing parameters for my panel before I was finished:
I tested this by resizing my displayed security so that only a few bars showed (so that my "loop over all bars" would have a small # of loops) then loading my indicator - that made no difference - I still am only seeing the panel sized too small in the Y direction to show all the lines I drew during OnRender.
Something I didn't mention: the problem only happens (but always happens) when I first load the Indicator during a session (or right after a recompile).
So
* no messages are generated in the Log tab
* it appears not to be that I'm exceeding a fixed amount-of-time-spent-in-OnRender (because I limited the bars to work on and it made no difference)
* it only happens for the first time I load the Indicator during a session
Any ideas?
This looks really bad and I don't have a workaround.
Comment
-
Hello dween,
Thank you for your reply.
When it comes to working with brushes, you have an option of using a static brush and implicitly recreating/disposing of the brush in OnRender() as shown in the first example on this page:Or, you could recalculate the brush in OnRenderTargetChanged() as demonstrated in the example "Recalculating a SharpDX Brush based on user input" on the following page:More information about working with brushes may be found here:Since this happens when you are first loading the indicator or after recompiling the indicator, I am curious if this potentially has to do with any values that are precomputed outside of OnRender(). Do you also see this behavior if you right-click the chart and select Reload NinjaScript?Code:protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { // implicitly recreate and dispose of brush on each render pass using (SharpDX.Direct2D1.SolidColorBrush dxBrush = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Blue)) { RenderTarget.FillRectangle(new SharpDX.RectangleF(ChartPanel.X, ChartPanel.Y, ChartPanel.W, ChartPanel.H), dxBrush); } }
There are some performance best practices listed on this page that may be relevant:- https://ninjatrader.com/support/help..._practices.htm
- Expand "Performance practices" and see the sections under "Precomputing values instead of calculating in OnRender()" and "Restricting OnRender() calculations to visible ChartBars"
Even if OnBarUpdate() is set to calculate On Price Change or On Each Tick, when it is processed historically it will only be called on bar close unless the script is designed to use Tick Replay. If there are values used from OnBarUpdate() in your OnRender() logic, this may be important to keep in mind. For more info about developing for Tick Replay (which may or may not apply to your script):
Please let me know if I may be of further assistance.
Comment
-
I think I've said this already in fewer words, but here's my thought:
Context
I've made some calls to Draw.Rectangle, Draw.HorizontalLine and Draw.Line.
The NT8 framework decides how much of those should be visible based on the points I've drawn to and how those points align horizontally with the bars in my security, and apparently vertically scaling things to fit everything I've drawn.
This decision about how to scale things vertically is, I think, the problem: NT8 is only including a subset of the things that I've drawn: the "bounding box" is vertically starting around "0" and going positive, and I need the bounding box to extend to some negative extent.
Note that once a user moves the mouse to my panel, presses the mouse down and drags either left or right, suddenly NT8 reconsiders and re-computes the bounding box to include the Lines, Rectangles and HorizontalLines that I've drawn below the 'zero' line.
I'm doing exactly the same logic in OnRender (I've got traces that demonstrate this).
Proposal
NT8 provides an API call for my Indicator (ForceRefresh()) to ask NT8 to trigger a call to OnRender.
Could NT8 expose a way for my Indicator to explicitly ask for NT8 to do the precursor step, that is, to ask NT8 to reconsider the objects I have drawn, and recompute the bounding/clipping box for the objects I have drawn in my panel?
I figure it would then call both my OnRenderTargetChanged and OnRender methods, necessarily, afterwards.
Comment
-
Hello dween,
Thank you for your patience and for the detailed explanation.
You asked, "Could NT8 expose a way for my Indicator to explicitly ask for NT8 to do the precursor step, that is, to ask NT8 to reconsider the objects I have drawn, and recompute the bounding/clipping box for the objects I have drawn in my panel?"
Based on your description, it sounds like the MinValue and MaxValue are not being calculated as expected for the auto-scaling of the y-axis until a user clicks and drags on the chart. You could consider setting the MinValue and MaxValue in OnCalculateMinMax() to override the values used for the min/max when auto-scaling the y-axis:- https://ninjatrader.com/support/help...8/minvalue.htm
- https://ninjatrader.com/support/help...8/maxvalue.htm
I believe this should address your inquiry; I look forward to hearing the results.
Comment
-
Emily, thank you for this lead - I'll pursue it - I'm feeling hopeful!Originally posted by NinjaTrader_Emily View PostHello dween,
Thank you for your patience and for the detailed explanation.
You asked, "Could NT8 expose a way for my Indicator to explicitly ask for NT8 to do the precursor step, that is, to ask NT8 to reconsider the objects I have drawn, and recompute the bounding/clipping box for the objects I have drawn in my panel?"
Based on your description, it sounds like the MinValue and MaxValue are not being calculated as expected for the auto-scaling of the y-axis until a user clicks and drags on the chart. You could consider setting the MinValue and MaxValue in OnCalculateMinMax() to override the values used for the min/max when auto-scaling the y-axis...
Comment
Latest Posts
Collapse
| Topics | Statistics | Last Post | ||
|---|---|---|---|---|
|
Started by Geovanny Suaza, 02-11-2026, 06:32 PM
|
0 responses
649 views
0 likes
|
Last Post
|
||
|
Started by Geovanny Suaza, 02-11-2026, 05:51 PM
|
0 responses
370 views
1 like
|
Last Post
|
||
|
Started by Mindset, 02-09-2026, 11:44 AM
|
0 responses
109 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
574 views
1 like
|
Last Post
|
||
|
Started by RFrosty, 01-28-2026, 06:49 PM
|
0 responses
576 views
1 like
|
Last Post
by RFrosty
01-28-2026, 06:49 PM
|

Comment