JAT Buy/Sell Volume Pressure Indicator For ThinkOrSwim

justAnotherTrader

Active member
VIP
VIP Enthusiast
Okay, so the most talked about and often most underutilized indicator we have is volume. And I get it, tos gives us beautiful candles and then gives us this boring volume chart underneath as if its an afterthought. So you probably guessed by now, I love pretty volume charts.

Think about all the different types of volume driven price action we get:
  • A ton of small orders comes in with above average volume but the price stays flat
  • A few large orders come in and push the price up 1-ATR
  • A mix of large and small orders come in and the price goes parabolic
  • A mix of large and small orders come in and the stock dumps
This is just 4 scenarios (there are so many more), and each one gives us a clue about whats driving the price without ever opening a news article or listening in on a conference call. So what does it tell us?

It could tell us:
  • A large institution is buying up shares quietly, because of the large order they have chosen to break it down into smaller sizes to avoid driving up the price
  • Some rich retail investor heard their uncle talk about a new product line about to drop an its going to change the industry
  • A, executive order comes out of the white house to shift us away from solar and into nuclear tech for "energy security"
  • The company misses earnings and not only is everyone piling out but algorithms and stop losses are triggering
Again this is just 4 scenarios. So wouldnt it be nice if our indicators did just that, you know indicate. Thats what this mildly edited version of a volume pressure indicator is attempting to do. I say attempting because it is not up to my standard (I am currently working on a better one as we speak) and also because its impossible to capture everything. Especially because true volume starts at the order book. That being said, this does a good job of giving you a quick idea if volume is trending in one way or another and if it seems buyers are more in control vs sellers. And because I am slow and like to be talked to like im 6 by my indicators there is a bunch of context labels for just that.

Enjoy!

mod note:
The ToS data feeds do not provide true buyers and sellers volume.
read here for how the amazing @Jman831 created the original indicator:
https://usethinkscript.com/threads/...e-pressure-for-thinkorswim.11739/#post-101477
1vIcYva.png

Code:
declare lower;
##########################
# Configurable Parameters
##########################
input Deviation_Length = 60;
input Deviate = 2;
input Show_Labels = yes;
input Audible_Alert = yes;
input Show_Arrows = yes;
input UseVWAPFilter = yes;

##########################
# Volume Stats & Context
##########################
def volumeStDev = RelativeVolumeStDev(length = Deviation_Length);
def abovedev = volumeStDev >= Deviate;

def increase = volume > volume[1];
def decrease = volume < volume[1];
def devincrease = increase and abovedev;
def devdecrease = decrease and abovedev;

##########################
# Buying vs. Selling Volume
##########################
def O = open;
def H = high;
def C = close;
def L = low;
def V = volume;

def Buying = if H != L then V * (C - L) / (H - L) else 0;
def Selling = if H != L then V * (H - C) / (H - L) else 0;

##########################
# VWAP Context Filter
##########################
def vwap = VWAP();
def aboveVWAP = close > vwap;
def belowVWAP = close < vwap;

##########################
# Volume Plots
##########################
plot SV = Selling;
SV.AssignValueColor(if devdecrease then Color.PINK else Color.RED);
SV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
SV.SetLineWeight(5);

plot BV = Buying;
BV.AssignValueColor(if devincrease then Color.LIGHT_GREEN else CreateColor(0, 165, 0));
BV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
BV.SetLineWeight(5);

##########################
# Relative Strength Calculation
##########################
def buyStrength = if Average(Buying, Deviation_Length) != 0 then Buying / Average(Buying, Deviation_Length) else 0;
def sellStrength = if Average(Selling, Deviation_Length) != 0 then Selling / Average(Selling, Deviation_Length) else 0;

def buyPct = if Buying + Selling != 0 then Buying / (Buying + Selling) else 0;
def sellPct = 1 - buyPct;

##########################
# Signal Conditions
##########################
def bigBuy = devincrease and buyPct > 0.7;
def bigSell = devdecrease and sellPct > 0.7;

def trendBuy = Buying > Buying[1] and Buying[1] > Buying[2];
def trendSell = Selling > Selling[1] and Selling[1] > Selling[2];

##########################
# Alerts
##########################
Alert(bigBuy and Audible_Alert, "Heavy Buying Surging", Alert.BAR, Sound.Ding);
Alert(bigSell and Audible_Alert, "Heavy Selling Dump", Alert.BAR, Sound.Bell);

##########################
# Arrow Signals
##########################
plot BuyArrow = Show_Arrows and bigBuy and (UseVWAPFilter == no or aboveVWAP);
BuyArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BuyArrow.SetDefaultColor(Color.GREEN);

plot SellArrow = Show_Arrows and bigSell and (UseVWAPFilter == no or belowVWAP);
SellArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SellArrow.SetDefaultColor(Color.RED);

##########################
# Custom Labels (Your Voice)
##########################
AddLabel(Show_Labels, "Buy Vol = " + Round(Buying, 0) +
    (if devincrease then " 🚀 Big Surge" else ""),
    if Buying > Selling then Color.GREEN else Color.DARK_GRAY);

AddLabel(Show_Labels, "Buy %: " + Round(buyPct * 100, 1) + "%" +
    (if buyPct > 0.7 then " | Buyers in Control" else if buyPct < 0.3 then " | Sellers Dominating" else " | Meh"),
    if buyPct > 0.7 then Color.LIGHT_GREEN else if buyPct < 0.3 then Color.RED else Color.GRAY);

AddLabel(Show_Labels, "Sell Vol = " + Round(Selling, 0) +
    (if devdecrease then " 🔻 Major Dump" else ""),
    if Selling > Buying then Color.RED else Color.DARK_GRAY);

AddLabel(Show_Labels, "Sell %: " + Round(sellPct * 100, 1) + "%" +
    (if sellPct > 0.7 then " | Nasty Pressure" else if sellPct < 0.3 then " | Soft Sellers" else " | Mixed Bag"),
    if sellPct > 0.7 then Color.PINK else if sellPct < 0.3 then Color.GRAY else Color.LIGHT_GRAY);

AddLabel(Show_Labels and trendBuy, "3-Bar Buy Momentum Building 📈", Color.CYAN);
AddLabel(Show_Labels and trendSell, "3-Bar Sell Pressure Mounting 📉", Color.ORANGE);

AddLabel(Show_Labels, "VWAP: " + Round(vwap, 2) + (if aboveVWAP then " | Above VWAP" else " | Below VWAP"),
    if aboveVWAP then Color.GREEN else Color.RED);
 
Last edited:
Is there any way to utilize this indicator as part of a scan? I was thinking how useful a scan showing which stocks "buyers in control" would be. Thanks for your advice!

So the buyers in control simply means that by our estimation that there were more buyers than sellers. We "guess" that because the price closed near the top of the candle it must of been more in charge. We then approximate the percentage of buyers in control (which really simply mean the close was near the high).

I say that because this can be misleading, so I am going to give you the code to the scan but its going to have a twist on it. We are going to make sure the candle is of a large enough size to matter. We are also going to make sure the volume is interesting enough for us to look at by normalizing the volume using Z thresholds and make sure the volume is at least 1.5 std larger than normal.

If you want simply buyers in control and I did to much with my edits let me know and I will give that to you but I hope you will allow my artistic liberties here

Code:
# === Inputs ===
input atrLength = 14;
input minBodyToATR = 1;
input volumeZLength = 30;
input volumeZThreshold = 1.5;

# === Core Candle Info ===
def O = open;
def H = high;
def L = low;
def C = close;
def V = volume;

# === Buy/Sell Volume Estimate ===
def Buying = if H != L then V * (C - L) / (H - L) else 0;
def Selling = if H != L then V * (H - C) / (H - L) else 0;
def buyPct = if Buying + Selling != 0 then Buying / (Buying + Selling) else 0;

# === ATR Body Filter ===
def bodySize = AbsValue(C - O);
def atr = Average(TrueRange(H, C, L), atrLength);
def strongBody = bodySize > (atr * minBodyToATR);

# === Volume Z-Score Filter ===
def volAvg = Average(V, volumeZLength);
def volStdev = StDev(V, volumeZLength);
def volumeZScore = if volStdev != 0 then (V - volAvg) / volStdev else 0;
def highVolume = volumeZScore > volumeZThreshold;

#Leave the following line uncommented for Buyers in control
plot scan = (buyPct > 0.7 ) and strongBody;


#Leave the following line uncommented for Sellers in control
#plot scan = (buyPct < 0.3) and strongBody;
 
Okay, so the most talked about and often most underutilized indicator we have is volume. And I get it, tos gives us beautiful candles and then gives us this boring volume chart underneath as if its an afterthought. So you probably guessed by now, I love pretty volume charts.

Think about all the different types of volume driven price action we get:
  • A ton of small orders comes in with above average volume but the price stays flat
  • A few large orders come in and push the price up 1-ATR
  • A mix of large and small orders come in and the price goes parabolic
  • A mix of large and small orders come in and the stock dumps
This is just 4 scenarios (there are so many more), and each one gives us a clue about whats driving the price without ever opening a news article or listening in on a conference call. So what does it tell us?

It could tell us:
  • A large institution is buying up shares quietly, because of the large order they have chosen to break it down into smaller sizes to avoid driving up the price
  • Some rich retail investor heard their uncle talk about a new product line about to drop an its going to change the industry
  • A, executive order comes out of the white house to shift us away from solar and into nuclear tech for "energy security"
  • The company misses earnings and not only is everyone piling out but algorithms and stop losses are triggering
Again this is just 4 scenarios. So wouldnt it be nice if our indicators did just that, you know indicate. Thats what this mildly edited version of a volume pressure indicator is attempting to do. I say attempting because it is not up to my standard (I am currently working on a better one as we speak) and also because its impossible to capture everything. Especially because true volume starts at the order book. That being said, this does a good job of giving you a quick idea if volume is trending in one way or another and if it seems buyers are more in control vs sellers. And because I am slow and like to be talked to like im 6 by my indicators there is a bunch of context labels for just that.

Enjoy!

mod note:

1vIcYva.png

Code:
declare lower;
##########################
# Configurable Parameters
##########################
input Deviation_Length = 60;
input Deviate = 2;
input Show_Labels = yes;
input Audible_Alert = yes;
input Show_Arrows = yes;
input UseVWAPFilter = yes;

##########################
# Volume Stats & Context
##########################
def volumeStDev = RelativeVolumeStDev(length = Deviation_Length);
def abovedev = volumeStDev >= Deviate;

def increase = volume > volume[1];
def decrease = volume < volume[1];
def devincrease = increase and abovedev;
def devdecrease = decrease and abovedev;

##########################
# Buying vs. Selling Volume
##########################
def O = open;
def H = high;
def C = close;
def L = low;
def V = volume;

def Buying = if H != L then V * (C - L) / (H - L) else 0;
def Selling = if H != L then V * (H - C) / (H - L) else 0;

##########################
# VWAP Context Filter
##########################
def vwap = VWAP();
def aboveVWAP = close > vwap;
def belowVWAP = close < vwap;

##########################
# Volume Plots
##########################
plot SV = Selling;
SV.AssignValueColor(if devdecrease then Color.PINK else Color.RED);
SV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
SV.SetLineWeight(5);

plot BV = Buying;
BV.AssignValueColor(if devincrease then Color.LIGHT_GREEN else CreateColor(0, 165, 0));
BV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
BV.SetLineWeight(5);

##########################
# Relative Strength Calculation
##########################
def buyStrength = if Average(Buying, Deviation_Length) != 0 then Buying / Average(Buying, Deviation_Length) else 0;
def sellStrength = if Average(Selling, Deviation_Length) != 0 then Selling / Average(Selling, Deviation_Length) else 0;

def buyPct = if Buying + Selling != 0 then Buying / (Buying + Selling) else 0;
def sellPct = 1 - buyPct;

##########################
# Signal Conditions
##########################
def bigBuy = devincrease and buyPct > 0.7;
def bigSell = devdecrease and sellPct > 0.7;

def trendBuy = Buying > Buying[1] and Buying[1] > Buying[2];
def trendSell = Selling > Selling[1] and Selling[1] > Selling[2];

##########################
# Alerts
##########################
Alert(bigBuy and Audible_Alert, "Heavy Buying Surging", Alert.BAR, Sound.Ding);
Alert(bigSell and Audible_Alert, "Heavy Selling Dump", Alert.BAR, Sound.Bell);

##########################
# Arrow Signals
##########################
plot BuyArrow = Show_Arrows and bigBuy and (UseVWAPFilter == no or aboveVWAP);
BuyArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BuyArrow.SetDefaultColor(Color.GREEN);

plot SellArrow = Show_Arrows and bigSell and (UseVWAPFilter == no or belowVWAP);
SellArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SellArrow.SetDefaultColor(Color.RED);

##########################
# Custom Labels (Your Voice)
##########################
AddLabel(Show_Labels, "Buy Vol = " + Round(Buying, 0) +
    (if devincrease then " 🚀 Big Surge" else ""),
    if Buying > Selling then Color.GREEN else Color.DARK_GRAY);

AddLabel(Show_Labels, "Buy %: " + Round(buyPct * 100, 1) + "%" +
    (if buyPct > 0.7 then " | Buyers in Control" else if buyPct < 0.3 then " | Sellers Dominating" else " | Meh"),
    if buyPct > 0.7 then Color.LIGHT_GREEN else if buyPct < 0.3 then Color.RED else Color.GRAY);

AddLabel(Show_Labels, "Sell Vol = " + Round(Selling, 0) +
    (if devdecrease then " 🔻 Major Dump" else ""),
    if Selling > Buying then Color.RED else Color.DARK_GRAY);

AddLabel(Show_Labels, "Sell %: " + Round(sellPct * 100, 1) + "%" +
    (if sellPct > 0.7 then " | Nasty Pressure" else if sellPct < 0.3 then " | Soft Sellers" else " | Mixed Bag"),
    if sellPct > 0.7 then Color.PINK else if sellPct < 0.3 then Color.GRAY else Color.LIGHT_GRAY);

AddLabel(Show_Labels and trendBuy, "3-Bar Buy Momentum Building 📈", Color.CYAN);
AddLabel(Show_Labels and trendSell, "3-Bar Sell Pressure Mounting 📉", Color.ORANGE);

AddLabel(Show_Labels, "VWAP: " + Round(vwap, 2) + (if aboveVWAP then " | Above VWAP" else " | Below VWAP"),
    if aboveVWAP then Color.GREEN else Color.RED);
Thank you for sharing 🙏
Cannot wait to see the updated version.
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
218 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top