RVOL (Relative Volume) Scan Label Watchlist for ThinkorSwim

Relative volume is one of the most important metrics to get an edge. Why on earth would anyone compare volume at 2pm with volume at 10pm...which is always triple average volume simply because it's the opening hour??? You have to compare apples to apples. How can anyone put on a morning day trade without knowing the relative volume of the first hour compared to average volume of the last 20 first hours? This is something Finviz always had. Yet, TOS is still getting out of bed.

How can anyone put on a 1pm day trade without knowing average volume of the last 20 1pm volumes??
Do you have such a script or know of one? I've written on in NinjaTrader and trying to figure how how to do it ThinkScript? Knowing the last 20 1pm volumes is exactly what I'm looking for on an intraday basis.
 
Hi, turn off the Ext Hours helps somewhat but still not accurate, I tested 4 tickers and 2 of them off within 1%, other 2 varies from 7% to 25%
How about the code for cumulated first 6 bars from the market open for the last 10 days in a 5 min chart? It should work the same as putting a time limit for the first 30 mins. Any idea how to write such code?

The code here probably has some bugs. In looking at it, this seems wrong to me:
Ruby:
def cumVolume = if IsActive and !IsActive[1]
    then volume[1]
    else if IsActive then cumVolume[1] + volume[1]
    else cumVolume[1];

Why is it using an index of 1, getting the previous bar instead of the current, on everything? That doesn't seem right. That seems like it'll get yesterday's last candle. It should probably be:

Ruby:
def cumVolume = if IsActive and !IsActive[1]
    then volume
    else if IsActive then cumVolume[1] + volume
    else cumVolume[1];

Where it's calculating the average may not need all the +1 either, such as in volume[(bpd*1)+1]. And now I remember part of why I had to make modifications when I used this code. In the definition of cumVolumePrev it should be averaging cumVolume not volume. That piece I can paste for you:

Ruby:
# average of cumulative volume at this time of day for the last 10 trading days
def cumVolumePrev = (cumVolume[(bpd*1)] + cumVolume[(bpd*2)] + cumVolume[(bpd*3)] + cumVolume[(bpd*4)] + cumVolume[(bpd*5)] + cumVolume[(bpd*6)] + cumVolume[(bpd*7)] + cumVolume[(bpd*8)] + cumVolume[(bpd*9)] + cumVolume[(bpd*10)]) / 10;

I'd paste the rest of my code for you but it doesn't have the active time window concept which you need.

To test/debug all of this, it's probably easiest to change to a 30m chart so you only care about one candle and don't have to keep adding candles' volumes together to see what it's capturing. Add a label that displays cumVolume. Then find the candle with matching volume. If it matches the volume of the wrong candle then play with the index.
 
Last edited:
Hi, I'm new to thinkscript and love all the great resource here already.

I find that volume helps filter out a lot noise for me. Ideally, I'd like to calculate the current bar's volume percentile relative to all the bars within the last 30 days. I am manually coding a threshold for what I usually trade, but the study becomes useless when I switch symbols.

A couple questions:
  • is there a percentile function? Can't see to find it.
  • Are calculations limited to the current charts timeframe? i.e. A 5 day chart cannot use historical data older than 5 days.
  • If the above isn't possible, any suggestions on how to build a dynamic volume filter?
Thanks in advance!
 
  • is there a percentile function? Can't see to find it.
  • Are calculations limited to the current charts timeframe? i.e. A 5 day chart cannot use historical data older than 5 days.
  • If the above isn't possible, any suggestions on how to build a dynamic volume filter?

There's no percentile function.

TOS will retrieve however many periods it needs to run your calculations, if that data exists. For example, you can have 200 day SMA on a 1 day chart, unless that symbol IPO'd less than 200 trading days ago.

Regarding "I'd like to calculate the current bar's volume percentile relative to all the bars within the last 30 days". If you're thinking of doing this on low timeframes (1m 2m 5m, etc.) and in scans or watchlist columns you'll likely suffer the entire TOS UI slowing to an annoying degree.

Relative Volume (rvol) is probably the closest existing thing to fill your need. It's a measure of today's volume so far compared to the average volume accumulated at the same time of day on previous days. There's a thread for that here but be aware there's some discussion near the end of the thread regarding bugs in one of the implementations. That code is probably the best example of how to do it, if it wasn't buggy. I'm assuming one of the people invested in the outcome will address those issues.

You can modify the rvol script to extend it to 30 days instead of 10 but that also may significantly affect TOS performance if used in scans and watchlist columns if you're set to a low timeframe. 10 days is probably adequate anyway and, as far as I know, is what other platforms that have it built in are using, such as TC2000's Volume Buzz.
 
Last edited:
Thank you. That helps a lot. Even though what I wanted isn't possible, it's helpful to know what ToS can do and it's limitations.

I just pulled the 30day number out of thin air. It may or may not be a good number. I'll take a lookt at rvol, and if it doesn't work for me needs, I'll probably just make a separate python script to run in the background.
 
thanks @BenTen is there a way to put this on a label on the main trade chart rather than being on the watchlist? Thanks

Sure

Code:
def isRollover = GetYYYYMMDD() != GetYYYYMMDD()[1];
def beforeStart = GetTime() < RegularTradingStart(GetYYYYMMDD());
def vol = if isRollover and beforeStart then volume else if beforeStart then vol[1] + volume else Double.NaN;
def PMV = if IsNaN(vol) then PMV[1] else vol;
def AV = AggregationPeriod.DAY;
def x = Average(Volume(period=AV)[1],60);
def y1 = Round((PMV/x),2);
def L = Lg(y1);
def p = if L>=1 then 0 else if L>=0 then 1 else 2;
def y2 = Round(y1,p);
def z = y2;
AddLabel(yes, AsText(z), Color.White);
 
Hi everybody. I am brand new here. I like using the TOS built in study RelativeVolumeStDev. However I would like to set an alert if the numDev were to hit 4.0 or higher during intraday and PM/AH. Could somebody kindly help me out. I've tried using some alert code but no luck; I have no clue what I'm doing. Please help!

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

declare lower;
declare zerobase;

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

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("Above", GetColor(0));
RelVol.DefineColor("Below", GetColor(2));
RelVol.AssignValueColor(if RelVol >= numDev then RelVol.Color("Above") else RelVol.Color("Below"));
StDevLevel.SetDefaultColor(GetColor(7));
StDevLevel.SetStyle(Curve.SHORT_DASH);
 
Try the following - I also added a label for you. If you do not want the label just pick "no" under input.

http://tos.mx/k9BGx4i


Code:
#Alert
def alerttrigger1 = volume crosses above numDev;

input alerttext = "!!!!! Volume crosses Number Deviation  !!!!!";

input UseAlerts = {false, default true};

input AlertType = {default "BAR", "ONCE", "TICK"};

def at = AlertType;

input AlertSound = {"Chimes", "Ring", default "Bell", "NoSound", "Ding"};

Alert (alerttrigger1 and UseAlerts, alerttext, if at == 1 then Alert.ONCE else if at == 2 then Alert.TICK else Alert.BAR, AlertSound);

#Label
input label = yes;

def nDev = alerttrigger1;

AddLabel(label and nDev, " Deviation > Input ", color.PLUM);
 
Try the following - I also added a label for you. If you do not want the label just pick "no" under input.

http://tos.mx/k9BGx4i


Code:
#Alert
def alerttrigger1 = volume crosses above numDev;

input alerttext = "!!!!! Volume crosses Number Deviation  !!!!!";

input UseAlerts = {false, default true};

input AlertType = {default "BAR", "ONCE", "TICK"};

def at = AlertType;

input AlertSound = {"Chimes", "Ring", default "Bell", "NoSound", "Ding"};

Alert (alerttrigger1 and UseAlerts, alerttext, if at == 1 then Alert.ONCE else if at == 2 then Alert.TICK else Alert.BAR, AlertSound);

#Label
input label = yes;

def nDev = alerttrigger1;

AddLabel(label and nDev, " Deviation > Input ", color.PLUM);
@mc01439
Thanks again. I've tested this with /NQ tonighADING]t and it isn't working :( . I've switch the code around and tried other code after reading the "Thinkscript Learning Center" with no luck. I've been trying to get this one thing right for a month and figured I'd find a group and ask folks that know more than me -because I'm obviously not a coder. I am pleased that I've found somebody that could offer some help as I posted the same question 6 hours ago and didn't get an answer - Thus the reason why I posted again. I'm not trying to get on here to mooch off others. I'm not trying to have poor forum etiquette. I just figured that maybe this could be easy for somebody that could help. Therefore, I thank you for your time and effort in attempting to get this 1 alert right for me. I'll keep searching. (Sorry for the bold font, I do not know why it won't "unbold", sorry for the repost and sorry for the stupid questions
 
Last edited by a moderator:
@mc01439
Thanks again. I've tested this with /NQ tonighADING]t and it isn't working :( . I've switch the code around and tried other code after reading the "Thinkscript Learning Center" with no luck. I've been trying to get this one thing right for a month and figured I'd find a group and ask folks that know more than me -because I'm obviously not a coder. I am pleased that I've found somebody that could offer some help as I posted the same question 6 hours ago and didn't get an answer - Thus the reason why I posted again. I'm not trying to get on here to mooch off others. I'm not trying to have poor forum etiquette. I just figured that maybe this could be easy for somebody that could help. Therefore, I thank you for your time and effort in attempting to get this 1 alert right for me. I'll keep searching. (Sorry for the bold font, I do not know why it won't "unbold", sorry for the repost and sorry for the stupid questions
Sorry my mistake. I tested with the corrections I made, it works now. Just change the "input numDev" to the number you want.

http://tos.mx/jDKQojo
 
Last edited by a moderator:
@mohsinm How is Finviz calculating their RVOL? Do you have their formula?
I would like to share what I have found and heard. I know a few folks from Finviz thru my old graduate school classmate (math department.) I asked him about the correct formula of RVOL and showed him different versions here plus a few others that I got from the internet.

He explained that he could not tell me the exact formula due to "intellectual property policy", but he told me that they and other competitors such as Trade Ideas build their RVOL codes as described in the following article:

https://stockbeep.com/how-to-calculate-relative-volume-rvol-for-intraday-trading

The correct formula is:
Current cumulative volume up to this time of day / Average cumulative volume up to this time of day

Though my friend refused to show me the lines of codes that Finviz uses to calculate the correct RVOL, he politely pointed out that our various versions here are not 100% correct.

Many fellow traders have contributed a lot of time and efforts to share their codes here. I hope to post the working version soon and contribute too.
 
I would like to share what I have found and heard. I know a few folks from Finviz thru my old graduate school classmate (math department.) I asked him about the correct formula of RVOL and showed him different versions here plus a few others that I got from the internet.

He explained that he could not tell me the exact formula due to "intellectual property policy", but he told me that they and other competitors such as Trade Ideas build their RVOL codes as described in the following article:

https://stockbeep.com/how-to-calculate-relative-volume-rvol-for-intraday-trading

The correct formula is:
Current cumulative volume up to this time of day / Average cumulative volume up to this time of day

Though my friend refused to show me the lines of codes that Finviz uses to calculate the correct RVOL, he politely pointed out that our various versions here are not 100% correct.

Many fellow traders have contributed a lot of time and efforts to share their codes here. I hope to post the working version soon and contribute too.

How rvol is supposed to be calculated is well known to some of us but I guess it's good you got confirmation for others. There's code already in this thread that has the right intent in how to calculate rvol but it's buggy. I posted comments on how to fix it recently. I'll post my code which is specifically for a watchlist column and you guys can modify for other purposes.

Whoever posted the original code had concerns about it dragging down overall TOS performance which is why I made it handle multiple timeframes. The lower the timeframe the more the performance impact. Though, I'm not sure I ever ran it below 5m so I'm not sure if the concern is warranted. The only real benefit of using a low timeframe is that the data is meaningless until the first period closes and a small period will close earlier. After that it matters less on each subsequent period. Though, you also don't want to set this higher than needed because it compares current volume to the average volume at the start of the period. If you set to 1H then at 11:15 it's comparing current volume to the average at 10:30. Better to narrow that window. After I switched to swing trading I changed mine to 10m. Before that I was using 5m.

This data is meaningless in pre-market. Having accurate pre-market rvol on TOS isn't possible because TOS doesn't have data for periods with no volume and it skews trying to look at the same time of day on previous days. Don't use Extended Hours with this code.

RVOL Watchlist Column Don't use Extended Hours with this code.
Ruby:
input greenLevel = 1.5;

def period = GetAggregationPeriod();
def minutesPerBar = period / 60000;
def minutesPerDay = 60 * 6.5; # 6.5 hours of standard trading session
def bpd = minutesPerDay / minutesPerBar; # bars per day

# This is the cumulative volume for the current day
def day = GetDay();
def cumVolume =
  if day != day[1] then volume
  else cumVolume[1] + volume
;

# average of cumulative volume at this time of day for the last 10 trading days
def avgCumVolume = (cumVolume[(bpd*1)] + cumVolume[(bpd*2)] + cumVolume[(bpd*3)] + cumVolume[(bpd*4)] + cumVolume[(bpd*5)] + cumVolume[(bpd*6)] + cumVolume[(bpd*7)] + cumVolume[(bpd*8)] + cumVolume[(bpd*9)] + cumVolume[(bpd*10)]) / 10;

plot RVol = Round(if IsNaN(cumVolume) then 0 else cumVolume / avgCumVolume, 2);
RVol.AssignValueColor(if RVol >= 1 and RVol < greenLevel then Color.YELLOW else if RVol >= greenLevel then Color.LIGHT_GREEN else Color.PINK);
 
Hi all,

I frequently use Relative Volume StDev as an integral part of my trading strategy. Instead of adding the entire lower indicator, I created a simple script that adds an upper bar to my chart:

Si0pXZm.png


Code:
# RelativeVolumeStDev_Bar
# Author: gravityflyer
# v1.0 - 2021.04.18

declare upper ;
input length = 60;
input numDev = 2.0;
input allowNegativeValues = no;

plot labelColor=double.nan;
labelColor.setHiding(1);
labelColor.hideTitle();
labELColor.defineColor("Unchanged", color.GRAY);
LabelColor.DEFIneColor("Rising", color.UPTICK);

def bar = (volume - Average(volume, length)) / StDev(volume, length);
AddLabel(1, Concat(Concat(Concat("RelVol(", length), "):"), bar),
  if bar > 0 then
    labelColor.color("Rising")
  else
    labelColor.color("Unchanged")
);

I figured I'd share in case someone else finds it helpful! :)
 
May i ask how you use it for your trading strategy?
Personally, I use it as additional confirmation with my other indicators and avoid fake-outs.

That said, I believe there are a lot of different ways in which traders use relative volume more generally!
 
This entire thread went from Tomsk simple, very nice, clean column/Watchlist to complicated.... unbelievable.
 
This entire thread went from Tomsk simple, very nice, clean column/Watchlist to complicated.... unbelievable.

Tomsk's post doesn't calculate "RVOL" in the common way it is calculated on other platforms, making it inaccurate intraday relative to those platforms. That strategy for calculating a relative value for volume isn't wrong. It was just sort of a misnomer within the context of other platforms.

And varied visual representations give everyone choices to match to their preferences. Since when is that a bad thing?
 

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
538 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