Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Clarification on redrawing objects in NinjaTrader using SharpDX

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

    Clarification on redrawing objects in NinjaTrader using SharpDX

    Hello support and all,

    I'm currently working on a strategy in NinjaTrader that involves drawing objects using SharpDX for rendering. I have a question regarding the best approach to redraw objects in each OnRender event.

    Based on my understanding, NinjaTrader follows a retained mode rendering system where the recommended practice is to redraw all the objects in each OnRender event, regardless of whether they have changed or not. This approach ensures that the chart is consistently rendered with the latest state of all elements.

    In light of this, I wanted to confirm if my understanding is correct and if it is indeed the recommended approach in NinjaTrader to redraw all objects in each OnRender event when using SharpDX for rendering. Additionally, I would appreciate any insights or best practices related to optimizing the rendering process or any other considerations I should be aware of.

    Thank you in advance for your guidance and assistance!

    #2
    Hello trendisyourfriend,

    Yes that is correct, each time OnRender is called whatever code is being used to render in that render pass ends up visualized. If you don't call the rendering code it won't be displayed.

    If you were to only call the rendering code sometimes when something has changed it would just briefly flash and then disappear.

    As a best practice your data calculation and conditions should usually go in OnBarUpdate and you would store anything you need to render to variable. In OnRender you just have your rendering logic which references those variables. That ensures values are only being calculated at the slower OnBarUpdate rate and OnRender doesn't have to do any specific heavy work and just renders.

    Comment


      #3
      What about the drawing objects which are outside the visible chart area ? should my script try to filter those objects and skip them or should i render them just as well even though they may be located outside the visible area ?

      Comment


        #4
        Hello trendisyourfriend,

        If by Drawing objects you mean the built in tools like Draw.Text those should generally be used from OnBarUpdate to create or modify them to avoid high resource usage. if you are using drawing objects from OnRender that can cause high utilization because of how frequently OnRender is called. Any objects outside of the viewable area that do not have autoscale enabled will be hidden.

        If you otherwise mean items you are rendering using the RenderTarget , if the X/Y values for that rendering is outside of the chart area it just won't be rendered. It would be more efficient to avoid trying to render a lot of items that are outside of the chart X/Y/W/H.

        Most scripts that use OnRender utilize series or variables that are set from OnBarUpdate. Inside OnRender you would use a loop over the FromIndex and ToIndex to only render data that is on the currently visible bars, anything on other bars is not used. In your X/Y calculation logic you can check for anything that is outside of the chart panels X/Y/W/H to ignore those data points.

        Here is an example of the loop: https://ninjatrader.com/support/help...htsub=frominde




        Comment


          #5
          You can check to see whether the objects are off the visible screen and if they're not going to show, don't draw them. You CAN still draw them, but it's just wasting cycles.
          Bruce DeVault
          QuantKey Trading Vendor Services
          NinjaTrader Ecosystem Vendor - QuantKey

          Comment


            #6
            Originally posted by QuantKey_Bruce View Post
            You can check to see whether the objects are off the visible screen and if they're not going to show, don't draw them. You CAN still draw them, but it's just wasting cycles.
            QuantKey_Bruce
            Thank you for your valuable advice; I genuinely appreciate it. If I may extend my request for your assistance, I would like to inquire further about obtaining the X and Y coordinates of the painted area on a chart. My objective is to determine whether my drawing object, such as a sharpDX rectangle or a line, intersects or overlaps with the visible area. Any guidance on how to proceed with this would be greatly appreciated.

            I was thinking about using these commands:

            // find the first visible price
            double topPrice = chartScale.GetValueByY(1);
            This would return the first price at the top of the chart

            // find the last visible price
            double bottomPrice = chartScale.GetValueByY( chartScale.Height - 1 );

            then to filter my lines i might use a for loop to check if it falls between the topPrice and bottomPrice.

            What do you think ?


            Last edited by trendisyourfriend; 05-26-2023, 09:21 AM.

            Comment


              #7
              Be sure to check for nulls and values to be in range so you don't get exceptions.

              You can tell the first and last bar index on the screen by ChartBars.FromIndex and ChartBars.ToIndex.

              Using those, you can tell the first and last datetimes using ChartBars.Bars.GetTime(ChartBars.FromIndex) and ChartBars.Bars.GetTime(ChartBars.ToIndex).

              Given these, you can also get the first and last pixel coordinates using ChartControl.GetXByBarIndex or ChartControl.GetXByTime.

              The top and bottom of the screen are available several ways, but one approach is the top price is ChartScale.MaxValue and the bottom price is ChartScale.MinValue.

              Those in pixels are ChartScale.GetYByValue(ChartScale.MaxValue) and ChartScale.GetYByValue(ChartScale.MinValue).

              You can also access ChartScale.GetValueByY and use ChartPanel.Y and ChartPanel.H.

              You can also access ChartPanel.X and ChartPanel.W to get the pixel dimensions.

              Between all of these, you should have no trouble deducing what of your things you would be drawing are visible.

              The cases are sort of like (for each axis): (1) the object is completely off the screen to the left, (2) the object is completely off the screen to the right, or (3) some other thing, such as it's spanning the screen or completely on the screen or part of it's on the screen - these are the ones you need to draw. Same for the vertical axis.
              Bruce DeVault
              QuantKey Trading Vendor Services
              NinjaTrader Ecosystem Vendor - QuantKey

              Comment


                #8
                Thanks very much that's exactly the commands i was looking for.

                Comment


                  #9
                  Originally posted by QuantKey_Bruce View Post
                  Be sure to check for nulls and values to be in range so you don't get exceptions.

                  You can tell the first and last bar index on the screen by ChartBars.FromIndex and ChartBars.ToIndex.

                  Using those, you can tell the first and last datetimes using ChartBars.Bars.GetTime(ChartBars.FromIndex) and ChartBars.Bars.GetTime(ChartBars.ToIndex).

                  Given these, you can also get the first and last pixel coordinates using ChartControl.GetXByBarIndex or ChartControl.GetXByTime.

                  The top and bottom of the screen are available several ways, but one approach is the top price is ChartScale.MaxValue and the bottom price is ChartScale.MinValue.

                  Those in pixels are ChartScale.GetYByValue(ChartScale.MaxValue) and ChartScale.GetYByValue(ChartScale.MinValue).

                  You can also access ChartScale.GetValueByY and use ChartPanel.Y and ChartPanel.H.

                  You can also access ChartPanel.X and ChartPanel.W to get the pixel dimensions.

                  Between all of these, you should have no trouble deducing what of your things you would be drawing are visible.

                  The cases are sort of like (for each axis): (1) the object is completely off the screen to the left, (2) the object is completely off the screen to the right, or (3) some other thing, such as it's spanning the screen or completely on the screen or part of it's on the screen - these are the ones you need to draw. Same for the vertical axis.
                  How do you recommend drawing lines that are partially across the screen?

                  For example there's a trendline tail suppose to be extended through the current screen, Should I use some function logic to calculate which pixels belongs in the screen and use a SharpDX vector to draw that? Or Is there a way to use SharpDX like "Draw.Line" method to draw it at some starting barsAgo and let it extend it by itself?​
                  Last edited by Curerious; 04-17-2025, 05:40 PM.

                  Comment


                    #10
                    No, there's no harm in using SharpDX to draw a vector that starts left of the screen and ends right of the screen. Only drawing on the screen is SharpDX's task, and it does it just fine.
                    Bruce DeVault
                    QuantKey Trading Vendor Services
                    NinjaTrader Ecosystem Vendor - QuantKey

                    Comment


                      #11
                      QuantKey_Bruce
                      So basically each time if I want to display the same trendline, I have to manually recalculate what pixels do the trendlines get, deduce it into two points on screen, then draw it with SharpDX?
                      Last edited by Curerious; 04-17-2025, 06:10 PM.

                      Comment


                        #12
                        Yes, that's the basic idea. You COULD try to deduce which pixels of the line are visible (clipping) and I'm not saying you should or shouldn't but I will say most people don't. The time it takes SharpDX to figure out which pixels are on the screen is minimal, and if you try to do it yourself there's a much higher chance of introducing bugs, so your starting stance should be to let the library handle it and only try to do this yourself if you must - for instance, if you have some special case where the library's performance is the limiting factor (this is highly unlikely).

                        What I suggested above is a practical trade-off - if you determine that NONE of the pixels are on the screen (it's entirely off the screen to the left, or right, or above the scale, or below the scale), skip it. If ANY of the pixels are on the screen, draw it, and let the library clip it. That's relatively easy to do on your end and not too likely to result in bugs, and you're letting the library do the hard part (figuring out where the line intercepts the screen edge). It is, in a way, a sort of "Algebra II" type problem to figure out the intercepts, but I would encourage you to let the library handle this, because your time can be better spent making your product/indicator/strategy better rather than reinventing wheels that have been invented for decades.
                        Last edited by QuantKey_Bruce; 04-18-2025, 04:38 AM.
                        Bruce DeVault
                        QuantKey Trading Vendor Services
                        NinjaTrader Ecosystem Vendor - QuantKey

                        Comment


                          #13
                          QuantKey_Bruce
                          Thank you for answering. Seems you introduced the idea of automatically clipping.

                          Are you suggesting me to draw outside of the screen (if intersecting with the current screen) and let the library automatically clip it? If so, the problem is: Will it really clip it or it will just leave the graph drawn in unseen areas?

                          (If you happen to have some example scripts that would be great ! There isn’t much example in the internet, the only one I saw is the one who uses negative x,y coordinates to draw)
                          Last edited by Curerious; 04-18-2025, 06:31 AM.

                          Comment


                            #14
                            There are two different clipping-type issues here. The first is the line you want to draw is ENTIRELY off the screen (as one example, it both starts and ends left of the screen). In that case, you can quickly determine that by getting the X coordinate of the rightmost endpoint, and if that value is left of CanvasLeft, no need to go any further. Similarly, if the leftmost endpoint is right of CanvasRight or if the lowermost endpoint is above the top of the screen or the uppermost endpoint is below the bottom of the screen, you're all done - you could draw it if you want, but it's a null operation ultimately as the library is going to determine it's not on the screen. I wouldn't spend too much time on this, but you could fairly easily determine if any of these four things is true, and then skip drawing it.

                            The second is that the line is partially on the screen. As an example, it starts left of the screen and ends on the screen or off the screen to the right. In this case, I would recommend you let the library handle it, rather than calculating the intercepts at the edges of the screen and just drawing on the screen, because the library already has this code in it, and for you to recreate it is a waste of your time (and even CPU time, because the library has to check anyway after you've checked). For that matter, you could elect to skip the checks above also, but they're so easy to check for, I tend to go ahead and rule those out before they hit the library.
                            Bruce DeVault
                            QuantKey Trading Vendor Services
                            NinjaTrader Ecosystem Vendor - QuantKey

                            Comment


                              #15
                              Also, negative x and y coordinates in pixels may be valid. For instance, if you have a "two up and two down" four monitor setup, and the lower right monitor is the primary monitor, the others may have negative values in one or more coordinates. You shouldn't be comparing with zero, but rather, the bounds of the chart you're drawing on.
                              Bruce DeVault
                              QuantKey Trading Vendor Services
                              NinjaTrader Ecosystem Vendor - QuantKey

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by abelsheila, 05-14-2025, 07:38 PM
                              2 responses
                              30 views
                              0 likes
                              Last Post hglover945  
                              Started by nailz420, 05-14-2025, 09:14 AM
                              1 response
                              57 views
                              0 likes
                              Last Post NinjaTrader_ChristopherJ  
                              Started by NinjaTrader_Brett, 05-12-2025, 03:19 PM
                              0 responses
                              327 views
                              1 like
                              Last Post NinjaTrader_Brett  
                              Started by domjabs, 05-12-2025, 01:55 PM
                              2 responses
                              62 views
                              0 likes
                              Last Post domjabs
                              by domjabs
                               
                              Started by Morning Cup Of Trades, 05-12-2025, 11:50 AM
                              1 response
                              81 views
                              0 likes
                              Last Post NinjaTrader_ChristopherJ  
                              Working...
                              X