Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Draw.Region question

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

    Draw.Region question

    I am trying to use Draw.Region to fill between two lines. I have another indicator where I do something similar to fill between Bollinger-type bands, and that works fine. What I am doing here looks to me to be good -- but all that means is that I am either missing something or misunderstanding something and I don't know how to find the problem. To be clear, the indicator plots correctly -- it's just the fill operation that is the problem.

    Since I want to fill between lines, I have two custom Series<double> that OnBarUpdate puts the respective line values into on each bar, which should create suitable data series objects for Draw.Region. Here is the drawing code -- a diagnostic Print and the Draw.Region:
    Code:
     Print($"BULL: bottomSeries.Count={bottomSeries.Count} topSeries.Count={topSeries.Count} bottomSeries[0]={bottomSeries[0]}"
               + $" topSeries[0]={topSeries[0]} Value[0]={Value[0]} CurrrentBar={CurrentBar}");
    Draw.Region(this, "tag1"+CurrentBar, CurrentBar, 0, bottomSeries, topSeries, null, Brushes.Green, 100 /*transparency*/);
    ​
    Here is the last few lines of output:
    Code:
    BULL: bottomSeries.Count=7145 topSeries.Count=7145 bottomSeries[0]=-50 topSeries[0]=50 Value[0]=54 CurrrentBar=7141
    BULL: bottomSeries.Count=7145 topSeries.Count=7145 bottomSeries[0]=-50 topSeries[0]=50 Value[0]=66 CurrrentBar=7142
    BULL: bottomSeries.Count=7145 topSeries.Count=7145 bottomSeries[0]=-50 topSeries[0]=50 Value[0]=74 CurrrentBar=7143
    BULL: bottomSeries.Count=7145 topSeries.Count=7145 bottomSeries[0]=-50 topSeries[0]=50 Value[0]=98 CurrrentBar=7144
    ​
    • The bar number and Value[0] are correct -- they match the screen so we are getting to the right place to be doing the Draw.Region.
    • I tried both "tag1" and "tag1"+CurrentBar -- did not make any difference.
    • I tried setting the start to CurrentBar, CurrentBar-1, 0, and 5 -- did not make any difference.
    • I tried with the second series and with the other signature that just takes a value -- did not make any difference.
    • The counts confirm that the series are getting populated. Their current values are as expected (-50 and 50).
    • The Print shows I am actually getting to the Draw line of code ... it is the next one after the Print statement.
    So what am I either missing or misunderstanding?

    Thanks
    Last edited by ETFVoyageur; 05-20-2024, 10:40 AM.

    #2
    Hello ETFVoyageur,

    You are expecting to see a region drawn from -50 to 50 is this correct?

    Is this in a separate panel?

    is -50 to 50 visible on that chart panel?
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      That is correct. I expect to fill between lines at -50 and +50 in the same panel in which the indicator is running. Do I have to do something to direct the drawing to that indicator panel? That never occurred to me, so I never looked into it. I would expect the drawing to automatically go to the same panel unless something was done to change that. There's that word "expect" .... perhaps that's it?

      FWIW: I'm just trying to fill the indicator's center band.

      And, yes, that range is visible -- the panel goes from -100 to +100 and the lines I want to fill between are easily visible.
      Last edited by ETFVoyageur; 05-20-2024, 11:30 AM.

      Comment


        #4
        Chelsea,

        Thanks for pointing me in the right direction. On looking further, I found I need to set "DrawOnPricePanel = false;" It now draws. Thanks.

        Comment


          #5
          OK, now I am drawing, but the drawing is not quite right. The problem is that if I use 1,0 for start & finish it fails because it starts one bar too soon. If I try 0, -1 the situation is no better -- aside from the negative offset being unsupported, now it draws one bar too far to the right. So what about 0,0 ? That is even worse -- I get no visible drawing at all.

          So, my choices are off-by-one on the left, unsupported and off-by-one on the right, or no drawing at all.

          I am trying to do bull/bear coloring of the center bar. Is the problem that Draw.Region is not the tool that I should be using? Is there something better that you would recommend?

          Comment


            #6
            Hello ETFVoyageur,

            To confirm you are trying to shade the region between the current bar (0 bars ago) and the previous bar (1 bar ago)?

            "it fails because it starts one bar too soon."

            Can you clarify what you are meaning by it is failing? Is it drawing on the wrong bars?

            It should be drawing from the last fully closed bar to the previous fully closed bar, is this correct?

            " If I try 0, -1 the situation is no better -- aside from the negative offset being unsupported, now it draws one bar too far to the right. So what about 0,0 ? "

            Unfortunately, negative indexes to draw in the blank space to the right of the chart bars is not supported.

            Using a startBarsAgo of 0 and endBarsAgo of 0 would result in no object being drawn as the region must be shaded between two bars.

            "I am trying to do bull/bear coloring of the center bar. "

            Can you clarify what you mean by the center bar?

            Do you mean you are trying to draw over three bars so there is a bar in the center?



            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Chelsea,

              I did a little more experimenting and I think I see the problem -- and it may well be my perception. To be clear, I am not alleging there is some sort of bug with Draw.Region.

              What I want is to color the region between the lines in my indicator (e.g. -50 to +50) green (bull), red (bear), or neither when my indicator is inconclusive. What I want to achieve is that when the user puts the cursor on the bar for a day it is unambiguous what color day my indicator says it is. I am coming to the conclusion that this is not a good job for Draw.Region. Draw.Region worked fine for filling some Bollinger-type bands, but that is quite a different undertaking.

              To better understand what is happening, I set it to color for exactly one bar. The coloring extends from the previous bar to the current bar. In other words, it colors the space between the bars with the result that it is not clear which bar the coloring applies to. You'd have to know the implementation detail that the coloring for a bar is the coloring that extends to the left of the bar.

              I altered my coloring a little so that there is coloring corresponding to each bar. When I put my cursor on a bar at the transition between colors, the colored area is red to the left of the cursor and green to the right. How is the user supposed to know that the color to the left is the correct one? That is terrible from a usability perspective!

              What I would far prefer from a usability perspective is that the coloring for a bar extends between the midpoints -- from halfway to the bar on the left to halfway to the bar on the right. Then when a user puts the cursor on a bar, the corresponding color would be unambiguous. Much better!

              It seems to me that the problem is not that there is anything wrong with Draw.Region. As far as I know, it is working exactly as it was designed to work. That means it is probably the wrong tool for me. I need to be able to color centered on a bar, not to the left of a bar.

              What would you suggest that I ought to be using? I know that the library supports fully general graphics, but I hope that is overkill and there is a simple solution that does what I want.

              I hope that this answers your questions. The bottom line is that I want my coloring to be centered on a bar so that the color that applies to a bar is unmistakable to the user. Draw.Region, at least as I am using it, does not meet that need.

              Comment


                #8
                Hello ETFVoyageur,

                Unfortunately, Draw.Region() cannot be used on one bar. It has be drawn between bars. The same is true for Draw.Rectangle().
                You could set the BackBrush to change the chart color behind a single bar.
                Or you could draw a dot, arrow up, arrow down, triangle up, triangle down, or vertical line, which all have one barsAgo input and are designed to be drawn on a single bar. A line could also be drawn on a single bar as long as the start and end price are different.


                If you really want a custom shape there, such as a rectangle drawn above, below or on the bar you could custom render it in OnRender().
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  Chelsea,

                  Thanks. I'll look at your links.

                  What I want to do sounds simple to me -- to fill the area between my lines (+50 to -50) with each day's coloring centered on that day's bar so that the result is clear to the user. It's not a problem during a continuous bull or bear period because the fill will be continuous The problem comes at the endpoints and transitions between colors. That's unfortunate because those can be the most significant times.

                  I'm not trying to show discrete bars and I'm not trying to write anything on the chart panel. I just want to fill an area in my indicator's panel in a way that the result is clear to the user at the transitions.

                  Comment


                    #10
                    Hello ETFVoyageur,

                    Where would you want to fill in an area?

                    Between two bars? Over one bar? Over all of the bars? Below the bar or bars, on top the bar or bars?
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      I'm sorry that I have been unclear.

                      I have an indicator in an indicator panel. Nothing that I am trying to do has anything to do with drawing anywhere other than in its own panel. When I refer to bars, I am referring to the X-coordinate in the indicator's panel that corresponds to that of the bar in the chart panel. I have no plan to color anything in the chart panel.

                      The indicator has two horizontal lines -- think of them as visually similar to many other indicators' overbought and oversold lines. I want to fill the area between those lines, colored according to what the indicator thinks is appropriate for the bar at that horizontal position. What I do currently is to have OnBarUpdate() run a Draw.Region call like the one I originally posted It runs the call with a red brush when bearish and a green brush when bullish.

                      That works, except at the endpoints. When a user uses a crosshair cursor, the cursor should be able to be over a bar and it should be clear what color my indicator intends to correspond to that bar. No solution that is based on coloring the area between bars, ending at the bar on each end, is satisfactory at the endpoints. The user's crosshair cursor will show one color to the left and another to the right. To me, that is unacceptable from a usability point of view because it is not clear to the user which color corresponds to that bar.

                      I need to color, ending at the X-coordinate that is at the midpoint between bars. Then it would be clear what color in my indicator's filled area corresponds to each bar. Unfortunately, it appears to me that all of the Draw.* objects take what is the wrong approach for my need -- as I understand it, they all end at a bar, not at the midpoint between bars.

                      Comment


                        #12
                        Hello ETFVoyageur,

                        Ok, it's in a separate panel, the bar slots will still be the same and the drawing tools will still work the same.

                        "When a user uses a crosshair cursor, the cursor should be able to be over a bar and it should be clear what color my indicator intends to correspond to that bar. No solution that is based on coloring the area between bars, ending at the bar on each end, is satisfactory at the endpoints."

                        Then you would need to be able to draw or render on a single bar slot instead of between two bars. In which case use a drawing object that only has one anchor (one barsAgo parameter) or custom render in OnRender().

                        "Unfortunately, it appears to me that all of the Draw.* objects take what is the wrong approach for my need -- as I understand it, they all end at a bar, not at the midpoint between bars."

                        Correct, drawing objects are either drawn on the bar or between bars depending on the drawing tool. You will likely need to custom render a shape.
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #13
                          Closure -- I have implemented custom rendering and it works fine.

                          The simple thing I expected did not work, though. I had expected to fill a small one-bar region each iteration over the on-screen bars. That does not work -- I could never get a smoothly colored bull or bear region if I was setting the opacity. There were always either some uncolored stripes or some darker stripes due to overlap. I eventually proved to myself that there is no width that will produce a smoothly colored area. I was surprised to find that an overlap at low opacity produced something of a higher opacity (the sum of the two?).

                          I had to go to filling an entire bull or bear region with one fill call. Less simple code (but not bad) and presumably better performance due to fewer SharpDX calls.
                          Last edited by ETFVoyageur; 05-23-2024, 07:25 AM.

                          Comment

                          Latest Posts

                          Collapse

                          Topics Statistics Last Post
                          Started by oneybuchi2, Today, 03:48 PM
                          0 responses
                          7 views
                          0 likes
                          Last Post oneybuchi2  
                          Started by Graci117, 06-19-2024, 01:39 PM
                          6 responses
                          53 views
                          0 likes
                          Last Post Graci117  
                          Started by farawayz, Today, 01:20 PM
                          0 responses
                          11 views
                          0 likes
                          Last Post farawayz  
                          Started by rjm1903, Today, 01:10 PM
                          0 responses
                          6 views
                          0 likes
                          Last Post rjm1903
                          by rjm1903
                           
                          Started by AH369, 06-21-2024, 11:09 AM
                          3 responses
                          29 views
                          0 likes
                          Last Post AH369
                          by AH369
                           
                          Working...
                          X