Login Page - Create Account

Support Board


Date/Time: Fri, 02 Jan 2026 10:17:27 +0000



Volume Distribution Paint Bar Study

View Count: 158

[2025-11-17 22:28:16]
User688525 - Posts: 373
Hello Sierra,
Is the source code available for the Volume Distribution Paint Bar Study (VolumeDistributionPaintBarStudy)?

I am trying to color individual price levels on a bar. Is this the best study to base this off? Is there an ACSIL function, etc., to color price levels based on volume, bid/ask, etc? I am aware of the Bid Ask Volume Bars, but I would like to build a custom study for this.

Thank you
[2025-11-18 07:12:33]
Sierra_Chart Engineering - Posts: 22147
Yes the source code is available:

SCSFExport scsf_VolumeDistributionPaintBarStudy(SCStudyInterfaceRef sc)
{
  SCSubgraphRef Subgraph_Close = sc.Subgraph[0];
  SCSubgraphRef Subgraph_BarTop = sc.Subgraph[1];
  SCSubgraphRef Subgraph_BarBot = sc.Subgraph[2];
  SCSubgraphRef Subgraph_UpperPercentTop = sc.Subgraph[3];
  SCSubgraphRef Subgraph_UpperPercentBot = sc.Subgraph[4];
  SCSubgraphRef Subgraph_LowerPercentTop = sc.Subgraph[5];
  SCSubgraphRef Subgraph_LowerPercentBot = sc.Subgraph[6];
  SCSubgraphRef Subgraph_MeanTop = sc.Subgraph[7];
  SCSubgraphRef Subgraph_MeanBot = sc.Subgraph[8];
  SCSubgraphRef Subgraph_ModeTop = sc.Subgraph[9];
  SCSubgraphRef Subgraph_ModeBot = sc.Subgraph[10];

  SCInputRef Input_MinRangeInTicks      = sc.Input[0];
  SCInputRef Input_BottomVolumePercentage    = sc.Input[1];
  SCInputRef Input_TopVolumePercentage    = sc.Input[2];
  
  if (sc.SetDefaults)
  {
    // Set the configuration and defaults
    sc.GraphName = "Volume Distribution Paint Bar Study";    

    sc.GraphRegion = 0;
    sc.DisplayStudyInputValues = 0;
    sc.MaintainVolumeAtPriceData = 1;
    sc.DrawZeros = 0;
    sc.AutoLoop = 1;

    // inputs
    Input_MinRangeInTicks.Name = "Minimum Range In Ticks:";
    Input_MinRangeInTicks.SetInt(1);
    Input_MinRangeInTicks.SetIntLimits(1, INT_MAX);

    Input_BottomVolumePercentage.Name = "Bottom Volume Percentage (0-100, 1.0 = 1%)";
    Input_BottomVolumePercentage.SetFloat(15.0f);
    Input_BottomVolumePercentage.SetFloatLimits(0.0f, 100.0f);

    Input_TopVolumePercentage.Name = "Top Volume Percentage (0-100, 1.0 = 1%)";
    Input_TopVolumePercentage.SetFloat(85.0f);
    Input_BottomVolumePercentage.SetFloatLimits(0.0f, 100.0f);

    uint32_t OutlineColor = sc.ChartBackgroundColor == COLOR_BLACK ? COLOR_WHITE : COLOR_BLACK;

    // subgraphs
    Subgraph_Close.Name = "Close";
    Subgraph_Close.DrawStyle = DRAWSTYLE_TRIANGLE_RIGHT_OFFSET_FOR_CANDLESTICK;
    Subgraph_Close.PrimaryColor = OutlineColor;
    Subgraph_Close.LineWidth = 5;
    Subgraph_Close.DrawZeros = 0;

    Subgraph_BarTop.Name = "Bar High";
    Subgraph_BarTop.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_OPEN;
    Subgraph_BarTop.PrimaryColor = COLOR_YELLOW;
    Subgraph_BarTop.LineWidth = 1;

    Subgraph_BarBot.Name = "Bar Low";
    Subgraph_BarBot.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_CLOSE;
    Subgraph_BarBot.PrimaryColor = OutlineColor;
    Subgraph_BarBot.LineWidth = 1;

    Subgraph_UpperPercentTop.Name = "Top % High";
    Subgraph_UpperPercentTop.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_OPEN;
    Subgraph_UpperPercentTop.PrimaryColor = COLOR_RED;
    Subgraph_UpperPercentTop.LineWidth = 1;

    Subgraph_UpperPercentBot.Name = "Top % Low";
    Subgraph_UpperPercentBot.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_CLOSE;
    Subgraph_UpperPercentBot.PrimaryColor = OutlineColor;
    Subgraph_UpperPercentBot.LineWidth = 0;

    Subgraph_LowerPercentTop.Name = "Bottom % High";
    Subgraph_LowerPercentTop.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_OPEN;
    Subgraph_LowerPercentTop.PrimaryColor = COLOR_BLUE;
    Subgraph_LowerPercentTop.LineWidth = 1;

    Subgraph_LowerPercentBot.Name = "Bottom % Low";
    Subgraph_LowerPercentBot.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_CLOSE;
    Subgraph_LowerPercentBot.PrimaryColor = OutlineColor;
    Subgraph_LowerPercentBot.LineWidth = 0;

    Subgraph_MeanTop.Name = "Mean Top";
    Subgraph_MeanTop.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_OPEN;
    Subgraph_MeanTop.PrimaryColor = COLOR_GREEN;
    Subgraph_MeanTop.LineWidth = 1;

    Subgraph_MeanBot.Name = "Mean Bottom";
    Subgraph_MeanBot.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_CLOSE;
    Subgraph_MeanBot.PrimaryColor = OutlineColor;
    Subgraph_MeanBot.LineWidth = 0;

    Subgraph_ModeTop.Name = "Mode Top";
    Subgraph_ModeTop.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_OPEN;
    Subgraph_ModeTop.PrimaryColor = COLOR_MAROON;
    Subgraph_ModeTop.LineWidth = 1;

    Subgraph_ModeBot.Name = "Mode Bottom";
    Subgraph_ModeBot.DrawStyle = DRAWSTYLE_CANDLESTICK_BODY_CLOSE;
    Subgraph_ModeBot.PrimaryColor = OutlineColor;
    Subgraph_ModeBot.LineWidth = 0;

    return;
  }

  float MinRange = Input_MinRangeInTicks.GetInt() * sc.TickSize;
  float HalfMinRange = MinRange / 2.0f;

  Subgraph_Close[sc.Index] = sc.Close[sc.Index];
  Subgraph_BarTop[sc.Index] = sc.High[sc.Index];
  Subgraph_BarBot[sc.Index] = sc.Low[sc.Index];

  // Calc Volume Weighted Avg of the prices for this bar, find mode, and find range edges
  unsigned int TotalVolume = static_cast<unsigned int>(sc.Volume[sc.Index]);
  unsigned int LowVolume = static_cast<unsigned int>(static_cast<float>(TotalVolume) * (Input_BottomVolumePercentage.GetFloat() * 0.01f) );
  unsigned int HighVolume = static_cast<unsigned int>(static_cast<float>(TotalVolume) * (Input_TopVolumePercentage.GetFloat() * 0.01f) );

  TotalVolume = 0;
  double Sum = 0;
  
  unsigned int MaxVolume = 0;
  float MaxVolumePrice = 0;

  const s_VolumeAtPriceV2 *p_VolumeAtPrice = nullptr;

  int NumVAPElementsAtBarIndex = sc.VolumeAtPriceForBars->GetSizeAtBarIndex(sc.Index);
  for (int VAPIndex = 0; VAPIndex < NumVAPElementsAtBarIndex; VAPIndex++)
  {
    sc.VolumeAtPriceForBars->GetVAPElementAtIndex(sc.Index, VAPIndex, &p_VolumeAtPrice);

    float Price = p_VolumeAtPrice->PriceInTicks * sc.TickSize;
    Sum += (Price * p_VolumeAtPrice->Volume);

    unsigned int PriorTotalVolume = TotalVolume;
    TotalVolume += p_VolumeAtPrice->Volume;

    if (PriorTotalVolume < LowVolume && TotalVolume >= LowVolume)
    {
      Subgraph_LowerPercentTop[sc.Index] = Price;
      Subgraph_LowerPercentBot[sc.Index] = sc.Low[sc.Index];
    }

    if (PriorTotalVolume < HighVolume && TotalVolume >= HighVolume)
    {
      Subgraph_UpperPercentTop[sc.Index] = sc.High[sc.Index];
      Subgraph_UpperPercentBot[sc.Index] = Price;
    }

    if (p_VolumeAtPrice->Volume > MaxVolume)
    {
      MaxVolume = p_VolumeAtPrice->Volume;
      MaxVolumePrice = Price;
    }
  }

  double Average = TotalVolume == 0 ? 0 : Sum / TotalVolume;

  if (Average != 0)
  {
    Subgraph_MeanTop[sc.Index] = static_cast<float>(Average + HalfMinRange);
    Subgraph_MeanBot[sc.Index] = static_cast<float>(Average - HalfMinRange);
  }

  if (MaxVolume != 0)
  {
    Subgraph_ModeTop[sc.Index] = MaxVolumePrice + HalfMinRange;
    Subgraph_ModeBot[sc.Index] = MaxVolumePrice - HalfMinRange;
  }
}

Sierra Chart Support - Engineering Level

Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy:
https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation

For the most reliable, advanced, and zero cost futures order routing, use the Teton service:
Sierra Chart Teton Futures Order Routing
[2025-11-20 11:50:20]
User688525 - Posts: 373
Thank you very much Sierra Engineering!

To post a message in this thread, you need to log in with your Sierra Chart account:

Login

Login Page - Create Account