Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Handling volumetric series

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

    Handling volumetric series

    Hi, I am a newbie to C# and I appreciate any help with my problem. I would like to use volumetric data in my indicator (calculating imbalances and so on) and for that I need to know the best way (practice) to handle a volumetric series in NT8. My initial thought is to use a structure like this (a dictionary of a dictionary) :

    dictionary { key = bar number, value = dictionary {key = price, value = list ( bid volume for that price, ask volume for that price)} }

    Does that make sense? Any better or more efficient approach for NT8? Is there any sample code I can take a look at?

    Thank you very much.
    Last edited by Photon66; 11-12-2020, 01:01 PM.

    #2
    Hello Photon66,

    Thank you for your reply.

    First, if you've got a Lifetime License for NinjaTrader you would have access to the Order Flow + Volumetric Bars, which can be accessed for data that may be helpful to you:



    For an example of using dictionaries with volumetric data you could take a look at the built in Volume Profile indicator that is not part of the Order Flow + suite and is available to all license types. This can be found in the NinjaScript Editor.

    There's also this example from our help guide that shows how to output a Level 2 order book to the Output window using Lists:



    The general consensus is that your idea of using a nested Dictionary in another Dictionary would work, but you could also use a Series<Something> (where Something could be a list or class) since the series would be synced to each bar already rather than have a Dictionary hold that.

    Here's an example of using a Series<T> in a script to hold values. In this particular example they used a Series<bool>, but the same concept could be applied to a list or class:



    Please let us know if we may be of further assistance to you.

    Comment


      #3
      Hi NinjaTrader_Kate,

      Thank you very much for the quick and helpful reply. I have a lifetime license and using Series instead of dictionary makes perfect sense. Taking your advice I tried to implement it with the idea of saving ask and bid volume in a dictionary inside a Series: I get this error:

      made it to here
      Indicator 'AAdebug': Error on calling 'OnBarUpdate' method on bar 1: Object reference not set to an instance of an object.



      My code is shown below; it works until the Print(" made it to here"). In red is what I think is critical. Can you say what might be the solution? I appreciate your help.

      ------------------------------------------------------------------------------------------------------------------
      namespace NinjaTrader.NinjaScript.Indicators.AA
      {
      public class AAdebug : Indicator
      {

      private Series<Dictionary<double, List<double>>> listBidAskVol;


      protected override void OnStateChange()
      {
      if (State == State.SetDefaults)
      {
      Description = @"Enter the description for your new custom Indicator here.";
      Name = "AAdebug";
      Calculate = Calculate.OnEachTick;
      IsOverlay = false;
      DisplayInDataBox = true;
      DrawOnPricePanel = true;
      DrawHorizontalGridLines = true;
      DrawVerticalGridLines = true;
      PaintPriceMarkers = true;
      ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
      //Disable this property if your indicator requires custom values that cumulate with each new market data event.
      //See Help Guide for additional information.
      IsSuspendedWhileInactive = true;
      }
      else if (State == State.DataLoaded)
      {
      listBidAskVol = new Series<Dictionary<double, List<double>>>(this);
      }

      protected override void OnBarUpdate()
      {
      if (Bars == null)
      return;

      NinjaTrader.NinjaScript.BarsTypes.VolumetricBarsTy pe barsType = Bars.BarsSeries.BarsType as
      NinjaTrader.NinjaScript.BarsTypes.VolumetricBarsTy pe;

      if (barsType == null)
      return;
      if (CurrentBar <1)
      return;

      double askVol = barsType.Volumes[CurrentBar].GetAskVolumeForPrice(Close[0]) ;
      double bidVol = barsType.Volumes[CurrentBar].GetBidVolumeForPrice(Close[0]) ;

      Print("made it to here");

      if(listBidAskVol[0].ContainsKey(Close[0]))
      {
      listBidAskVol[0][Close[0]] = new List<double> { bidVol, askVol };
      }
      else
      {
      listBidAskVol[0].Add(Close[0], new List<double> {bidVol, askVol });
      }


      foreach(double key in listBidAskVol[0].Keys)
      {
      int count1 = listBidAskVol[0].Count;
      Print(count1);
      }



      }
      }
      }

      ------------------------------------------------------------------------------------------------------------------

      Comment


        #4
        Hello Photon66,

        Thank you for your reply.

        You're really really close here, you're just not creating a new Dictionary for the bar before trying to assign things to it:

        Code:
        [B]listBidAskVol[0] = new Dictionary<double, List<double>>();[/B]
        
        if(listBidAskVol[0].ContainsKey(Close[0]))
        {
        
        listBidAskVol[0][Close[0]] = new List<double> { bidVol, askVol };
        }
        else
        {
        listBidAskVol[0].Add(Close[0], new List<double> {bidVol, askVol });
        }
        Try adding that first line before you try to assign items to the dictionary and it should work for you.

        Please let us know if we may be of further assistance to you.

        Comment


          #5
          Hi Kate,

          Great! It worked beautifully after adding the line of code you gave. Thank you very much for the help.

          Comment


            #6
            Hi Kate, To my surprise I realized that most lines of codes in the above post are not used in the program despite giving surprisingly correct results. So there is something wrong in my code that I do not understand. I try to associate a dictionary to a series private Series<Dictionary<double, List<double>>> listBidAskVol, but I am doing something which is not correct. The following code works ok, but when I try to access listBidAskVol[1]instead of listBidAskVol[0], I get the error ": Error on calling 'OnBarUpdate' method on bar 1: Object reference not set to an instance of an object."

            In the bottom of the code in the print section Print(i++); It only prints number 1, i.e., which shows only one keypair; however, I expect more keys in my dictionary equal to the count of tick levels in my bar. This also baffles me.

            Could you please show me the correct way of using a dictionary inside a series? Thank you.


            namespace NinjaTrader.NinjaScript.Indicators.AA
            {
            public class AAAforNinjaTrader : Indicator
            {
            private Series<Dictionary<double, List<double>>> listBidAskVol;
            protected override void OnStateChange()
            {
            if (State == State.SetDefaults)
            {
            Description = @"Enter the description for your new custom Indicator here.";
            Name = "AAAforNinjaTrader";
            Calculate = Calculate.OnEachTick;
            IsOverlay = false;
            DisplayInDataBox = true;
            DrawOnPricePanel = true;
            DrawHorizontalGridLines = true;
            DrawVerticalGridLines = true;
            PaintPriceMarkers = true;
            ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
            //Disable this property if your indicator requires custom values that cumulate with each new market data event.
            //See Help Guide for additional information.
            IsSuspendedWhileInactive = true;
            }
            else if (State == State.DataLoaded)
            {
            listBidAskVol = new Series<Dictionary<double, List<double>>>(this);
            }

            else if (State == State.Configure)
            {
            }
            }

            protected override void OnBarUpdate()
            {
            NinjaTrader.NinjaScript.BarsTypes.VolumetricBarsTy pe barsType = Bars.BarsSeries.BarsType as
            NinjaTrader.NinjaScript.BarsTypes.VolumetricBarsTy pe;

            if (barsType == null)
            return;

            double askVol = barsType.Volumes[CurrentBar].GetAskVolumeForPrice(Close[0]) ;
            double bidVol = barsType.Volumes[CurrentBar].GetBidVolumeForPrice(Close[0]) ;


            listBidAskVol[0] = new Dictionary<double, List<double>>();
            listBidAskVol[0].Add(Close[0], new List<double> {bidVol, askVol });



            int i = 1;
            foreach(var keyValue in listBidAskVol[0])
            {

            Print( i++);
            var key = keyValue.Key;
            var value = keyValue.Value;
            Print(key +" - "+value[0]+" - "+value[1]);

            }
            }

            }
            }
            }
            Last edited by Photon66; 11-23-2020, 12:03 PM.

            Comment


              #7
              Hello Photon66,

              Thank you for your reply.

              You're not checking in your code if enough bars have elapsed to check the prior bar's value.

              Try adding this to the beginning of OnBarUpdate:

              if (CurrentBar < 1)
              return;

              Here's a page from our help guide that goes over making sure you have enough bars to process:


              Please let us know if we may be of further assistance to you.

              Comment


                #8
                Hi Kate,
                Thanks for the reply. I actually had if (CurrentBar < 1) return; in my code and forgot to copy-paste above. That does not solve the problem. I suspect there is a problem with the assignment of the dictionary. Thanks.

                Comment


                  #9
                  Not sure but it could also be that creating the Dictionary (initialization) suggested in post #4 related to post #3 needs to be done differently. I think the values need to be stored in the dictionary of series but the way suggested in post#4 will reset the series on every bar update. If there is any examples of Series<Dictionary...> or Series<List..> that would be very helpful. Thanks.

                  Comment


                    #10
                    Hello Photon66,

                    Thank you for your reply.

                    You're totally right, the issue is that every tick we're looping through OnBarUpdate and recreating the Dictionary when we only need to create it once, on the first tick of the bar. I'm attaching a modified version that seems to work quite nicely and gives levels I'd expect when it prints. We simply check whether it's the first tick of the bar, if so we create the dictionary for that bar, then we check to see whether there's already a key with the close value or not and add or update depending on whether it's been added already or not.

                    Please let us know if we may be of further assistance to you.
                    Attached Files

                    Comment


                      #11
                      Hi Kate, Thank you very much. My code functions correctly now using your method.

                      Comment

                      Latest Posts

                      Collapse

                      Topics Statistics Last Post
                      Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                      0 responses
                      656 views
                      0 likes
                      Last Post Geovanny Suaza  
                      Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                      0 responses
                      371 views
                      1 like
                      Last Post Geovanny Suaza  
                      Started by Mindset, 02-09-2026, 11:44 AM
                      0 responses
                      109 views
                      0 likes
                      Last Post Mindset
                      by Mindset
                       
                      Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                      0 responses
                      574 views
                      1 like
                      Last Post Geovanny Suaza  
                      Started by RFrosty, 01-28-2026, 06:49 PM
                      0 responses
                      579 views
                      1 like
                      Last Post RFrosty
                      by RFrosty
                       
                      Working...
                      X