Volume by Price
Volume by Price
Introduction
Volume-by-Price is an indicator that shows the amount of volume for a particular price range, which is based on closing prices. The Volume-by-Price
bars are horizontal and shown on the left side of the chart to correspond with these price ranges. Chartists can view these bars as a single color or with
two colors to separate up volume and down volume. By combining volume and closing prices, this indicator can be used to identify high-volume price
ranges to mark support or resistance
Calculation
Volume-by-Price calculations are based on the entire period displayed on the chart. Volume-by-Price on a five-month daily chart would be based
on ALL five months of daily closing data. Volume-by-Price on a two-week 30-minute chart would be based on two weeks of 30-minute closing data.
Volume-by-Price on a three-year weekly chart would be based on three years of weekly closing data. You get the idea. Volume-by-Price calculations do
not extend beyond the historical data shown on the chart.
There are four steps involved in the calculation.
This example is based on closing prices and the default parameter setting (12).
1. Find the high-low range for closing prices for the entire period.
2. Divide this range by 12 to create 12 equal price zones.
3. Total the amount of volume traded within each price zone.
4. Divide the volume into up volume and down volume (optional).
Note that volume is negative when the closing price moves down from one period to the next. Volume is positive when the closing price moves up from
one period to the next.
The example above shows a Volume-by-Price calculation taken for the Nasdaq 100 ETF from April 12th until September 15th, 2010. Closing prices
ranged from 40.32 to 47.87 during this period (47.87 – 40.32 = 7.55). The one hundred and ten closing prices (one for each trading day) were sorted
from low to high and then divided into 12 even price zones (7.55/12 = .6292).
The chart above highlights the first three price zones (40.32 to 40.95, 40.96 to 41.58 and 41.59 to 42.21). Starting from the low (40.32), we can add the
zone size (.6292) to create the price zones leading to the high. Only prices that fall within these zones are used for that particular Volume-by-Price
calculation.
The Volume-by-Price bars represent the total volume for each price zone. Volume can then be separated into positive and negative volume. Notice that
the Volume-by-Price bars on the chart above are red and green to separate positive volume from negative volume.
Interpretation
Volume-by-Price can be used to identify current support and resistance levels as well as estimate future support and resistance levels. Price zones with
heavy volume reflect elevated interest levels that can influence future supply or demand (a.k.a. resistance or support). Long Volume-by-Price bars
underneath prices should be watched as potential support during a pullback. Similarly, long Volume-by-Price bars above prices should be watched as
potential resistance on a bounce.
Price breaks above or below long Volume-by-Price bars can also be used as signals. A break above a long bar shows strength because demand was
strong enough to overcome a supply overhang. Similarly, a break below a long bar shows weakness because supply was ample enough to overwhelm
demand.
Nuances
Before looking at some examples, it is important to understand how Volume-by-Price works. Volume-by-Price can be used to identify current support
or resistance. Current bars should not be used to validate past support or resistance levels because the indicator is based on all the price-
volume data shown on the chart. This means six months of data for a chart that extends from January to June. Bars may appear to identify support in
March, but keep in mind that the indicator data extends well beyond March because the chart ends in June.
Chartists should also understand that big gaps can produce bars that equal zero. This makes sense because Volume-by-Price equals zero when there are
no closing prices within a specific price zone.
Identifying Support
The chart for Netflix (NFLX) shows Volume-by-Price identifying support around 95-100 at the end of June. Notice that this is the longest bar. Also,
notice that NFLX is beginning a pullback so we can use Volume-by-Price to estimate support in the near future. The second chart shows NFLX with the
yellow area marking Volume-by-Price support from the first chart. Support was expected in the 95-100 area and the stock reversed here in late July.
Notice that volume surged in August to validate the reversal off of support.
Identifying Resistance
The chart for TE Connectivity (TEL) shows Volume-by-Price identifying resistance around 26-26.5 in early August. Remember, the April break above
this bar is not really a breakout because the current Volume-by-Price calculation extends from January to early August. The second longest bar marks
current resistance in the 26-26.5 area. TEL is at its make-or-break point with prices near resistance. The second chart shows Volume-by-Price
resistance from the first and the ultimate failure at resistance.
Support Breaks
A break below a long Volume-by-Price bar signals increasing supply or selling pressure that can foreshadow lower prices. Long bars below prices show
elevated interest areas and potential support. A break below this support zone signals a significant increase in selling pressure and lower prices are then
expected.
The SanDisk (SNDK) chart shows a long Volume-by-Price bar marking support in the 39-43 area in mid-August. Also, notice that the stock forged at
least three reaction lows around 42 from early July to mid-August. This support (demand) zone is clearly marked. The second chart shows SNDK
breaking below the previously identified Volume-by-Price support zone with high volume. Demand crumbled, supply won the day and prices moved
sharply lower.
Resistance Breaks
A break above a long Volume-by-Price bar signals an increase in demand that can foreshadow higher prices. Long bars above prices mark supply
overhangs that demand has not been able to overcome. A break above this resistance zone signals strengthening demand and higher prices are
expected.
Sometimes chartists need to combine price action and Volume-by-Price to identify support zones and resistance zones. The McDonalds (MCD) chart
shows a long bar marking overhead supply between 60 and 61. The stock also met resistance between 61 and 62 with reaction highs in late April and
mid-June. For support, the second and third longest bars mark potential demand in the 57.5-58.5 area and the stock is near the late May low. Overall, a
large Symmetrical Triangle could be forming on the price chart as MCD tries to hold above the late May low. The second chart shows MCD breaking
resistance in July and surging to new highs in August.
Conclusions
Volume-by-Price is best suited for identifying present or future support and resistance. The indicator marks potential support when prices are above a
long bar and potential resistance when prices are below a long bar. Chartists can enhance their analysis by looking at the positive (green) and negative
(red) volume within the Volume-by-Price bars. Long green portions reflect more demand that can further validate support. Long red portions reflect
more supply that can further validate resistance. It is important to confirm Volume-by-Price findings with other indicators and analysis
techniques. Momentum oscillatorsand chart patterns are good complements to this volume based indicator.
_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
volDiff = ROC( V, 1 );
_N(titleSpecial = " Vol " + WriteVal( V, 1.0 ) + WriteIf( volDiff < 0, EncodeColor( colorRed ), EncodeColor(
colorGreen ) ) + " (" + WriteVal( volDiff , 1.1 ) + "%%)" +
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%)" +
titleSpecial, O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( C, "Close", ParamColor("Price Color", colorDefault ), styleNoTitle | ParamStyle("Price Style") |
GetPriceStyle(), Null, Null, 0, 0 );
_SECTION_END();
_SECTION_BEGIN( "MPLite" );
// i.e. "•Warning 502: Calling Plot()/PlotOHLC over 500 times is displayed in indicator in runtime to
prevent abuse"
// - uses GFX for major calls of plot only if AB version newer than 5.40 - this only delays reaching the plot
limit
function Lastthursday() {
return returnvalue;
procedure PlotlinewithGFXinit() {
RequestTimedRefresh(1);
GfxSetOverlayMode( 0 );
AB_penwidth = Pen_Thickness;
if ( Period == "Hourly" ) {
if ( Period == "Daily" ) {
BarsInDay = BarsSince( Day() != Ref( Day(), -1 ) ) ;
if ( Period == "Weekly" ) {
}
if ( Period == "Lastthursday" ) {
den = ( coverage / 10 );
multiplier = IIf( round( totalVisible ) / 300 < 1, 1, round( totalVisible ) / 300 );
if ( ViewVlines == 1 ) {
relTodayRange = 0;
x = 0;
basey = 0;
basex = 0;
newday = 0;
total = 0;
shiftup = 0;
shiftdn = 0;
Line = Null;
Voloumeunit = 0;
PlotlinewithGFXinit();
for ( i = IIf( FirstVisibleBar - 100 > 1, FirstVisibleBar - 100, FirstVisibleBar ); i < Lastvisiblebar AND i <
BarCount - 1 ; i++ ) {
if ( BarsInDay[i] == 0 ) {
t = BarsInDay[i-1];
if ( EnIB == 1 ) {
IBH = HHV( H, IBBars );
poc = 0;
pocj = 0;
poc = x[j];
pocj = j;
poc = x[j];
pocj = j;
shiftup = a;
shiftdn = a;
break;
shiftup = a;
shiftdn = pocj;
break;
shiftdn = a + 1;
break;
if ( ViewVpoc == 1 ) {
newi = Null;
newi = j;
break;
else {
newi = BarCount;
Vah = LineArray( baseX[i], baseY + ( pocj + shiftup ) * den, i, baseY + ( pocj + shiftup ) *
den );
Val = LineArray( baseX[i], baseY + ( pocj - shiftdn ) * den, i, baseY + ( pocj - shiftdn ) * den
);
pocline = LineArray( basex, basey + pocj * den, basex[i] + poc, basey + pocj * den );
Vahn = LineArray( i, baseY + ( pocj + shiftup ) * den, i + t , baseY + ( pocj + shiftup ) * den
);
Valn = LineArray( i, baseY + ( pocj - shiftdn ) * den, i + t , baseY + ( pocj - shiftdn ) * den );
else {
if ( ViewYvalues == 1 ) {
if ( ViewTPO == 1 ) {
}
if ( Viewvalues == 1 ) {
PlotText( "" + round( ( baseY + ( pocj + shiftup )*den ) ), baseX[i], baseY + ( pocj +
shiftup )*den, colorWhite, colorDarkGrey );
PlotText( "" + round( ( baseY + ( pocj - shiftdn )*den ) ), baseX[i], baseY + ( pocj -
shiftdn )*den, colorWhite, colorDarkGrey );
else {
if ( P > 0 ) {
Plot( line, "", IIf( p > ( pocj + shiftup ), Color_Above_VA, IIf( p <= ( pocj +
shiftup )AND p >= ( pocj - shiftdn ), Color_VA, Color_Below_VA ) ) , EnMP2 );
}
///////////////////
basex = 0;
x = 0;
Basex = i;
baseY = Bot[i];
//////////////////////////////////
poc = 0;
pocj = 0;
poc = x[j];
pocj = j;
poc = x[j];
pocj = j;
}
Value_area = ( total[relTodayRange] * percent ) / 100;
shiftup = a;
shiftdn = a;
break;
shiftup = a;
shiftdn = pocj;
break;
shiftdn = a + 1;
break;
}
}
Vah = LineArray( baseX[i], baseY + ( pocj + shiftup ) * den, i, baseY + ( pocj + shiftup ) * den );
Val = LineArray( baseX[i], baseY + ( pocj - shiftdn ) * den, i, baseY + ( pocj - shiftdn ) * den );
pocline = LineArray( basex, basey + pocj * den, basex[i] + poc, basey + pocj * den );
if ( ViewTPO == 1 ) {
if ( Viewvalues == 1 ) {
PlotText( "" + round( ( baseY + ( pocj + shiftup )*den ) ), baseX[i], baseY + ( pocj + shiftup )*den,
colorWhite, colorDarkGrey );
PlotText( "" + round( ( baseY + ( pocj - shiftdn )*den ) ), baseX[i], baseY + ( pocj - shiftdn )*den,
colorWhite, colorDarkGrey );
}
// pocline
else {
Plot( line, "", IIf( p > ( pocj + shiftup ), Color_Above_VA, IIf( p <= ( pocj + shiftup )AND p
>= ( pocj - shiftdn ), IIf( x[p]-x_scale < 1, colorRed, colorBlueGrey), Color_Below_VA ) ), EnMP2 );
_SECTION_END();