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

Plotting text, needing to refresh NinjaScript

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

    Plotting text, needing to refresh NinjaScript

    When I started testing (in Market Replay) an indicator that plots text above bars from a secondary data series, I came across this issue. If you compare the two screenshots you can see on one of them, the text plots are all stacked up. This happened when I added VWAP. Then I refreshed, and things were corrected (the screenshot where the text plots are not stacked up).

    What is typically done to address this?

    I didn't post any code because it seems like a general best-practices type of thing but if code is required let me know.
    Attached Files
    Last edited by WalterSkinner; 07-27-2021, 02:44 PM. Reason: *started testing on market replay is when i noticed

    #2
    Hi Walter, thanks for posting.

    It looks like a CurrentBar parameter issue within the script. If Draw.Text() is called multiple times with the same CurrentBar parameter the drawings would all occur on the same bar. A very effective way to see data flowing through the script and debug issues is to use the Print() method, that way you can see what lines of code are being called and when e.g.

    Print("Executing Command 1");
    //Draw something else

    Print("Executing Command 2")
    //Draw something else

    We have a brief guide on debugging NinjaScript code here:


    Kind regards,
    -ChrisL
    Chris L.NinjaTrader Customer Service

    Comment


      #3
      What's strange is I've only seen this issue when changing times in market replay

      Edit:
      To be more specific if I'm in market replay and it's playing, this error can come up when adding new indi's, or compiling the code after modification.

      Switching to a new time seems to fix it.

      Last edited by WalterSkinner; 07-27-2021, 06:14 PM.

      Comment


        #4
        Hello WalterSkinner,

        As Chris mentions with using CurrentBar with the drawing method, this is typically used to create unique drawing tags so each drawing is unique. If this is a multi time frame script, and the draw methods can be called on multiple data series, CurrentBar can reflect the primary bar or the secondary bar, whichever is processing in OnBarUpdate. We can then encounter a potential scenario where multiple secondary bars result in multiple unique drawings, and these may stack depending on how the code is written.

        I would suggest writing the code so drawings are made on BarsInProgress == 0, the primary data series, so we can expect one drawing per bar if we use CurrentBar to make the drawing tags unique. (You can write to private variables on the secondary series and use those variables with your drawings on the primary data series.

        If you need additional help from here, it may be best to add an example that demonstrates the behaviors in simple terms and how you are creating those symptoms, and we will be able to provide more specific direction. (We would ask for a small example as complexities of a full indicator can distract from the issue at hand.)

        Exporting as source code - https://ninjatrader.com/support/help...tAsSourceFiles

        JimNinjaTrader Customer Service

        Comment


          #5
          Originally posted by NinjaTrader_Jim View Post

          I would suggest writing the code so drawings are made on BarsInProgress == 0, the primary data series, so we can expect one drawing per bar if we use CurrentBar to make the drawing tags unique. (You can write to private variables on the secondary series and use those variables with your drawings on the primary data series.
          Thank you so much for replying.

          One of the things I experimented with was moving the code that plots the text to three different locations:
          1. BarsInProgress == 0
          2. BarsInProgress == 1 (on the final pass through the loop that creates variable newFinalMagcount)
          3. Inside OnBarUpdate() but outside of BarsInProgress
          When I don't have the code in BarsInProgress == 0, the text is plotted on the correct bar. When I do have it in == 0, it shifts the plotted value to the next bar. Printing newFinalMagcount (the value that is plotted in the text) shows the correct value still corresponds to the proper bar.

          Here's the code that plots the text, let me know if you would like an exported version this is just a snippet for brevity.

          Part of my plan today is to use a histogram instead of plotting the text if this turns out to be a time waster.

          Thanks again for the thoughtful input and let me know if the pasted code below is insufficient.

          Edit:
          Just in case I forgot to mention this: The chart primary data series is a ten tick range bar chart, and the secondary data series is also set to ten ticks range (volumetric).

          Edit 2:
          Also I have BarsInProgress == 0 AFTER BarsInProgress == 1. Not sure if this is wrong (new to coding) but my thinking was if the code is being processed top down, and the calculation for newFinalMagcount is done on == 1, that == 0 should come after that. Could be way wrong.

          Code:
          else if (BarsInProgress == 0)
          {
               NinjaTrader.Gui.Tools.SimpleFont myFont = new NinjaTrader.Gui.Tools.SimpleFont("Courier New", fontSize) { Size = otherSize, Bold = true };
               Draw.Text(this, "myTag"+CurrentBar, false, newFinalMagcount.ToString(), 0, High[0] + 2*TickSize, 0, Brushes.Black, myFont, TextAlignment.Center, Brushes.Black, null, 1);
          }
          Last edited by WalterSkinner; 07-28-2021, 07:51 AM.

          Comment


            #6
            Hello WalterSkinner,

            If drawing from the secondary series is a requirement, and you only want one drawing per primary bar, you can use CurrentBars[0] (CurrentBar specific to the primary data series) as the drawing tag.

            Using CurrentBar in BarsInProgress 1 will reflect CurrentBars[1] or the CurrentBar index of the secondary series. Outside of a BarsInProgress check, CurrentBar will be which ever data series is currently updating.

            JimNinjaTrader Customer Service

            Comment


              #7
              Originally posted by NinjaTrader_Jim View Post
              Hello WalterSkinner,

              If drawing from the secondary series is a requirement, and you only want one drawing per primary bar, you can use CurrentBars[0] (CurrentBar specific to the primary data series) as the drawing tag.

              Using CurrentBar in BarsInProgress 1 will reflect CurrentBars[1] or the CurrentBar index of the secondary series. Outside of a BarsInProgress check, CurrentBar will be which ever data series is currently updating.
              Wow that makes so much sense thank you! This is incredibly useful.

              Comment


                #8
                I'll be testing this out on market replay after it looks perfect on historical data, eventually it will stop working with no changes to the code, just going to different places in market replay.

                This is the only thing that I've found that reliably fixes it: close platform > delete \Documents\NinjaTrader 8\db\cache > start platform.

                Are there any typical reasons why this might be the case?

                Deleting the cache folder may or may not do anything it might just be the restarting of the platform.

                Edit:

                Considering the issues arise when I change times and historical data downloaded from your broker is where that comes from - made sure I have tick data and rebooted and will keep other notes in here in case someone has the same issue in the future and comes across this.
                Last edited by WalterSkinner; 07-28-2021, 11:04 AM.

                Comment


                  #9
                  Hello WalterSkinner,

                  Deleting the cache should really never be necessary. Switching instruments would mean that new historical data would be requested from the data provider, but we should also make sure the data is in fact present as some data providers may limit how much data you can request during regular market hours.

                  Also to consider, if the script finished processing historical data and then started realtime data, and the symptom comes up after pressing F5 to reload scripts, the data that was processed as realtime would then be processed as historical.

                  You can also use prints to verify if there are OnBarUpdate iterations on BarsInProgress 0 and BarsInProgress 1 to compare against your chart to see if there were prints for bars when you do not see prints on your chart.

                  Tick Replay can also change the way multiple time frames are updated in OnBarUpdate, we would advise not using Tick Replay unless it is a necessity, but this should also be a leaf that is not left unturned.

                  If you are still having issues, please share an export that just includes the specific part of the script you are still having trouble with, and let us know some steps to take to see what you are seeing so we may comment.

                  JimNinjaTrader Customer Service

                  Comment


                    #10
                    Originally posted by NinjaTrader_Jim View Post
                    Hello WalterSkinner,

                    Deleting the cache should really never be necessary. Switching instruments would mean that new historical data would be requested from the data provider, but we should also make sure the data is in fact present as some data providers may limit how much data you can request during regular market hours.

                    Also to consider, if the script finished processing historical data and then started realtime data, and the symptom comes up after pressing F5 to reload scripts, the data that was processed as realtime would then be processed as historical.

                    You can also use prints to verify if there are OnBarUpdate iterations on BarsInProgress 0 and BarsInProgress 1 to compare against your chart to see if there were prints for bars when you do not see prints on your chart.

                    Tick Replay can also change the way multiple time frames are updated in OnBarUpdate, we would advise not using Tick Replay unless it is a necessity, but this should also be a leaf that is not left unturned.

                    If you are still having issues, please share an export that just includes the specific part of the script you are still having trouble with, and let us know some steps to take to see what you are seeing so we may comment.
                    This gives me a ton of great stuff to work on thanks again for even more valuable info.

                    Quick question about this: how do you know that tick replay is necessary or if it is not necessary? In this case the secondary series is volumetric and the numbers plotted result from calculations done on individual price levels' Bid Volume and Ask volume. Would tick replay be necessary for this?

                    Comment


                      #11
                      Hello WalterSkinner,

                      Tick Replay is going to be necessary for indicators that need historical Calculate.OnEachTick/OnPriceChange, or need historical Last tick events in OnMarketData. The BuySellVolume indicator is an example that looks at Last ticks in OnMarketData to identify buys and sells and their associated volume. With Tick Replay enabled, you will see historical plots for BuySellVolume.

                      Tick Replay may also be necessary for custom BarsTypes that perform similar volume analysis by looking at associated bid/ask with each tick and require each historical tick in order to identify each trade as a buy/sell.

                      > Volumetric does not do this and uses a proprietary approach to analyzing volume without Tick Replay.

                      Essentially, if Tick Replay is necessary, it would most likely be for historical volume analysis and you would notice missing information, errors, and it also would be made apparent by the person providing the script (if a BarsType or custom indicator) as they would know if the script would need historical OnEachTick/OnPriceChange, Last ticks in OnMarketData, or volume analysis within the BarsType.

                      More information on developing for Tick Replay can be found here - https://ninjatrader.com/support/help...ick_replay.htm
                      JimNinjaTrader Customer Service

                      Comment


                        #12
                        Originally posted by NinjaTrader_Jim View Post
                        Hello WalterSkinner,

                        Tick Replay is going to be necessary for indicators that need historical Calculate.OnEachTick/OnPriceChange, or need historical Last tick events in OnMarketData. The BuySellVolume indicator is an example that looks at Last ticks in OnMarketData to identify buys and sells and their associated volume. With Tick Replay enabled, you will see historical plots for BuySellVolume.

                        Tick Replay may also be necessary for custom BarsTypes that perform similar volume analysis by looking at associated bid/ask with each tick and require each historical tick in order to identify each trade as a buy/sell.

                        > Volumetric does not do this and uses a proprietary approach to analyzing volume without Tick Replay.

                        Essentially, if Tick Replay is necessary, it would most likely be for historical volume analysis and you would notice missing information, errors, and it also would be made apparent by the person providing the script (if a BarsType or custom indicator) as they would know if the script would need historical OnEachTick/OnPriceChange, Last ticks in OnMarketData, or volume analysis within the BarsType.

                        More information on developing for Tick Replay can be found here - https://ninjatrader.com/support/help...ick_replay.htm
                        I had tick replay enabled when I should not have, everything has been working perfectly since unchecking. Only had to refresh scripts once and it actually worked when I did.

                        Hopefully that's the end of that.

                        Thanks for all of your patience and help.

                        Comment


                          #13
                          Originally posted by NinjaTrader_Jim View Post
                          If you are still having issues, please share an export that just includes the specific part of the script you are still having trouble with, and let us know some steps to take to see what you are seeing so we may comment.
                          Still having the issues we discussed in here.

                          Also looks like there is a mystery issue preventing me from exporting.

                          I moved the relevant part of the script into its own debugging script and the issue persists.

                          The debugging script is attached to the chart and is visible in the indicators menu, but is not showing up when I try to export it. Look at this: https://imgur.com/oTRfrbl

                          The code will work fine for a while, and then with no changes made this will happen. I've only seen it happen in market replay. I have historical tick data a well as market replay data for this time period. I've kept pretty much all of the development and debugging to this period of time. I know the code can work, but when this stacking issue comes up I can generally refresh data and scripts and it will work.

                          Because there is a mystery issue preventing me from exporting I hope it's ok if I just paste in here:

                          Code:
                          namespace NinjaTrader.NinjaScript.Indicators
                          {
                          public class Debuggging : Indicator
                          {
                          //VARIABLES
                          int barsReq;
                          double finalMagCount;
                          double newFinalMagcount;
                          
                          protected override void OnStateChange()
                          {
                          if(State == State.SetDefaults)
                          {
                          Name = "Debuggging";
                          Calculate = Calculate.OnBarClose;
                          IsOverlay = true;
                          otherSize = 5;
                          fontSize = 8;
                          
                          lookback = 5;
                          plotVertPos = 5;
                          
                          }
                          else if(State == State.Configure)
                          {
                          int barPeriodValue = BarsPeriod.Value;
                          AddVolumetric("",BarsPeriodType.Range,barPeriodVal ue,VolumetricDeltaType.BidAsk,1);
                          ClearOutputWindow();
                          }
                          }//OnStateChange
                          
                          protected override void OnBarUpdate()
                          {
                          //variables
                          double magCount=0;
                          barsReq = lookback +1;
                          long barDelta = 0;
                          long prevBarDelta = 0;
                          
                          //bars check
                          if(CurrentBars[0] < barsReq || CurrentBars[1] < barsReq)
                          return;
                          
                          //volumetric bars
                          BarsTypes.VolumetricBarsType barsType = Bars.BarsSeries.BarsType as BarsTypes.VolumetricBarsType;
                          
                          //secondary data series
                          if (BarsInProgress == 1)
                          {
                          //configure text variable myFont2 then plot text
                          NinjaTrader.Gui.Tools.SimpleFont myFont2 = new NinjaTrader.Gui.Tools.SimpleFont("Courier New", fontSize) { Size = otherSize, Bold = true };
                          Draw.Text(this, "deltaText"+CurrentBar, false, "123", 0, High[0] + 10*TickSize, 0, Brushes.Black, myFont2, TextAlignment.Center, Brushes.Black, null, 1);
                          
                          }//BarsInProgress == 1
                          else if (BarsInProgress == 0)
                          {
                          }
                          
                          //configure font then plot text
                          NinjaTrader.Gui.Tools.SimpleFont myFont1 = new NinjaTrader.Gui.Tools.SimpleFont("Courier New", fontSize) { Size = otherSize, Bold = true };
                          Draw.Text(this, "magCountText"+CurrentBar, false, "xyz", 0, High[0] + plotVertPos*TickSize, 0, Brushes.Black, myFont1, TextAlignment.Center, Brushes.Black, null, 1);
                          
                          if(High[0] > High[1])
                          {
                          Draw.TriangleDown(this, "downarrow"+CurrentBar, true, 0, High[0] + 1*TickSize, Brushes.Red);
                          }
                          if(Low[0] < Low[1])
                          {
                          Draw.TriangleUp(this, "uparrow"+CurrentBar, true, 0, Low[0] - 1*TickSize, Brushes.Green);
                          }
                          
                          
                          }//OnBarUpdate
                          
                          
                          
                          
                          
                          
                          #region properties
                          [NinjaScriptProperty]
                          [Display(Name="Font Size", Order=4, GroupName="Parameters")]
                          public int fontSize
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Display(Name="Size of maybe the box?", Order=5, GroupName="Parameters")]
                          public int otherSize
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Display(Name="Hi/Lo Lookback", Order=3, GroupName="Parameters")]
                          public int lookback
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Display(Name="Vertical Offset Units", Order=3, GroupName="Parameters")]
                          public int plotVertPos
                          { get; set; }
                          
                          #endregion
                          }//Indicator
                          }//Class



                          Edit:
                          Note that this is designed to be used on a range chart. It adds a range volumetric chart as the secondary series and sets the range size to the same as the primary series.







                          Attached Files
                          Last edited by WalterSkinner; 07-29-2021, 11:41 AM.

                          Comment


                            #14
                            Slightly different version of the pasted code, same issue.

                            Not sure why this one was available to export.

                            Note that the screenshot was taken while disconnected from market replay.
                            Attached Files

                            Comment


                              #15
                              Hello WalterSkinner,

                              Looking at the code, the Draw.Text method in BarsInProgress == 1 is using CurrentBar with the tag, so each time there is a new secondary bar, this tag will change and a new drawing object will be placed.

                              Following the recommendation from post #6, please consider using CurrentBars[0] with the tag instead, as CurrentBars[0] reflects the index of the primary data series and you want to have one drawing per primary bar.
                              JimNinjaTrader Customer Service

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by cre8able, Today, 01:01 PM
                              0 responses
                              2 views
                              0 likes
                              Last Post cre8able  
                              Started by manitshah915, Today, 12:59 PM
                              0 responses
                              2 views
                              0 likes
                              Last Post manitshah915  
                              Started by ursavent, Today, 12:54 PM
                              0 responses
                              3 views
                              0 likes
                              Last Post ursavent  
                              Started by Mizzouman1, Today, 07:35 AM
                              3 responses
                              17 views
                              0 likes
                              Last Post NinjaTrader_Gaby  
                              Started by RubenCazorla, Today, 09:07 AM
                              2 responses
                              13 views
                              0 likes
                              Last Post NinjaTrader_ChelseaB  
                              Working...
                              X