Login Page - Create Account

Support Board


Date/Time: Mon, 07 Jul 2025 03:33:18 +0000



Post From: Horizontal Volume by Price Feature Request .....

[2025-07-03 17:48:51]
Tony - Posts: 610
[post edited as one solution was found]

We have access to VbP data by using something called "sc.VolumeAtPriceForBars" in Sierra's toolbox.

Link To Documentation

One of the solution is to draw a Subgraph, as it is showed in the attached animated 20-second screenshot, (ES mini July-01 2025, right after market open, around 09:31 Eastern), chart bar space has to be 1 to have a smooth looking of the distribution curve.

Unfortunately there are a few issues, not all VbP values are accurate; and my study's recalculating time went from 3ms to 80ms after adding this Subgraph; also Sierra crashes after using this study for about 5 to 10 minutes, it is basically not usable, I just don't have time to find out what is wrong.

This is pretty much as far as I can go, I am a very low level armature coder. Hopefully you would be able to optimize it. (the code below just to give you a rough idea, not ready for copy and paste, because some functions and variables are claimed somewhere else), "ProfileLine" is a subgraph. ProfileRange[0]/ProfileRange[1] are lowest and highest prices of profile/trading day

Good luck

BTW, you didn't explain the reason why you need a view VbP with different angle, maybe you could elaborate when you have time ... besides having whole lot of fun, I don't see any other reasons.


  if (sc.SetDefaults) {
    sc.GraphName = "My Custom Study";
    sc.GraphRegion = 0;
    sc.AutoLoop = 1;
    sc.UpdateAlways = 1;
    sc.MaintainVolumeAtPriceData = 1;

    return;
  }
  //std::vector <int> ProfileValues;
  //ProfileValues.clear();
  //for (double LevelCount {ProfileRange[0]}; LevelCount<=ProfileRange[1]; LevelCount+=0.25)
    //ProfileValues.push_back(0);
  
  int TotalLevels = (int)((ProfileRange[1] - ProfileRange[0]) / 0.25) + 1;
  int ProfileValues[400] {};
  
  for (int IndexCount {ProfileStartIndex}; IndexCount<=ProfileEndIndex; IndexCount++) {  
    const s_VolumeAtPriceV2 *p_VolumeAtPrice=NULL;
    int VAPSizeAtBarIndex = sc.VolumeAtPriceForBars->GetSizeAtBarIndex(IndexCount);

    for (int VAPIndex {0} ; VAPIndex<VAPSizeAtBarIndex; VAPIndex++) {
      if (!sc.VolumeAtPriceForBars->GetVAPElementAtIndex(IndexCount, VAPIndex, &p_VolumeAtPrice))
        break;
      int IndexID {(int)((sc.Low[IndexCount] + 0.25*VAPIndex - ProfileRange[0]) / 0.25)};
      ProfileValues[IndexID] += p_VolumeAtPrice->Volume;
    }
  }

  //DebuggingText.Format("Result:\n\n");
  int HighestVolume {0};
  for (int IndexCount {0}; IndexCount<TotalLevels; IndexCount++) {
    //DebuggingText.AppendFormat("%d\n", ProfileValues[IndexCount]);
    if (ProfileValues[IndexCount] > HighestVolume)
      HighestVolume = ProfileValues[IndexCount];
  }
  //DebuggingText.AppendFormat("HighestVolume: %d", HighestVolume);
  
  int HorizShift = sc.IndexOfFirstVisibleBar + 137;
  int BaseLine = (ProfileRange[0] + ProfileRange[1]) / 2.0 - 17.0;
  for (int IndexCount{HorizShift}; IndexCount<TotalLevels+HorizShift; IndexCount++)
    ProfileLine[IndexCount] = BaseLine + 20.0*ProfileValues[IndexCount-HorizShift]/HighestVolume;
  AddDrawing(sc, UniqueNumber++, 1, HorizShift, TotalLevels+HorizShift, DRAWING_LINE, BaseLine, BaseLine, RGB(37,37,37), 1, "");
  
  int IndexOfLastPrice {(int)((sc.Close[sc.Index] - ProfileRange[0]) / 0.25) + HorizShift};
  AddDrawing(sc, UniqueNumber++, 0, IndexOfLastPrice, IndexOfLastPrice, DRAWING_LINE, BaseLine, BaseLine+20, RGB(37,37,37), 1, "");


Date Time Of Last Edit: 2025-07-07 00:52:24
imageVbP.gif / V - Attached On 2025-07-05 05:50:49 UTC - Size: 39.67 KB - 42 views