Further modify relative volume indicator to segment the volume bars with horizontal lines that show the size of the trades in T&S

lmk99

Member
I already modified the built-in relative volume indicator to be color-coded in a way that reflects buy vs sell relative volume intuitively:

Code:
# TD Ameritrade IP Company, Inc. (c) 2014-2021
#

declare lower;
declare zerobase;

input length = 60;
input numDev = 2.0;
input allowNegativeValues = yes;

def rawRelVol = (volume - Average(volume, length)) / StDev(volume, length);
plot RelVol = if allowNegativeValues then rawRelVol else Max(0, rawRelVol);
plot StDevLevel = numDev;

RelVol.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
RelVol.SetLineWeight(3);
RelVol.DefineColor("UpCandleAbove", Color.Light_Green);
RelVol.DefineColor("DownCandleAbove", Color.Red);
RelVol.DefineColor("UpCandleBelow", Color.CYAN);
RelVol.DefineColor("DownCandleBelow", Color.DARK_ORANGE);
RelVol.DefineColor("DownCandleNegBelow", CreateColor(60,25,25));
RelVol.DefineColor("UpCandleNegBelow", CreateColor(25,60,25));
RelVol.AssignValueColor(if RelVol >= numDev and RelVol>0 and open<close then RelVol.Color("UpCandleAbove") else if RelVol < numDev and RelVol<0 and open>close then RelVol.Color("DownCandleNegBelow") else if RelVol < numDev and RelVol<0 and open<close then RelVol.Color("UpCandleNegBelow")  else if RElVol>0 and open<close then RelVol.Color("UpCandleBelow") else if RelVol >= numDev and RelVol>0 and open>close then RelVol.Color("DownCandleAbove") else if RElVol>0 and open>close then  RelVol.Color("DownCandleBelow") else  Color.Gray);
StDevLevel.SetDefaultColor(GetColor(7));
StDevLevel.SetStyle(Curve.SHORT_DASH);

The result looks like this on a 1min chart (example here is KOSS):

Fk8EQ3K.png


What I'm interested in, however, is to further modify the relative volume indicator to reflect what is happening with the transaction sizes in the tape.

For example, I was thinking of something like horizontal lines segmenting the volume bars, or maybe a region of the volume bar highlighted with a brighter or darker shade with the proportionally highlighted area reflecting the size of the trade(s). Some way in other words to reflect if the volume bar consists of a bunch of small sells or a massive block sale, and likewise for buys. Because currently, the only way I can be aware of huge buys or sells happening in one transaction is to keep my eyes on the tape. But of course it's very helpful for being able to interpret whether the stock is in accumulation or distribution, to be able to see if any individual sells or buys have sizes that are some standard deviation above normal.

Does anyone have ideas or suggestions for how this could be accomplished (i.e. reflecting large individual tape transactions in a lower study), and furthermore, how it could be combined with the relative volume indicator?

EDIT: Another thing that would be useful is if within the 1min volume bar, it was possible to represent both buy and sell transactions, because that would help to avoid being fooled by when the bar gets painted a misleading color. For example, there can be a 1 share buy at $1, a 10,000 share buy at $2, and then a 1 share sell at $0.99 before the candle closes, and then it makes it look like a massive dump happened in that 1min bar. I've noticed this happens sometimes before a stock gets pumped hard and it's often difficult to see through the deception unless also watching the tape at the same time.
 
Last edited:

rad14733

Well-known member
VIP
@lmk99 Thinkscript only allows a means of Buy and Sell volumes but NOT individual trade volumes as we can see in Time and Sales... There are several volume indicators here in these forums that display the Buy/Sell volume comparison...
 

lmk99

Member
@lmk99 Thinkscript only allows a means of Buy and Sell volumes but NOT individual trade volumes as we can see in Time and Sales... There are several volume indicators here in these forums that display the Buy/Sell volume comparison...
From your reply I understand that it's possible to break down the ratio of buy to sell volume within a candle (to help see through misleading paint jobs on the volume bar) but it's not possible to access within a study the individual trade volumes to designate large chunked trades.

Maybe the closest way to represent that as a lower study would be to have a separate cell which is a tick-based volume study (like Welkin's tick volume study).

But it seems to me like actually the Ticks Per Volume study posted here might work with a 1min chart: https://usethinkscript.com/threads/tick-buy-and-sell-volume-indicator-for-thinkorswim.534/

The description given is: "Shows volume divided by ticks or in other words the volume traded divided by the number of trades. Higher means larger lots being traded and lower bar means smaller lots."

The code is as follows:

Code:
declare lower;
declare zerobase;

def TradeCount = tick_count;
def MoneyCount = volume;

plot avgTradeCount = ((MoneyCount[1] + MoneyCount) / 2) / ((TradeCount + TradeCount[1]) / 2);

AvgTradeCount.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
AvgTradeCount.AssignValueColor(if TradeCount >= AvgTradeCount then Color.UPTICK else Color.DOWNTICK);

I'm going to see if there's a way to usefully integrate this into the relative volume study.
 

lmk99

Member
Hi all, this is what I came up with for trying to represent that the share amounts of the individual trade(s) in a candle exceed one or two standard deviations: a horizontal line that is color coded which appears on top of the volume cande. This is the code:

Code:
#
# TD Ameritrade IP Company, Inc. (c) 2014-2021
#

declare lower;
declare zerobase;

input length = 60;
input numDev = 2.0;
input allowNegativeValues = yes;

def rawRelVol = (volume - Average(volume, length)) / StDev(volume, length);
plot RelVol = if allowNegativeValues then rawRelVol else Max(0, rawRelVol);
plot StDevLevel = numDev;

RelVol.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
RelVol.SetLineWeight(3);
RelVol.DefineColor("UpCandleAbove", Color.Light_Green);
RelVol.DefineColor("DownCandleAbove", Color.Red);
RelVol.DefineColor("UpCandleBelow", Color.CYAN);
RelVol.DefineColor("DownCandleBelow", Color.DARK_ORANGE);
RelVol.DefineColor("DownCandleNegBelow", CreateColor(60,25,25));
RelVol.DefineColor("UpCandleNegBelow", CreateColor(25,60,25));
RelVol.AssignValueColor(if RelVol >= numDev and RelVol>0 and open<close then RelVol.Color("UpCandleAbove") else if RelVol < numDev and RelVol<0 and open>close then RelVol.Color("DownCandleNegBelow") else if RelVol < numDev and RelVol<0 and open<close then RelVol.Color("UpCandleNegBelow")  else if RElVol>0 and open<close then RelVol.Color("UpCandleBelow") else if RelVol >= numDev and RelVol>0 and open>close then RelVol.Color("DownCandleAbove") else if RElVol>0 and open>close then  RelVol.Color("DownCandleBelow") else  Color.Gray);
StDevLevel.SetDefaultColor(GetColor(7));
StDevLevel.SetStyle(Curve.SHORT_DASH);

def TradeCount = tick_count;
def MoneyCount = volume;

def avgTradeCount = ((MoneyCount[1] + MoneyCount) / 2) / ((TradeCount + TradeCount[1]) / 2);

def ticksizestddev = (avgTradeCount - Average(avgTradeCount, length)) / StDev(avgTradeCount, length);

plot relticksize = RelVol;

relticksize.SetPaintingStrategy(PaintingStrategy.HoriZONTAL);
relticksize.SetLineWeight(3);
relticksize.AssignValueColor(if ticksizestddev >= numDev and ticksizestddev>0 and open<close then RelVol.Color("UpCandleAbove") else if ticksizestddev < numDev and ticksizestddev<0 and open>close then RelVol.Color("DownCandleNegBelow") else if ticksizestddev < numDev and ticksizestddev<0 and open<close then RelVol.Color("UpCandleNegBelow")  else if ticksizestddev>0 and open<close then RelVol.Color("UpCandleBelow") else if ticksizestddev >= numDev and ticksizestddev>0 and open>close then RelVol.Color("DownCandleAbove") else if ticksizestddev>0 and open>close then  RelVol.Color("DownCandleBelow") else Color.Gray);

It seems to work pretty OK most of the time, but it doesn't always convey the information that I want it to convey. Recall that the purpose of this indicator is to convey the information that is shown in Time and Sales, to see if the buy or sell volume of that bar consists of a bunch of average sized trades or if it contains any large sized trades. The problem is that a large sized buy of the ask can still happen in Time and Sales but then the information is coded as sell volume if the candle closes down, as in this type of case:

9uOT1It.png


Not sure if you can see well but there was a huge 84,000 share buy of the ask but it was concealed in one of the candles (it may not have been the exact bar I circled, but the point is that the bars made it hard to tell that this had happened because it closed as an indecision candle or a down candle to conceal it; indeed a few minutes after this large buy, the bid moved up significantly).

So I think the solution is that the code for the horizontal line's color needs to somehow factor in if the large trade(s) (or if that's not possible, if the trades overall) were buys or sells, instead of basing the color on how the price candle closed.

Any ideas for how to do this? I think this would be a really useful modification to the relative volume indicator if this could be done. This is for reference an example of when the indicator does what I want, because the candle closes in congruence with the large buy occurring:

ZAZt2oT.png


But how can the horizontal line on the volume bar be made to display that same color even if the candle had closed flat or down?
 
Last edited:

TexasAVI03

New member
ToS_lowerStudy_volBuySell_Indicator

Code:
# Show total volume in gray.  Buying volume in green.  Sell Volume in red.
# Volume average is gray line.
# Specified percent over average volume is cyan triangles.
# Horserider 12/30/2019 derived from some already existing studies.


declare lower;

#Inputs

input Show30DayAvg = yes;
input ShowTodayVolume =  yes;
input ShowPercentOf30DayAvg = yes;
input UnusualVolumePercent = 200;
input Show30BarAvg = yes;
input ShowCurrentBar = yes;
input ShowPercentOf30BarAvg = yes;
input ShowSellVolumePercent = yes;

def O = open;
def H = high;
def C = close;
def L = low;
def V = volume;
def buying = V*(C-L)/(H-L);
def selling = V*(H-C)/(H-L);

# Selling Volume

Plot SellVol = selling;
SellVol.setPaintingStrategy(PaintingStrategy.Histogram);
SellVol.SetDefaultColor(Color.Red);
SellVol.HideTitle();
SellVol.HideBubble();
SellVol.SetLineWeight(1);

# Total Volume

# Note that Selling + Buying Volume = Volume.
plot TV =  volume;

TV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
TV.SetDefaultColor(Color.GRAY);
#TV.HideTitle();
#TV.HideBubble();
TV.SetLineWeight(1);

Plot BuyVol = buying;
BuyVol.setPaintingStrategy(PaintingStrategy.Histogram);
BuyVol.SetDefaultColor(Color.Green);
BuyVol.HideTitle();
BuyVol.HideBubble();
BuyVol.SetLineWeight(5);

#Volume Data

def volLast30DayAvg = (volume(period = "DAY")[1] + volume(period = "DAY")[2] + volume(period = "DAY")[3] + volume(period = "DAY")[4] + volume(period = "DAY")[5] + volume(period = "DAY")[6] + volume(period = "DAY")[7] + volume(period = "DAY")[8] + volume(period = "DAY")[9] + volume(period = "DAY")[10] + volume(period = "DAY")[11] + volume(period = "DAY")[12] + volume(period = "DAY")[13] + volume(period = "DAY")[14] + volume(period = "DAY")[15] + volume(period = "DAY")[16] + volume(period = "DAY")[17] + volume(period = "DAY")[18] + volume(period = "DAY")[19] + volume(period = "DAY")[20] + volume(period = "DAY")[21] + volume(period = "DAY")[22] + volume(period = "DAY")[23] + volume(period = "DAY")[24] + volume(period = "DAY")[25] + volume(period = "DAY")[26] + volume(period = "DAY")[27] + volume(period = "DAY")[28] + volume(period = "DAY")[29] + volume(period = "DAY")[30]) / 30;
def today = volume(period = "DAY");
def percentOf30Day = Round((today / volLast30DayAvg) * 100, 0);
def avg30Bars = (volume[1] + volume[2] + volume[3] + volume[4] + volume[5] + volume[6] + volume[7] + volume[8] + volume[9] + volume[10] + volume[11] + volume[12] + volume[13] + volume[14] + volume[15] + volume[16] + volume[17] + volume[18] + volume[19] + volume[20] + volume[21] + volume[22] + volume[23] + volume[24] + volume[25] + volume[26] + volume[27] + volume[28] + volume[29] + volume[30]) / 30;
def curVolume = volume;
def percentOf30Bar = Round((curVolume / avg30Bars) * 100, 0);
def SellVolPercent = Round((Selling / Volume) * 100, 0);

# Labels

AddLabel(Show30DayAvg, "Avg 30 Days: " + Round(volLast30DayAvg, 0), Color.LIGHT_GRAY);

AddLabel(ShowTodayVolume, "Today: " + today, (if percentOf30Day >= UnusualVolumePercent then Color.GREEN else if percentOf30Day >= 100 then Color.ORANGE else Color.LIGHT_GRAY));

AddLabel(ShowPercentOf30DayAvg, percentOf30Day + "%", (if percentOf30Day >= UnusualVolumePercent then Color.GREEN else if percentOf30Day >= 100 then Color.ORANGE else Color.WHITE) );

AddLabel(Show30BarAvg, "Avg 30 Bars: " + Round(avg30Bars, 0), Color.LIGHT_GRAY);

AddLabel(ShowCurrentBar, "Cur Bar: " + curVolume, (if percentOf30Bar >= UnusualVolumePercent then Color.GREEN else if PercentOf30Bar >= 100 then Color.ORANGE else Color.LIGHT_GRAY));

AddLabel(ShowPercentOf30BarAvg, PercentOf30Bar + "%", (if PercentOf30Bar >= UnusualVolumePercent then Color.GREEN else if PercentOf30Bar >= 100 then Color.ORANGE else Color.WHITE) );

AddLabel(ShowSellVolumePercent, "Cur Bar Sell %: " + SellVolPercent, (if SellVolPercent > 51 then Color.RED else if SellVolPercent < 49 then Color.GREEN else Color.ORANGE));

input length = 20;
plot VolAvg = Average(volume, length);

VolAvg.SetDefaultColor(GetColor(7));


# hiVolume indicator
# source: http://tinboot.blogspot.com
# author: allen everhart


input type = { default SMP, EXP } ;
input length1 = 20 ;
input hotPct = 100.0 ;

def ma =
if type == type.SMP then
SimpleMovingAvg(volume, length)
else
MovAvgExponential(volume, length);

plot hv =
if 100 * ((volume / ma) - 1) >= hotPct then
ma
else
Double.NaN;

hv.SetDefaultColor( Color.CYAN);
hv.SetLineWeight(1) ;
hv.SetPaintingStrategy( PaintingStrategy.TRIANGLES);;

Alert(today/volLast30DayAvg > 3, "Volume above 300% threshold", Alert.BAR, Sound.Ring);
 

lmk99

Member
ToS_lowerStudy_volBuySell_Indicator

Code:
# Show total volume in gray.  Buying volume in green.  Sell Volume in red.
# Volume average is gray line.
# Specified percent over average volume is cyan triangles.
# Horserider 12/30/2019 derived from some already existing studies.


declare lower;

#Inputs

input Show30DayAvg = yes;
input ShowTodayVolume =  yes;
input ShowPercentOf30DayAvg = yes;
input UnusualVolumePercent = 200;
input Show30BarAvg = yes;
input ShowCurrentBar = yes;
input ShowPercentOf30BarAvg = yes;
input ShowSellVolumePercent = yes;

def O = open;
def H = high;
def C = close;
def L = low;
def V = volume;
def buying = V*(C-L)/(H-L);
def selling = V*(H-C)/(H-L);

# Selling Volume

Plot SellVol = selling;
SellVol.setPaintingStrategy(PaintingStrategy.Histogram);
SellVol.SetDefaultColor(Color.Red);
SellVol.HideTitle();
SellVol.HideBubble();
SellVol.SetLineWeight(1);

# Total Volume

# Note that Selling + Buying Volume = Volume.
plot TV =  volume;

TV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
TV.SetDefaultColor(Color.GRAY);
#TV.HideTitle();
#TV.HideBubble();
TV.SetLineWeight(1);

Plot BuyVol = buying;
BuyVol.setPaintingStrategy(PaintingStrategy.Histogram);
BuyVol.SetDefaultColor(Color.Green);
BuyVol.HideTitle();
BuyVol.HideBubble();
BuyVol.SetLineWeight(5);

#Volume Data

def volLast30DayAvg = (volume(period = "DAY")[1] + volume(period = "DAY")[2] + volume(period = "DAY")[3] + volume(period = "DAY")[4] + volume(period = "DAY")[5] + volume(period = "DAY")[6] + volume(period = "DAY")[7] + volume(period = "DAY")[8] + volume(period = "DAY")[9] + volume(period = "DAY")[10] + volume(period = "DAY")[11] + volume(period = "DAY")[12] + volume(period = "DAY")[13] + volume(period = "DAY")[14] + volume(period = "DAY")[15] + volume(period = "DAY")[16] + volume(period = "DAY")[17] + volume(period = "DAY")[18] + volume(period = "DAY")[19] + volume(period = "DAY")[20] + volume(period = "DAY")[21] + volume(period = "DAY")[22] + volume(period = "DAY")[23] + volume(period = "DAY")[24] + volume(period = "DAY")[25] + volume(period = "DAY")[26] + volume(period = "DAY")[27] + volume(period = "DAY")[28] + volume(period = "DAY")[29] + volume(period = "DAY")[30]) / 30;
def today = volume(period = "DAY");
def percentOf30Day = Round((today / volLast30DayAvg) * 100, 0);
def avg30Bars = (volume[1] + volume[2] + volume[3] + volume[4] + volume[5] + volume[6] + volume[7] + volume[8] + volume[9] + volume[10] + volume[11] + volume[12] + volume[13] + volume[14] + volume[15] + volume[16] + volume[17] + volume[18] + volume[19] + volume[20] + volume[21] + volume[22] + volume[23] + volume[24] + volume[25] + volume[26] + volume[27] + volume[28] + volume[29] + volume[30]) / 30;
def curVolume = volume;
def percentOf30Bar = Round((curVolume / avg30Bars) * 100, 0);
def SellVolPercent = Round((Selling / Volume) * 100, 0);

# Labels

AddLabel(Show30DayAvg, "Avg 30 Days: " + Round(volLast30DayAvg, 0), Color.LIGHT_GRAY);

AddLabel(ShowTodayVolume, "Today: " + today, (if percentOf30Day >= UnusualVolumePercent then Color.GREEN else if percentOf30Day >= 100 then Color.ORANGE else Color.LIGHT_GRAY));

AddLabel(ShowPercentOf30DayAvg, percentOf30Day + "%", (if percentOf30Day >= UnusualVolumePercent then Color.GREEN else if percentOf30Day >= 100 then Color.ORANGE else Color.WHITE) );

AddLabel(Show30BarAvg, "Avg 30 Bars: " + Round(avg30Bars, 0), Color.LIGHT_GRAY);

AddLabel(ShowCurrentBar, "Cur Bar: " + curVolume, (if percentOf30Bar >= UnusualVolumePercent then Color.GREEN else if PercentOf30Bar >= 100 then Color.ORANGE else Color.LIGHT_GRAY));

AddLabel(ShowPercentOf30BarAvg, PercentOf30Bar + "%", (if PercentOf30Bar >= UnusualVolumePercent then Color.GREEN else if PercentOf30Bar >= 100 then Color.ORANGE else Color.WHITE) );

AddLabel(ShowSellVolumePercent, "Cur Bar Sell %: " + SellVolPercent, (if SellVolPercent > 51 then Color.RED else if SellVolPercent < 49 then Color.GREEN else Color.ORANGE));

input length = 20;
plot VolAvg = Average(volume, length);

VolAvg.SetDefaultColor(GetColor(7));


# hiVolume indicator
# source: http://tinboot.blogspot.com
# author: allen everhart


input type = { default SMP, EXP } ;
input length1 = 20 ;
input hotPct = 100.0 ;

def ma =
if type == type.SMP then
SimpleMovingAvg(volume, length)
else
MovAvgExponential(volume, length);

plot hv =
if 100 * ((volume / ma) - 1) >= hotPct then
ma
else
Double.NaN;

hv.SetDefaultColor( Color.CYAN);
hv.SetLineWeight(1) ;
hv.SetPaintingStrategy( PaintingStrategy.TRIANGLES);;

Alert(today/volLast30DayAvg > 3, "Volume above 300% threshold", Alert.BAR, Sound.Ring);

Thanks for the suggestion. This study has the same limitation: where I circled, a huge buy of the ask had occurred in the Time and Sales but the volume studies don't show that at all, they just show red and gray on those bars:

 

TexasAVI03

New member
Thanks for the suggestion. This study has the same limitation: where I circled, a huge buy of the ask had occurred in the Time and Sales but the volume studies don't show that at all, they just show red and gray on those bars:

You're welcome. By chance does that large Buy at the Ask, that will not show up, have extra decimal point numbers? As in the trading price is $. but then all of a sudden you see a series of $.00* or $.00** (*being the extra decimal numbers, equallying a fraction of Bid or Ask price.)
 

ktp

New member
I wish think script allowed access to the time and sell date. but it doesn't seem like it does. I guess only think you can really do is use tick charts and use tick_count/volume on it to ~the sell/buy size.
 

rad14733

Well-known member
VIP
I wish think script allowed access to the time and sell date. but it doesn't seem like it does. I guess only think you can really do is use tick charts and use tick_count/volume on it to ~the sell/buy size.

@ktp You are correct... We do not have access to the Time and Sales data... I believe someone posted a tick-based solution within the past few weeks for someone with the same question...
 

Similar threads

Top