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

get the bid ask volume inside the bar from the example

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

    get the bid ask volume inside the bar from the example

    Hello everyone

    I am trying to get the bid ask volume inside the bar from the example

    the problem is that I need a method to get the bid and ask volume without tick replay.

    I am trying to create this indicator on my own - from the example of the developers

    But the result is without successfully

    Below is my code

    I ask for help in the task, or a real example of how you can get the volume at bid ask prices without tick replay


    Code:
     private void CalculateValues(bool forceCurrentBar)
    {
    // This lets us know what processing mode we are in
    // if indexOffset == 0 and State is Realtime then we are in 'realtime processing mode'
    // if indexOffset is > 0 then we are in 'historical processing mode'
    int indexOffset = BarsArray[1].Count - 1 - CurrentBars[1];
    bool inTransition = State == State.Realtime && indexOffset > 1;
    
    // For Calculate.OnBarClose in realtime processing we have to advance the index on the tick series to not be one tick behind
    // The means, at the end of the 'transition' (where State is Realtime but we are still in historical processing mode) -> we have to calculate two ticks (CurrentBars[1] and CurrentBars[1] + 1)
    if (!inTransition && lastInTransition && !forceCurrentBar && Calculate == Calculate.OnBarClose)
    CalculateValues(true);
    
    bool useCurrentBar = State == State.Historical || inTransition || Calculate != Calculate.OnBarClose || forceCurrentBar;
    
    // This is where we decide what index to use
    int whatBar = useCurrentBar ? CurrentBars[1] : Math.Min(CurrentBars[1] + 1, BarsArray[1].Count - 1);
    
    // This is how we get the right tick values
    double volume = BarsArray[1].GetVolume(whatBar);
    double price = BarsArray[1].GetClose(whatBar);
    
    // Accumulate volume
    if (price >= BarsArray[1].GetAsk(whatBar))
    buys += volume;
    else if (price <= BarsArray[1].GetBid(whatBar))
    sells += volume;
    
    lastInTransition = inTransition;
    
    // LAST
    
    if (MyDict.ContainsKey(price))
    MyDict[price] += volume;
    else
    MyDict.Add(price, volume);
    
    // Ask
    
    if (price >= buys) //
    {
    if (!MyDictAsk.ContainsKey(price))
    MyDictAsk.Add(price, volume);
    else
    MyDictAsk[price] += volume;
    if (!MyDictBid.ContainsKey(price))
    MyDictBid.Add(price, 0);
    }
    
    // Bid
    
    else if (price <= sells) //
    {
    if (!MyDictBid.ContainsKey(price))
    MyDictBid.Add(price, volume);
    else
    MyDictBid[price] += volume;
    if (!MyDictAsk.ContainsKey(price))
    MyDictAsk.Add(price, 0);
    }
    else //
    {
    if (!MyDictAsk.ContainsKey(price))
    MyDictAsk.Add(price, volume);
    else
    MyDictAsk[price] += volume;
    if (!MyDictBid.ContainsKey(price))
    MyDictBid.Add(price, volume);
    else
    MyDictBid[price] += volume;
    }
    
    // price Bid Ask
    
    double volAskS = 0;
    double volBidS = 0;
    
    foreach (double kvp in MyDictAsk.Keys)
    {
    volAskS += volume;
    
    }
    foreach (double kvp in MyDictBid.Keys)
    {
    volBidS += volume;
    }
    
    }
    
    private void SetValues(int barsAgo)
    {
    foreach (double kvp in MyDictAsk.Keys)
    if (volAskS > 100)
    {
    
    Print(volAskS);
    }
    
    
    }
    
    private void ResetValues(bool isNewSession)
    {
    MyDict.Clear();
    
    MyDictAsk.Clear();
    MyDictAsk.Clear();
    
    buys = sells = 1;
    
    if (Bars.IsFirstBarOfSession)
    {
    
    volAskS = 0;
    volBidS = 0;
    }
    
    if (isNewSession)
    {
    
    volAskS = 0;
    volBidS = 0;
    
    }
    
    }

    #2
    Hello memonolog,

    Thanks for your post.

    Could you clarify on what you are having trouble with?

    The code looks nearly the same as my BuySellVolumeOneTick modification to our OneTickMultiSeriesTemplate example script. I have attached both scripts here. That indicator also shows buy/sell volume getting collected for each bar.

    We use a single tick data series to develop the plot values and we assign the plot values in BarsInProgress 0.

    We use BarsArray[1].GetBid and BarsArray[1].GetAsk to get the Ask and Bid prices from Bid/Ask stamped tick data. BarsArray[1] is the single tick data series. Once we know the bid/ask price, we compare it with the last price to se if we have a buy or a sell.

    I look forward to assisting.
    Attached Files
    JimNinjaTrader Customer Service

    Comment


      #3
      Originally posted by NinjaTrader_Jim View Post
      Hello memonolog,

      Thanks for your post.

      Could you clarify on what you are having trouble with?

      The code looks nearly the same as my BuySellVolumeOneTick modification to our OneTickMultiSeriesTemplate example script. I have attached both scripts here. That indicator also shows buy/sell volume getting collected for each bar.

      We use a single tick data series to develop the plot values and we assign the plot values in BarsInProgress 0.

      We use BarsArray[1].GetBid and BarsArray[1].GetAsk to get the Ask and Bid prices from Bid/Ask stamped tick data. BarsArray[1] is the single tick data series. Once we know the bid/ask price, we compare it with the last price to se if we have a buy or a sell.

      I look forward to assisting.

      volAskS
      volBidS

      I need help with the code, I can't get the bid and ask volume on prices inside the bar

      Comment


        #4
        Hello memonolog,

        Please see the modifications attached. I use two Series<Dictionary<double, double>>'s to track bid/ask volume at price for every bar.

        Somethings to keep in mind:

        Anything Series related should only be done in SetValues. If not, you will hit errors since the Dictionary<double, double> is synchronized to the primary data series and CalculateValues is processed in BarsInProgress 1.

        To work around this, I create temporary class level dictionaries to hold what is being calculated.

        I then create the Dictionaries from the Series in SetValues and then I copy KeyValuePairs from the temporary dictionary to the Series dictionaries.
        Attached Files
        Last edited by NinjaTrader_Jim; 05-19-2022, 06:43 AM.
        JimNinjaTrader Customer Service

        Comment


          #5
          Thanks a lot for the example, now there are a couple of questions left one I understand that this is how I can get the ask in the dictionary

          Code:
          foreach (KeyValuePair<double, double> kvp in MySeriesDictAsk[0])
          if (kvp.Value > 100)
          {
           // print ask if > 100
          }
          the question is how can I compare the ask with the bid at this price eg

          Code:
          foreach (KeyValuePair<double, double> kvp in MySeriesDictAsk[0])
          if (kvp.Value > Bidkvp.Value +50)
          {
          // print
          }
          how to compare the ask and bid prices from dictionaries correctly? what will be the syntax for the variables ask and bid prices

          Comment


            #6
            Hello memonolog,

            You can do something like the following to compare ask and bid volume.

            Code:
            foreach (KeyValuePair<double, double> kvp in MySeriesDictAsk[0])
            {
                Print(String.Format("Ask: {0} {1}", kvp.Key, kvp.Value));
                if (MySeriesDictBid[0].ContainsKey(kvp.Key))
                    Print(String.Format("Bid: {0} {1}", kvp.Key, MySeriesDictBid[0][kvp.Key]));
            }
            A publicly available resource on using Dictionaries in C# can be found below.

            Dictionary in C# is the generic collection type in the System.Collection.Generics namespace that contains Keys and Values.


            We look forward to assisting.
            JimNinjaTrader Customer Service

            Comment


              #7
              Originally posted by NinjaTrader_Jim View Post
              Hello memonolog,

              You can do something like the following to compare ask and bid volume.

              Code:
              foreach (KeyValuePair<double, double> kvp in MySeriesDictAsk[0])
              {
              Print(String.Format("Ask: {0} {1}", kvp.Key, kvp.Value));
              if (MySeriesDictBid[0].ContainsKey(kvp.Key))
              Print(String.Format("Bid: {0} {1}", kvp.Key, MySeriesDictBid[0][kvp.Key]));
              }
              A publicly available resource on using Dictionaries in C# can be found below.

              Dictionary in C# is the generic collection type in the System.Collection.Generics namespace that contains Keys and Values.


              We look forward to assisting.
              Thanks a lot, figured it out.

              I still have one more question regarding the additional data series

              in the example without the lists of bid and ask, I successfully implemented one more series of data, and the whole calculation took place over a series of data, everything works fine

              here are the changes that works in the first code

              Code:
              else if (State == State.Configure)
              {
              AddDataSeries(BarsPeriodType.Tick, 1);
              AddDataSeries(BarsPeriodType.Minute, 15);
              
              }
              Code:
              protected override void OnBarUpdate()
              {
              if (BarsInProgress == 2)
              {
              in the version with ask and bid lists this is not enough, the script does not work, it gives errors

              what else needs to be changed for the second data series?

              Comment


                #8
                All

                MySeriesDictAsk [0])

                Should be replaced by

                MySeriesDictAsk [2])

                ??

                Comment


                  #9
                  Originally posted by NinjaTrader_Jim View Post
                  Hello memonolog,

                  You can do something like the following to compare ask and bid volume.

                  Code:
                  foreach (KeyValuePair<double, double> kvp in MySeriesDictAsk[0])
                  {
                  Print(String.Format("Ask: {0} {1}", kvp.Key, kvp.Value));
                  if (MySeriesDictBid[0].ContainsKey(kvp.Key))
                  Print(String.Format("Bid: {0} {1}", kvp.Key, MySeriesDictBid[0][kvp.Key]));
                  }
                  A publicly available resource on using Dictionaries in C# can be found below.

                  Dictionary in C# is the generic collection type in the System.Collection.Generics namespace that contains Keys and Values.


                  We look forward to assisting.
                  on the first question, another problem was revealed, if I want to compare the bid and ask at the price, then the comparison does not take place if the bid or the ask at the price is 0, for example, the bid is 20 and the ask at this price is 0,
                  then nothing is displayed for me,

                  why is this happening with zeros?
                  and how to resolve the issue?

                  Comment


                    #10
                    Hello memonolog,

                    If there is not a tick identified as a buy/sell, it would not get added to the dictionary.

                    You could consider looping through the prices of the bar and reference buy and sell volume from there.

                    Code:
                    for (double p = Low[0]; p <= High[0]; p += TickSize)
                    {
                        if (MySeriesDictAsk[0].ContainsKey(p))
                            Print(String.Format("Ask: {0} {1}", p, MySeriesDictAsk[0][p]));
                        if (MySeriesDictBid[0].ContainsKey(p))
                            Print(String.Format("Bid: {0} {1}", p, MySeriesDictBid[0][p]));
                    }
                    The purpose of the example was to provide insight on how you can track buy sell volume per bar so buy/sell volume can be checked per price level per bar. Adding an additional data series to the example would not break it, so you would have to be something incorrect to receive errors.

                    If you are running into issues adding code which cause run time errors, I suggest eliminating your modifications and carefully reviewing them while reviewing the Multi Time Frame and Instruments documentation.

                    If you are receiving errors but don't know which lines the errors are coming from, I suggest reproducing the errors with prints added so you can identify the lines of code that are producing errors so you can correct the.

                    Multi Time Frame and Instruments - https://ninjatrader.com/support/help...nstruments.htm

                    Debugging Tips - https://ninjatrader.com/support/help...script_cod.htm
                    Last edited by NinjaTrader_Jim; 05-19-2022, 06:43 AM.
                    JimNinjaTrader Customer Service

                    Comment


                      #11
                      Originally posted by NinjaTrader_Jim View Post
                      Hello memonolog,

                      If there is not a tick identified as a buy/sell, it would not get added to the dictionary.

                      You could consider looping through the prices of the bar and reference buy and sell volume from there.

                      Code:
                      for (double p = Low[0]; p <= High[0]; p += TickSize)
                      {
                      if (MySeriesDictAsk[0].ContainsKey(p))
                      Print(String.Format("Ask: {0} {1}", p, MySeriesDictAsk[0][p]));
                      if (MySeriesDictBid[0].ContainsKey(p))
                      Print(String.Format("Bid: {0} {1}", p, MySeriesDictBid[0][p]));
                      }
                      The purpose of the example was to provide insight on how you can track buy sell volume per bar so buy/sell volume can be checked per price level per bar. Adding an additional data series to the example would not break it, so you would have to be something incorrect to receive errors.

                      If you are running into issues adding code which cause run time errors, I suggest eliminating your modifications and carefully reviewing them while reviewing the Multi Time Frame and Instruments documentation.

                      If you are receiving errors but don't know which lines the errors are coming from, I suggest reproducing the errors with prints added so you can identify the lines of code that are producing errors so you can correct the.

                      Multi Time Frame and Instruments - https://ninjatrader.com/support/help...nstruments.htm

                      Debugging Tips - https://ninjatrader.com/support/help...script_cod.htm

                      We look forward to assisting.
                      I added an additional data series

                      Code:
                      else if (State == State.Configure)
                      {
                      AddDataSeries(BarsPeriodType.Tick, 1);
                      [B]AddDataSeries(Instrument.FullName, new BarsPeriod { BarsPeriodType = BarsPeriodType.Minute, Value = 1 }, "Forex");[/B]
                      
                      }
                      changed the second data series here

                      Code:
                      protected override void OnBarUpdate()
                      {
                      [B]if (BarsInProgress == 2)[/B]
                      {
                      // This lets us know what processing mode we are in
                      // if indexOffset == 0 then we are in 'realtime processing mode'
                      // if indexOffset is > 0 then we are in 'historical processing mode'
                      int indexOffset = BarsArray[1].Count - 1 - CurrentBars[1];
                      
                      // If we are not Calculate.OnBarClose and we are in Realtime processing mode
                      if (IsFirstTickOfBar && Calculate != Calculate.OnBarClose && (State == State.Realtime || BarsArray[0].IsTickReplay))
                      {
                      // We always get the last tick after the primary triggers OBU so we update the last bar
                      if (CurrentBars[0] > 0)
                      SetValues(1);
                      
                      // We have the last tick of the bar added so now we can reset
                      if (BarsArray[0].IsTickReplay || State == State.Realtime && indexOffset == 0)
                      ResetValues(false);
                      }
                      
                      // We only set the value on the primary to preserve external programmatic access to plot as well as indicator-as-input cases
                      SetValues(0);
                      
                      // If we are Calculate.OnBarClose or we are in Historical processing mode, we are already update to date on the 1 tick series so we reset here
                      if (Calculate == Calculate.OnBarClose || (lastBar != CurrentBars[0] && (State == State.Historical || State == State.Realtime && indexOffset > 0)))
                      ResetValues(false);
                      
                      lastBar = CurrentBars[0];
                      
                      }
                      else if (BarsInProgress == 1)
                      {
                      // The more granular series will open the new session so we have to reset any session related stuff here
                      if (BarsArray[1].IsFirstBarOfSession)
                      ResetValues(true);
                      
                      // We only calculate values from the 1 tick series
                      CalculateValues(false);
                      }
                      }
                      I get an error

                      Indicator 'BuySellVolumeOneTickMod': Error on calling 'OnBarUpdate' method on bar 42: An item with the same key has already been added.

                      what is the problem?

                      Comment


                        #12
                        Hello memonolog,

                        My example uses BIP 0 (primary data series) and BIP 1 (single tick secondary series.)

                        Plots are synchronized to the primary data series so their assignment needs to be done in BIP 0.

                        You added a new data series and modified the code to use BIP 2 instead of BIP 0 and this broke the script.

                        An item with the same key has already been added
                        This is a C# error pertaining to dictionaries. You may find many articles external to NinjaTrader that describe how other C# developers have hit this error and how they have over come it.

                        Any changes made to the example that broke it will need to be reviewed and debugged by you, keeping the above in mind.

                        If you have any other inquiries, please do not hesitate to open a new thread.
                        JimNinjaTrader Customer Service

                        Comment


                          #13
                          Originally posted by NinjaTrader_Jim View Post
                          Hello memonolog,

                          If there is not a tick identified as a buy/sell, it would not get added to the dictionary.

                          You could consider looping through the prices of the bar and reference buy and sell volume from there.

                          Code:
                          for (double p = Low[0]; p <= High[0]; p += TickSize)
                          {
                          if (MySeriesDictAsk[0].ContainsKey(p))
                          Print(String.Format("Ask: {0} {1}", p, MySeriesDictAsk[0][p]));
                          if (MySeriesDictBid[0].ContainsKey(p))
                          Print(String.Format("Bid: {0} {1}", p, MySeriesDictBid[0][p]));
                          }
                          Hello Jim, I'm trying to do something similar.
                          What I'd want would be to simply plot a dash/line on each candle at the highest volume price level for each 10 minutes bar.
                          I found this NT8-OrderFlow kit user Apps Share indicator that seems to do it, but after some research I found it requires TickReplay, and I'm with Interactive Brokers so I can't use TickReplay.

                          I need the Highest Volume count per price of each/any bar.
                          For example, if the previous bar's High-To-Low range was 1.43 to 1.01, and the highest Volume count per price in that range was 4000 contracts and it occurred at price 1.21, then I want my indicator to plot a dash on the previous candle at the 1.21 price level.

                          Isn't there some VolumesPerPrices() method (similar to the Volume[0] series but per price instead of per bar)?

                          If not, what simpler way to use your for loop (double p = Low[0]; p <= High[0]; p += TickSize) model?

                          In your loop example, the Key-Value pair would be:

                          Key = any/each double value price comprised between the Low[0] and the High[0] of each bar (the price values)
                          Value = the accumulated volumes per any/each prices values comprised between the Low[0] and the High[0] of each bar (the volumes-a-prices values)

                          As deducted from
                          TempAskDict.Add(price, volume);
                          and
                          TempBidDict.Add(price, volume);


                          PHP Code:
                                      // Accumulate volume
                                      
                          if (price >= BarsArray[1].GetAsk(whatBar))
                                      {
                                          
                          buys += volume;
                                          if (
                          TempAskDict.ContainsKey(price))
                                              
                          TempAskDict[price] += volume;
                                          else
                                              
                          TempAskDict.Add(pricevolume);
                                      }
                                      else if (
                          price <= BarsArray[1].GetBid(whatBar))
                                      {
                                          
                          sells += volume;
                                          if (
                          TempBidDict.ContainsKey(price))
                                              
                          TempBidDict[price] += volume;
                                          else
                                              
                          TempBidDict.Add(pricevolume);
                                      } 
                          PHP Code:
                                  private void SetValues(int barsAgo)
                                  {
                                      
                          // Typical assignment for BuySellVolume
                                      
                          BuyVolume[barsAgo] = buys sells;
                                      
                          SellVolume[barsAgo] = sells;

                                      
                          // When using Dictionaries, make sure we create a new empty dictionaries to store values from our TempDictionaries
                                      
                          MySeriesDictAsk[barsAgo] = new Dictionary<doubledouble>();
                                      
                          MySeriesDictBid[barsAgo] = new Dictionary<doubledouble>();

                                      
                          // Populate values from the TempAsk Dictionary to the bar's Ask Dictionary
                                      
                          foreach (KeyValuePair<doubledoublekvp in TempAskDict)
                                          
                          MySeriesDictAsk[barsAgo].Add(kvp.Keykvp.Value); 

                          But it seems Dictionaries aren't appropriate/simple enough to retrieve the Highest volume values, since they are only sortable by Keys (we can't sort them by values, and if we invert the volume, price to get the volume as key we could run into the issue of having duplicate same key values and get errors...).

                          What workaround would you suggest to get the Highest volume for the Bid and Ask (I previously used a SortedList and strings and linq method as workaround but it seems it would need reworking your entire Dictionaries model premise)?

                          If I understand you approach right, I would then need to add up the Volume at Bid and at Ask to get the total volume per price.

                          Finally I would need to plot a dash at the retrieved Highest Volume at the corresponding Key/price value. To do so what would you suggest using as simplest method to draw the dashes at the right price?

                          And, if possible, what simpler flow (or corrected flow if you see mistakes) would you suggest?

                          I'd appreciate greatly if you would consider updating your BuySellVolumeOneTick.zip (2.5 KB, 53 views) sample to reflect the plotting aspect and showcasing where you would put your for loop (double p = Low[0]; p <= High[0]; p += TickSize). Thanks!

                          Comment


                            #14
                            Hello PaulMohn,

                            Methods to get volume at price information exists in the Order Flow Volumetric BarsType.

                            The maximum volume at price can be fetched from the Volumetric BarsType with:

                            GetMaximumVolume(bool? askVolume, out double price)

                            An example that demonstrates reading the Volumetric Bars methods along with explanations of each method can be found below:



                            If you wanted to get maximum volume at price with your own indicator code, I would suggest just making your own Plot for CombinedVolume, and count the volume from each tick in CalculateValues, without checking if price is above the ask or less than the bid.

                            An overview for how the examples work:
                            • The example script adds the plot in OnStateChange > State.SetDefaults.
                            • At the bottom of the script, the Series are mapped to the Plot's Values[] so we can use the friendly named Series<double>'s BuyVolume and SellVolume.
                            • The script uses private class level variables to track temporary values.
                            • CalculateValues is used to calculate the temporary values and updates from the single tick data series. Each tick is compared with the bid/ask price to determine if it was a buy/sell.
                            • SetValues is used to assign temporary values to the plot.
                            • ResetValues is used to reset the temporary variables to initial levels, and clear temporary dictionaries.
                            I will not be modifying the example since a solution exists with Order Flow Volumetric Bars, but if you want to do it yourself in an indicator, you can follow the above notes for how bid/ask is accumulated for Buy/Sell Volume inside the dictionary, and then you can add a dictionary for Combined Volume. (I would suggest following the BuySellVolumeOneTickDictionaries example after the simpler example is understood.)

                            Then, to find the maximum volume at price, loop through your combined dictionary and keep track of the highest volume and the price level of that volume. I.E. when you have a higher volume than the highest volume you tracked, update variables that track the highest volume and the associated price level.
                            JimNinjaTrader Customer Service

                            Comment


                              #15
                              Hello Jim, I made progresses, from your directions and those other sources:

                              How do you sort a dictionary by value?

                              Good way to get the key of the highest value of a Dictionary in C#

                              I followed your directions and reduced your BuySellVolumeOneTickDictionaries.zip (3.0 KB, 18 views) script to:
                              1. only one CombinedVolume plot (TempCombinedVolumeDict);
                              2. Adding a 2nd dictionary "dctTemp" to order the TempCombinedVolumeDict Dictionary values;
                              3. Retrieving the max value from dctTemp new Dictionary.
                              Here are the modifications summarized (the bulk in the CalculateValues() method)

                              PHP Code:
                                public class MyCustomPOC Indicator
                                
                              {
                                  private 
                              Series<Dictionary<doubledouble>> MySeriesDictCombinedVolume;

                                  private 
                              Dictionary<doubledoubleTempCombinedVolumeDict;


                              =====
                              =====
                              =====


                                protected 
                              override void OnStateChange()
                                  {
                                    if (
                              State == State.SetDefaults)
                                    {

                                      
                              AddPlot(new Stroke(Brushes.Magenta,     5), PlotStyle.Hash"CombinedVolume");

                                      
                              AddPlot(new Stroke(Brushes.Pink,     5), PlotStyle.Hash"CombinedVolume2");

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

                                      
                              MySeriesDictCombinedVolume = new Series<Dictionary<doubledouble>>(thisMaximumBarsLookBack.Infinite);

                                      
                              TempCombinedVolumeDict = new Dictionary<doubledouble>();
                                    }
                                  }


                              =====
                              =====
                              =====


                                  private 
                              double     combined   1;


                              =====
                              =====
                              =====



                                  private 
                              void CalculateValues(bool forceCurrentBar)
                                  {
                                    
                              // This lets us know what processing mode we are in
                                    // if indexOffset == 0 and State is Realtime then we are in 'realtime processing mode'
                                    // if indexOffset is > 0 then we are in 'historical processing mode'
                                    
                              int   indexOffset   BarsArray[1].Count CurrentBars[1];
                                    
                              bool   inTransition   State == State.Realtime && indexOffset 1;

                                    
                              // For Calculate.OnBarClose in realtime processing we have to advance the index on the tick series to not be one tick behind
                                    // The means, at the end of the 'transition' (where State is Realtime but we are still in historical processing mode) -> we have to calculate two ticks (CurrentBars[1] and CurrentBars[1] + 1)
                                    
                              if (!inTransition && lastInTransition && !forceCurrentBar && Calculate == Calculate.OnBarClose)
                                      
                              CalculateValues(true);

                                    
                              bool   useCurrentBar   State == State.Historical || inTransition || Calculate != Calculate.OnBarClose || forceCurrentBar;

                                    
                              // This is where we decide what index to use
                                    
                              int   whatBar     useCurrentBar CurrentBars[1] : Math.Min(CurrentBars[1] + 1BarsArray[1].Count 1);

                                    
                              // This is how we get the right tick values
                                    
                              double   volume       BarsArray[1].GetVolume(whatBar);
                                    
                              double   price       BarsArray[1].GetClose(whatBar);      

                                    
                              // Accumulate volume
                                    
                              if (price == price)
                                    {
                                      
                              combined += volume;
                                      if (
                              TempCombinedVolumeDict.ContainsKey(price))
                                        
                              TempCombinedVolumeDict[price] += volume;
                                      else
                                        
                              TempCombinedVolumeDict.Add(pricevolume);
                                    }




                                    
                              Dictionary<doubledoubledctTemp = new Dictionary<doubledouble>();

                                    for (
                              double p Low[0]; <= High[0]; += TickSize)
                                    {
                                      if (
                              TempCombinedVolumeDict.ContainsKey(p))
                              //         Print(String.Format("Ask: {0} {1} {2}", p, TempCombinedVolumeDict[p], Time[0]));

                                      
                              foreach (KeyValuePair<doubledoublepair in TempCombinedVolumeDict.OrderBy(key => key.Value))
                                      {
                                        
                              dctTemp.Add(pair.Keypair.Value);
                                        Print(
                              String.Format("Ask: {0} {1} {2}"pair.Keypair.ValueTime[0]));
                                      }

                                      
                              KeyValuePair<doubledoublemax = new KeyValuePair<doubledouble>();
                                      foreach (var 
                              kvp in dctTemp)
                                      {
                                        if (
                              kvp.Value max.Value)
                                        
                              max kvp;
                                      }

                                      Print(
                              String.Format("max: {0} {1}"max.Keymax.ValueTime[0]));

                                    }





                                    
                              lastInTransition   inTransition;
                                  }


                              =====
                              =====
                              =====


                                  private 
                              void SetValues(int barsAgo)
                                  {
                                    
                              // Typical assignment for BuySellVolume
                                    
                              CombinedVolume[barsAgo] = combined;

                                    
                              // When using Dictionaries, make sure we create a new empty dictionaries to store values from our TempCombinedVolumeDict
                                    
                              MySeriesDictCombinedVolume[barsAgo] = new Dictionary<doubledouble>();

                                    
                              // Populate values from the TempCombined Dictionary to the price's level Dictionary
                                    
                              foreach (KeyValuePair<doubledoublekvp in TempCombinedVolumeDict)
                                      
                              MySeriesDictCombinedVolume[barsAgo].Add(kvp.Keykvp.Value);

                                    
                              // Be sure to reset our accumulation of Combined Volume from Dictionary
                                    
                              double dictCombinedTotalVolume 0;
                                    foreach (
                              KeyValuePair<doubledoublekvp in MySeriesDictCombinedVolume[barsAgo])
                                      
                              dictCombinedTotalVolume += kvp.Value;

                                    
                              // Assign our accumulation of Combined Volume to the plot
                                    
                              Values[0][barsAgo] = dictCombinedTotalVolume;


                                  }


                              =====
                              =====
                              =====


                                  private 
                              void ResetValues(bool isNewSession)
                                  {
                                    
                              combined 0;

                                    
                              isReset true;

                                    
                              TempCombinedVolumeDict.Clear();

                                    if (
                              isNewSession)
                                    {
                                      
                              // Cumulative values (per session) would reset here
                                      // EMA is not gapless so we ignore in this example
                                    
                              }
                                  }


                              =====
                              =====
                              =====


                                  [
                              Browsable(false)]
                                  [
                              XmlIgnore()]
                                  public 
                              Series<doubleCombinedVolume
                                  
                              {
                                    
                              get { return Values[0]; }
                                  }
                                }


                              Please find attached the new script version "MyCustomPOC.zip"

                              The CalculateValues() update does print the Highest volume at price per bar (I checked over a 1 min prints and with correct Highest result in spreadsheet Key For Highest Value
                              108.76 328 05/05/2022 16:43:59
                              )


                              Now I'm wondering how to display a dash sign or equivalent mark on each candle max volume's price level.
                              What method would you suggest that would be the simplest to use?

                              For example of exactly what I'd like to do:
                              if the previous bar's High-To-Low range was 1.43 to 1.01, and the highest Volume count per price in that range was 4000 contracts and it occurred at price 1.21, then I want my indicator to plot a dash on the previous candle at the 1.21 price level.
                              Thanks!
                              Attached Files
                              Last edited by PaulMohn; 05-05-2022, 09:30 AM.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Max238, Today, 01:28 AM
                              4 responses
                              33 views
                              0 likes
                              Last Post Max238
                              by Max238
                               
                              Started by r68cervera, Today, 05:29 AM
                              1 response
                              7 views
                              0 likes
                              Last Post NinjaTrader_ChelseaB  
                              Started by geddyisodin, Today, 05:20 AM
                              1 response
                              11 views
                              0 likes
                              Last Post NinjaTrader_Gaby  
                              Started by timko, Today, 06:45 AM
                              2 responses
                              13 views
                              0 likes
                              Last Post NinjaTrader_ChristopherJ  
                              Started by habeebft, Today, 07:27 AM
                              0 responses
                              6 views
                              0 likes
                              Last Post habeebft  
                              Working...
                              X