Intraday Volume Tracking and Forecasting (VTF) for ThinkorSwim

mashume

Expert
VIP
Lifetime

Introduction

Forecasting volume is notoriously tricky business. To try to tame the wilderness of volume analysis, I humbly present a script for comparing intraday volume to recent volumes and projecting a forecast for volume through the day.

Other studies show, often in labels, volume by time t as a percentage of an average volume for the day. A problem I see is that volume does not accumulate in a linear manner through the trading day, and visualizing above and below average volume days is not easy.

This script is a work derived in part from an indicator I found on the internet. I cannot lay claim to having originated the average volume by time method. Hopefully the original author will be pleased to see old work resurface and with a twist.

The Indicator

The indicator is, at it's essence three plots. One is the running total of the average volume by time over the last n days. This is dependant on those days being open in the current timeframe -- it will not pull data not on your plot. I should note that, because of the copious number of lines of code, this may not represent true averages over multiple days if your timeframe is really small. I like this indicator on 30 and 15 minute charts.

The second plot is the running sum of today's volume. A cloud is drawn to indicate the relative volume today with the average volume. It defaults to cyan if the current volume is above average and pink if it is below. This shows in real time how today's volume accumulation compares to an average and gives a really clear view of unusual intraday volume activity.

The third plot is the most interesting mathematically, and the most open to tweaking. It attempts to project an average volume curve through the remainder of the trading day based on the relative volume of the first hour of trading. The starting time may be adjusted, as can the end of the calculation period. Of note is that it does not wait for the opening period to end before calculation and so there WILL BE REPAINT of the forecast line until the ratio is fixed for the day (whenever you have it set to be fixed).

Please reference the screen shots below.

The Future

I sat down to code this using a sum of least squares curve fitting for the data in the first hour and settled on a simple ratio. There are clearly improvements that can be made. I offer this up to the UseThinkScript community both in appreciation of the hard work you all put in and in hope of finding some input to make this a more useful tool.

Have fun with it!
-mashume

Link to Study

https://tos.mx/GrYtT3j
Be aware that some values are still hard coded in this and the opening time is set to 0400 because I like to see pre-market volume as an indication of the day. If you don't have show extended hours turned on it may not behave well for you with these settings.

Eye Candy

LBCEycm.png

TTNP. Black line is actual accumulated volume, Blue dashed line is average volume over last days, and gold line is volume forecast. The line really did come close to being an accurate forecast. It was plotted all the way to the right from the start of the day.

CzsCCUx.png

Novabay. Interesting here is that while volume started below average, it picked up (the cyan cloud) with a price spike, but when volume fell below the average again price levels were not maintainable. While your eye may tell you this, the volume trend between 8:30 and 10:30 looks bullish, but examining the red/blue cloud, we see a volume falloff preceding the price drop at about 9:45.

CODE

For your hacking enjoyment.
Code:
#
# Intraday Volume Tracking and Forecasting
#
# VFT
#
# Author: Seth Urion (Mashume)
# Version: 2020-06-27
# Initial Public
#
# This code is licensed (as applicable) under the GPL v3
#
# ----------------------


declare lower;
def na = Double.NaN;

rec barcounter = if GetDay() != GetDay()[1] then 1 else barcounter[1] + 1;

rec daycount = if BarNumber() == 1 then 0 else if GetDay() > GetDay()[1] then 1 else 0;

def istoday = if GetLastDay() == GetDay() then 1 else 0;

def bar1volume = if istoday then 0 else if barcounter == 1 then volume else 0;
def bar2volume = if istoday then 0 else if barcounter == 2 then volume else 0;
def bar3volume = if istoday then 0 else if barcounter == 3 then volume else 0;
def bar4volume = if istoday then 0 else if barcounter == 4 then volume else 0;
def bar5volume = if istoday then 0 else if barcounter == 5 then volume else 0;
def bar6volume = if istoday then 0 else if barcounter == 6 then volume else 0;
def bar7volume = if istoday then 0 else if barcounter == 7 then volume else 0;
def bar8volume = if istoday then 0 else if barcounter == 8 then volume else 0;
def bar9volume = if istoday then 0 else if barcounter == 9 then volume else 0;
def bar10volume = if istoday then 0 else if barcounter == 10 then volume else 0;
def bar11volume = if istoday then 0 else if barcounter == 11 then volume else 0;
def bar12volume = if istoday then 0 else if barcounter == 12 then volume else 0;
def bar13volume = if istoday then 0 else if barcounter == 13 then volume else 0;
def bar14volume = if istoday then 0 else if barcounter == 14 then volume else 0;
def bar15volume = if istoday then 0 else if barcounter == 15 then volume else 0;
def bar16volume = if istoday then 0 else if barcounter == 16 then volume else 0;
def bar17volume = if istoday then 0 else if barcounter == 17 then volume else 0;
def bar18volume = if istoday then 0 else if barcounter == 18 then volume else 0;
def bar19volume = if istoday then 0 else if barcounter == 19 then volume else 0;
def bar20volume = if istoday then 0 else if barcounter == 20 then volume else 0;
def bar21volume = if istoday then 0 else if barcounter == 21 then volume else 0;
def bar22volume = if istoday then 0 else if barcounter == 22 then volume else 0;
def bar23volume = if istoday then 0 else if barcounter == 23 then volume else 0;
def bar24volume = if istoday then 0 else if barcounter == 24 then volume else 0;
def bar25volume = if istoday then 0 else if barcounter == 25 then volume else 0;
def bar26volume = if istoday then 0 else if barcounter == 26 then volume else 0;
def bar27volume = if istoday then 0 else if barcounter == 27 then volume else 0;
def bar28volume = if istoday then 0 else if barcounter == 28 then volume else 0;
def bar29volume = if istoday then 0 else if barcounter == 29 then volume else 0;
def bar30volume = if istoday then 0 else if barcounter == 30 then volume else 0;
def bar31volume = if istoday then 0 else if barcounter == 31 then volume else 0;
def bar32volume = if istoday then 0 else if barcounter == 32 then volume else 0;
def bar33volume = if istoday then 0 else if barcounter == 33 then volume else 0;
def bar34volume = if istoday then 0 else if barcounter == 34 then volume else 0;
def bar35volume = if istoday then 0 else if barcounter == 35 then volume else 0;
def bar36volume = if istoday then 0 else if barcounter == 36 then volume else 0;
def bar37volume = if istoday then 0 else if barcounter == 37 then volume else 0;
def bar38volume = if istoday then 0 else if barcounter == 38 then volume else 0;
def bar39volume = if istoday then 0 else if barcounter == 39 then volume else 0;
def bar40volume = if istoday then 0 else if barcounter == 40 then volume else 0;
def bar41volume = if istoday then 0 else if barcounter == 41 then volume else 0;
def bar42volume = if istoday then 0 else if barcounter == 42 then volume else 0;
def bar43volume = if istoday then 0 else if barcounter == 43 then volume else 0;
def bar44volume = if istoday then 0 else if barcounter == 44 then volume else 0;
def bar45volume = if istoday then 0 else if barcounter == 45 then volume else 0;
def bar46volume = if istoday then 0 else if barcounter == 46 then volume else 0;
def bar47volume = if istoday then 0 else if barcounter == 47 then volume else 0;
def bar48volume = if istoday then 0 else if barcounter == 48 then volume else 0;
def bar49volume = if istoday then 0 else if barcounter == 49 then volume else 0;
def bar50volume = if istoday then 0 else if barcounter == 50 then volume else 0;
def bar51volume = if istoday then 0 else if barcounter == 51 then volume else 0;
def bar52volume = if istoday then 0 else if barcounter == 52 then volume else 0;
def bar53volume = if istoday then 0 else if barcounter == 53 then volume else 0;
def bar54volume = if istoday then 0 else if barcounter == 54 then volume else 0;
def bar55volume = if istoday then 0 else if barcounter == 55 then volume else 0;
def bar56volume = if istoday then 0 else if barcounter == 56 then volume else 0;
def bar57volume = if istoday then 0 else if barcounter == 57 then volume else 0;
def bar58volume = if istoday then 0 else if barcounter == 58 then volume else 0;
def bar59volume = if istoday then 0 else if barcounter == 59 then volume else 0;
def bar60volume = if istoday then 0 else if barcounter == 60 then volume else 0;
def bar61volume = if istoday then 0 else if barcounter == 61 then volume else 0;
def bar62volume = if istoday then 0 else if barcounter == 62 then volume else 0;
def bar63volume = if istoday then 0 else if barcounter == 63 then volume else 0;
def bar64volume = if istoday then 0 else if barcounter == 64 then volume else 0;
def bar65volume = if istoday then 0 else if barcounter == 65 then volume else 0;
def bar66volume = if istoday then 0 else if barcounter == 66 then volume else 0;
def bar67volume = if istoday then 0 else if barcounter == 67 then volume else 0;
def bar68volume = if istoday then 0 else if barcounter == 68 then volume else 0;
def bar69volume = if istoday then 0 else if barcounter == 69 then volume else 0;
def bar70volume = if istoday then 0 else if barcounter == 70 then volume else 0;
def bar71volume = if istoday then 0 else if barcounter == 71 then volume else 0;
def bar72volume = if istoday then 0 else if barcounter == 72 then volume else 0;
def bar73volume = if istoday then 0 else if barcounter == 73 then volume else 0;
def bar74volume = if istoday then 0 else if barcounter == 74 then volume else 0;
def bar75volume = if istoday then 0 else if barcounter == 75 then volume else 0;
def bar76volume = if istoday then 0 else if barcounter == 76 then volume else 0;
def bar77volume = if istoday then 0 else if barcounter == 77 then volume else 0;
def bar78volume = if istoday then 0 else if barcounter == 78 then volume else 0;
def bar79volume = if istoday then 0 else if barcounter == 79 then volume else 0;
def bar80volume = if istoday then 0 else if barcounter == 80 then volume else 0;
def bar81volume = if istoday then 0 else if barcounter == 81 then volume else 0;

def avgbar1 = TotalSum(bar1volume) / TotalSum(daycount);
def avgbar2 = TotalSum(bar2volume) / TotalSum(daycount);
def avgbar3 = TotalSum(bar3volume) / TotalSum(daycount);
def avgbar4 = TotalSum(bar4volume) / TotalSum(daycount);
def avgbar5 = TotalSum(bar5volume) / TotalSum(daycount);
def avgbar6 = TotalSum(bar6volume) / TotalSum(daycount);
def avgbar7 = TotalSum(bar7volume) / TotalSum(daycount);
def avgbar8 = TotalSum(bar8volume) / TotalSum(daycount);
def avgbar9 = TotalSum(bar9volume) / TotalSum(daycount);
def avgbar10 = TotalSum(bar10volume) / TotalSum(daycount);
def avgbar11 = TotalSum(bar11volume) / TotalSum(daycount);
def avgbar12 = TotalSum(bar12volume) / TotalSum(daycount);
def avgbar13 = TotalSum(bar13volume) / TotalSum(daycount);
def avgbar14 = TotalSum(bar14volume) / TotalSum(daycount);
def avgbar15 = TotalSum(bar15volume) / TotalSum(daycount);
def avgbar16 = TotalSum(bar16volume) / TotalSum(daycount);
def avgbar17 = TotalSum(bar17volume) / TotalSum(daycount);
def avgbar18 = TotalSum(bar18volume) / TotalSum(daycount);
def avgbar19 = TotalSum(bar19volume) / TotalSum(daycount);
def avgbar20 = TotalSum(bar20volume) / TotalSum(daycount);
def avgbar21 = TotalSum(bar21volume) / TotalSum(daycount);
def avgbar22 = TotalSum(bar22volume) / TotalSum(daycount);
def avgbar23 = TotalSum(bar23volume) / TotalSum(daycount);
def avgbar24 = TotalSum(bar24volume) / TotalSum(daycount);
def avgbar25 = TotalSum(bar25volume) / TotalSum(daycount);
def avgbar26 = TotalSum(bar26volume) / TotalSum(daycount);
def avgbar27 = TotalSum(bar27volume) / TotalSum(daycount);
def avgbar28 = TotalSum(bar28volume) / TotalSum(daycount);
def avgbar29 = TotalSum(bar29volume) / TotalSum(daycount);
def avgbar30 = TotalSum(bar30volume) / TotalSum(daycount);
def avgbar31 = TotalSum(bar31volume) / TotalSum(daycount);
def avgbar32 = TotalSum(bar32volume) / TotalSum(daycount);
def avgbar33 = TotalSum(bar33volume) / TotalSum(daycount);
def avgbar34 = TotalSum(bar34volume) / TotalSum(daycount);
def avgbar35 = TotalSum(bar35volume) / TotalSum(daycount);
def avgbar36 = TotalSum(bar36volume) / TotalSum(daycount);
def avgbar37 = TotalSum(bar37volume) / TotalSum(daycount);
def avgbar38 = TotalSum(bar38volume) / TotalSum(daycount);
def avgbar39 = TotalSum(bar39volume) / TotalSum(daycount);
def avgbar40 = TotalSum(bar40volume) / TotalSum(daycount);
def avgbar41 = TotalSum(bar41volume) / TotalSum(daycount);
def avgbar42 = TotalSum(bar42volume) / TotalSum(daycount);
def avgbar43 = TotalSum(bar43volume) / TotalSum(daycount);
def avgbar44 = TotalSum(bar44volume) / TotalSum(daycount);
def avgbar45 = TotalSum(bar45volume) / TotalSum(daycount);
def avgbar46 = TotalSum(bar46volume) / TotalSum(daycount);
def avgbar47 = TotalSum(bar47volume) / TotalSum(daycount);
def avgbar48 = TotalSum(bar48volume) / TotalSum(daycount);
def avgbar49 = TotalSum(bar49volume) / TotalSum(daycount);
def avgbar50 = TotalSum(bar50volume) / TotalSum(daycount);
def avgbar51 = TotalSum(bar51volume) / TotalSum(daycount);
def avgbar52 = TotalSum(bar52volume) / TotalSum(daycount);
def avgbar53 = TotalSum(bar53volume) / TotalSum(daycount);
def avgbar54 = TotalSum(bar54volume) / TotalSum(daycount);
def avgbar55 = TotalSum(bar55volume) / TotalSum(daycount);
def avgbar56 = TotalSum(bar56volume) / TotalSum(daycount);
def avgbar57 = TotalSum(bar57volume) / TotalSum(daycount);
def avgbar58 = TotalSum(bar58volume) / TotalSum(daycount);
def avgbar59 = TotalSum(bar59volume) / TotalSum(daycount);
def avgbar60 = TotalSum(bar60volume) / TotalSum(daycount);
def avgbar61 = TotalSum(bar61volume) / TotalSum(daycount);
def avgbar62 = TotalSum(bar62volume) / TotalSum(daycount);
def avgbar63 = TotalSum(bar63volume) / TotalSum(daycount);
def avgbar64 = TotalSum(bar64volume) / TotalSum(daycount);
def avgbar65 = TotalSum(bar65volume) / TotalSum(daycount);
def avgbar66 = TotalSum(bar66volume) / TotalSum(daycount);
def avgbar67 = TotalSum(bar67volume) / TotalSum(daycount);
def avgbar68 = TotalSum(bar68volume) / TotalSum(daycount);
def avgbar69 = TotalSum(bar69volume) / TotalSum(daycount);
def avgbar70 = TotalSum(bar70volume) / TotalSum(daycount);
def avgbar71 = TotalSum(bar71volume) / TotalSum(daycount);
def avgbar72 = TotalSum(bar72volume) / TotalSum(daycount);
def avgbar73 = TotalSum(bar73volume) / TotalSum(daycount);
def avgbar74 = TotalSum(bar74volume) / TotalSum(daycount);
def avgbar75 = TotalSum(bar75volume) / TotalSum(daycount);
def avgbar76 = TotalSum(bar76volume) / TotalSum(daycount);
def avgbar77 = TotalSum(bar77volume) / TotalSum(daycount);
def avgbar78 = TotalSum(bar78volume) / TotalSum(daycount);
def avgbar79 = TotalSum(bar79volume) / TotalSum(daycount);
def avgbar80 = TotalSum(bar80volume) / TotalSum(daycount);
def avgbar81 = TotalSum(bar81volume) / TotalSum(daycount);





plot AvgVol = if GetDay() != GetLastDay() then na
else if barcounter == 1 then avgbar1
else if barcounter == 2 then avgbar2
else if barcounter == 3 then avgbar3
else if barcounter == 4 then avgbar4
else if barcounter == 5 then avgbar5
else if barcounter == 6 then avgbar6
else if barcounter == 7 then avgbar7
else if barcounter == 8 then avgbar8
else if barcounter == 9 then avgbar9
else if barcounter == 10 then avgbar10
else if barcounter == 11 then avgbar11
else if barcounter == 12 then avgbar12
else if barcounter == 13 then avgbar13
else if barcounter == 14 then avgbar14
else if barcounter == 15 then avgbar15
else if barcounter == 16 then avgbar16
else if barcounter == 17 then avgbar17
else if barcounter == 18 then avgbar18
else if barcounter == 19 then avgbar19
else if barcounter == 20 then avgbar20
else if barcounter == 21 then avgbar21
else if barcounter == 22 then avgbar22
else if barcounter == 23 then avgbar23
else if barcounter == 24 then avgbar24
else if barcounter == 25 then avgbar25
else if barcounter == 26 then avgbar26
else if barcounter == 27 then avgbar27
else if barcounter == 28 then avgbar28
else if barcounter == 29 then avgbar29
else if barcounter == 30 then avgbar30
else if barcounter == 31 then avgbar31
else if barcounter == 32 then avgbar32
else if barcounter == 33 then avgbar33
else if barcounter == 34 then avgbar34
else if barcounter == 35 then avgbar35
else if barcounter == 36 then avgbar36
else if barcounter == 37 then avgbar37
else if barcounter == 38 then avgbar38
else if barcounter == 39 then avgbar39
else if barcounter == 40 then avgbar40
else if barcounter == 41 then avgbar41
else if barcounter == 42 then avgbar42
else if barcounter == 43 then avgbar43
else if barcounter == 44 then avgbar44
else if barcounter == 45 then avgbar45
else if barcounter == 46 then avgbar46
else if barcounter == 47 then avgbar47
else if barcounter == 48 then avgbar48
else if barcounter == 49 then avgbar49
else if barcounter == 50 then avgbar50
else if barcounter == 51 then avgbar51
else if barcounter == 52 then avgbar52
else if barcounter == 53 then avgbar53
else if barcounter == 54 then avgbar54
else if barcounter == 55 then avgbar55
else if barcounter == 56 then avgbar56
else if barcounter == 57 then avgbar57
else if barcounter == 58 then avgbar58
else if barcounter == 59 then avgbar59
else if barcounter == 60 then avgbar60
else if barcounter == 61 then avgbar61
else if barcounter == 62 then avgbar62
else if barcounter == 63 then avgbar63
else if barcounter == 64 then avgbar64
else if barcounter == 65 then avgbar65
else if barcounter == 66 then avgbar66
else if barcounter == 67 then avgbar67
else if barcounter == 68 then avgbar68
else if barcounter == 69 then avgbar69
else if barcounter == 70 then avgbar70
else if barcounter == 71 then avgbar71
else if barcounter == 72 then avgbar72
else if barcounter == 73 then avgbar73
else if barcounter == 74 then avgbar74
else if barcounter == 75 then avgbar75
else if barcounter == 76 then avgbar76
else if barcounter == 77 then avgbar77
else if barcounter == 78 then avgbar78
else if barcounter == 79 then avgbar79
else if barcounter == 80 then avgbar80
else if barcounter == 81 then avgbar81
else na;

AvgVol.SetDefaultColor(Color.DARK_GRAY);
AvgVol.SetLineWeight(1);
def zero = 0;


def vol = volume;

def avg_vol = SimpleMovingAvg(vol, 8);

input OpenBell  = 0400.0;
input CloseBell  = 1605.0;


def RTH = if SecondsTillTime(CloseBell) > 0 and
                    SecondsFromTime(OpenBell) >= 0
                 then 1
                 else 0;

def cum_vol = if RTH ==  0 then 0 else cum_vol[1] + VOLUME;
plot day_volume = cum_vol;


def AvgVolSum =  if GetDay() == GetLastDay() then AvgVolSum[1] + AvgVol else 0;;
plot AVS = if AvgVolSum != 0 then AvgVolSum else double.nan;
addCloud(AVS, Day_Volume, color.pink, color.cyan, no);

def OpenHour = 1030.0;
def FirstHour = if SecondsTillTime(OpenHour) > 0 and
                    SecondsFromTime(OpenBell) >= 0
                 then 1
                 else 0;

def FirstHourRatio = if GetDay() == GetLastDay()

    and FirstHour == 1
    then
        cum_vol / AvgVolSum
    else
        FirstHourRatio[1]
    ;
addVerticalLine(if GetDay() == GetLastDay() and FirstHour == 0 and FirstHour[1] == 1 then yes else no, "First Hour Ratio Set", color = Color.BLUE);
addLabel(yes, concat("Ratio: ", FirstHourRatio), color.blue);

def VolumeProjection = if GetDay() != GetLastDay() then na
else if barcounter == 1  then avgbar1 * FirstHourRatio
else if barcounter == 2  then  VolumeProjection[1] + ( avgbar2 * FirstHourRatio)
else if barcounter == 3  then  VolumeProjection[1] + ( avgbar3 * FirstHourRatio)
else if barcounter == 4  then  VolumeProjection[1] + ( avgbar4 * FirstHourRatio)
else if barcounter == 5  then  VolumeProjection[1] + ( avgbar5 * FirstHourRatio)
else if barcounter == 6  then  VolumeProjection[1] + ( avgbar6 * FirstHourRatio)
else if barcounter == 7  then  VolumeProjection[1] + ( avgbar7 * FirstHourRatio)
else if barcounter == 8  then  VolumeProjection[1] + ( avgbar8 * FirstHourRatio)
else if barcounter == 9  then  VolumeProjection[1] + ( avgbar9 * FirstHourRatio)
else if barcounter == 10 then  VolumeProjection[1] +  (avgbar10 * FirstHourRatio)
else if barcounter == 11 then  VolumeProjection[1] +  (avgbar11 * FirstHourRatio)
else if barcounter == 12 then  VolumeProjection[1] +  (avgbar12 * FirstHourRatio)
else if barcounter == 13 then  VolumeProjection[1] +  (avgbar13 * FirstHourRatio)
else if barcounter == 14 then  VolumeProjection[1] +  (avgbar14 * FirstHourRatio)
else if barcounter == 15 then  VolumeProjection[1] +  (avgbar15 * FirstHourRatio)
else if barcounter == 16 then  VolumeProjection[1] +  (avgbar16 * FirstHourRatio)
else if barcounter == 17 then  VolumeProjection[1] +  (avgbar17 * FirstHourRatio)
else if barcounter == 18 then  VolumeProjection[1] +  (avgbar18 * FirstHourRatio)
else if barcounter == 19 then  VolumeProjection[1] +  (avgbar19 * FirstHourRatio)
else if barcounter == 20 then  VolumeProjection[1] +  (avgbar20 * FirstHourRatio)
else if barcounter == 21 then  VolumeProjection[1] +  (avgbar21 * FirstHourRatio)
else if barcounter == 22 then  VolumeProjection[1] +  (avgbar22 * FirstHourRatio)
else if barcounter == 23 then  VolumeProjection[1] +  (avgbar23 * FirstHourRatio)
else if barcounter == 24 then  VolumeProjection[1] +  (avgbar24 * FirstHourRatio)
else if barcounter == 25 then  VolumeProjection[1] +  (avgbar25 * FirstHourRatio)
else if barcounter == 26 then  VolumeProjection[1] +  (avgbar26 * FirstHourRatio)
else if barcounter == 27 then  VolumeProjection[1] +  (avgbar27 * FirstHourRatio)
else if barcounter == 28 then  VolumeProjection[1] +  (avgbar28 * FirstHourRatio)
else if barcounter == 29 then  VolumeProjection[1] +  (avgbar29 * FirstHourRatio)
else if barcounter == 30 then  VolumeProjection[1] +  (avgbar30 * FirstHourRatio)
else if barcounter == 31 then  VolumeProjection[1] +  (avgbar31 * FirstHourRatio)
else if barcounter == 32 then  VolumeProjection[1] +  (avgbar32 * FirstHourRatio)
else if barcounter == 33 then  VolumeProjection[1] +  (avgbar33 * FirstHourRatio)
else if barcounter == 34 then  VolumeProjection[1] +  (avgbar34 * FirstHourRatio)
else if barcounter == 35 then  VolumeProjection[1] +  (avgbar35 * FirstHourRatio)
else if barcounter == 36 then  VolumeProjection[1] +  (avgbar36 * FirstHourRatio)
else if barcounter == 37 then  VolumeProjection[1] +  (avgbar37 * FirstHourRatio)
else if barcounter == 38 then  VolumeProjection[1] +  (avgbar38 * FirstHourRatio)
else if barcounter == 39 then  VolumeProjection[1] +  (avgbar39 * FirstHourRatio)
else if barcounter == 40 then  VolumeProjection[1] +  (avgbar40 * FirstHourRatio)
else if barcounter == 41 then  VolumeProjection[1] +  (avgbar41 * FirstHourRatio)
else if barcounter == 42 then  VolumeProjection[1] +  (avgbar42 * FirstHourRatio)
else if barcounter == 43 then  VolumeProjection[1] +  (avgbar43 * FirstHourRatio)
else if barcounter == 44 then  VolumeProjection[1] +  (avgbar44 * FirstHourRatio)
else if barcounter == 45 then  VolumeProjection[1] +  (avgbar45 * FirstHourRatio)
else if barcounter == 46 then  VolumeProjection[1] +  (avgbar46 * FirstHourRatio)
else if barcounter == 47 then  VolumeProjection[1] +  (avgbar47 * FirstHourRatio)
else if barcounter == 48 then  VolumeProjection[1] +  (avgbar48 * FirstHourRatio)
else if barcounter == 49 then  VolumeProjection[1] +  (avgbar49 * FirstHourRatio)
else if barcounter == 50 then  VolumeProjection[1] +  (avgbar50 * FirstHourRatio)
else if barcounter == 51 then  VolumeProjection[1] +  (avgbar51 * FirstHourRatio)
else if barcounter == 52 then  VolumeProjection[1] +  (avgbar52 * FirstHourRatio)
else if barcounter == 53 then  VolumeProjection[1] +  (avgbar53 * FirstHourRatio)
else if barcounter == 54 then  VolumeProjection[1] +  (avgbar54 * FirstHourRatio)
else if barcounter == 55 then  VolumeProjection[1] +  (avgbar55 * FirstHourRatio)
else if barcounter == 56 then  VolumeProjection[1] +  (avgbar56 * FirstHourRatio)
else if barcounter == 57 then  VolumeProjection[1] +  (avgbar57 * FirstHourRatio)
else if barcounter == 58 then  VolumeProjection[1] +  (avgbar58 * FirstHourRatio)
else if barcounter == 59 then  VolumeProjection[1] +  (avgbar59 * FirstHourRatio)
else if barcounter == 60 then  VolumeProjection[1] +  (avgbar60 * FirstHourRatio)
else if barcounter == 61 then  VolumeProjection[1] +  (avgbar61 * FirstHourRatio)
else if barcounter == 62 then  VolumeProjection[1] +  (avgbar62 * FirstHourRatio)
else if barcounter == 63 then  VolumeProjection[1] +  (avgbar63 * FirstHourRatio)
else if barcounter == 64 then  VolumeProjection[1] +  (avgbar64 * FirstHourRatio)
else if barcounter == 65 then  VolumeProjection[1] +  (avgbar65 * FirstHourRatio)
else if barcounter == 66 then  VolumeProjection[1] +  (avgbar66 * FirstHourRatio)
else if barcounter == 67 then  VolumeProjection[1] +  (avgbar67 * FirstHourRatio)
else if barcounter == 68 then  VolumeProjection[1] +  (avgbar68 * FirstHourRatio)
else if barcounter == 69 then  VolumeProjection[1] +  (avgbar69 * FirstHourRatio)
else if barcounter == 70 then  VolumeProjection[1] +  (avgbar70 * FirstHourRatio)
else if barcounter == 71 then  VolumeProjection[1] +  (avgbar71 * FirstHourRatio)
else if barcounter == 72 then  VolumeProjection[1] +  (avgbar72 * FirstHourRatio)
else if barcounter == 73 then  VolumeProjection[1] +  (avgbar73 * FirstHourRatio)
else if barcounter == 74 then  VolumeProjection[1] +  (avgbar74 * FirstHourRatio)
else if barcounter == 75 then  VolumeProjection[1] +  (avgbar75 * FirstHourRatio)
else if barcounter == 76 then  VolumeProjection[1] +  (avgbar76 * FirstHourRatio)
else if barcounter == 77 then  VolumeProjection[1] +  (avgbar77 * FirstHourRatio)
else if barcounter == 78 then  VolumeProjection[1] +  (avgbar78 * FirstHourRatio)
else if barcounter == 79 then  VolumeProjection[1] +  (avgbar79 * FirstHourRatio)
else if barcounter == 80 then  VolumeProjection[1] +  (avgbar80 * FirstHourRatio)
else if barcounter == 81 then  VolumeProjection[1] +  (avgbar81 * FirstHourRatio)
else na;

plot VP = volumeProjection;

All typoes are myne.
 
Last edited:

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

Hi @mashume , very cool study. I've been looking for visual ways to compare current volume to previous/avg volume and this looks great. The way the indicator is coded right now -if I use a 10 min 2 day chart- will the "AVS" plot the data average from the previous 2 days only? "the running total of the average volume by time over the last n days" with the "n" being 2 days as determined by my chart time frame setting?

Also, I normally run 5 min charts for the regular stock market period (9:30AM - 4PM EST) which should be 78 time bars total. I see the code accounts for 81 bars so it seems like a 5 min chart should plot fine (with a 0930-1600 open to closing bell setting) but the plot seems to stop short midway. I attached a pic comparing the 2-Day 10 min to 5 min charts. Also, on the 5 min, even though I have the opening bell set for 0930, it seems the chart is starting the "AVS plot" @ around 0750. Thanks

BG0Bwnt.jpg
 
@Corpus,
I'll take a look and see what gives. Thanks for the feedback on this one. It's highly experimental at this early stage. Glad you're finding some use for it. Thanks for the screenshots to show what you're seeing.
-mashume
 
@Corpus,

The AVS plot can be made to respect the OpeningBell variable by changing the definition as follows:
Code:
def AvgVolSum =  if GetDay() == GetLastDay()
    and RTH == 1
    then AvgVolSum[1] + AvgVol else 0;
where the second line is added to the conditions.

I haven't been able to recreate the plot stopping short yet.

hope this helps

-mashume
 
@mashume any updated versions of this? I think this has amazing potential and just want to make sure I'm using the best version.

I'm having some issues with it working

Essentially all I want from it is a end of day volume prediction that I can use on some daily volume strategies to get in earlier, instead of waiting for eod I can use the projected. It's fine with me if the indicator uses up until 11:30 to predict the eod volume.
 
Last edited by a moderator:
@mashume any updated versions of this? I think this has amazing potential and just want to make sure I'm using the best version.

I'm having some issues with it working

Essentially all I want from it is a end of day volume prediction that I can use on some daily volume strategies to get in earlier, instead of waiting for eod I can use the projected. It's fine with me if the indicator uses up until 11:30 to predict the eod volume.

Can you be more specific about what's not working... time frames (days x periods), behaviour, and expected behaviour?

It may be possible to tweak the calculation of average volume to get an eod value by finding the average cumulative volume for a day (not hard), the multiplier (already calculated as a ratio at a given time) and multiplying the two. You may not even need to go through adding up all the values over the day.

May look into it if I have a few spare minutes.

-mashume
 
Hello @mashume

May i ask how you use the Concavity Z Score study?
It tells me how decisively the HMA is turning. Following the Z-Score tends to keep me away from the alternating cycles of false-turn around that can happen simply following HMA turning points.

If you want the statistics of it, any good page on z-scores (Wikipedia). It's good to understand at least something of any [mathematical] mechanism you use to make financial decisions :cool:

YMMV

-mashume
 
@mashume Do you mind posting that code for zScore concavity? The link does not work.

I just copied and pasted the Hull script and inputted zscore in place of price into a lower study but wanted to cross check against yours. Thanks!
 
@mashume Do you mind posting that code for zScore concavity? The link does not work.

I just copied and pasted the Hull script and inputted zscore in place of price into a lower study but wanted to cross check against yours. Thanks!
Here ya go...

Code:
declare lower;

input price = HL2;
input HMA_Length = 55;
input lookback = 2;

input stddev_len = 21;
input zlength = 13;
input threshold = 1.5;

def HMA = HullMovingAvg(price = price, length = HMA_Length);

def delta = HMA[1] - HMA[lookback + 1];
def delta_per_bar = delta / lookback;

def next_bar = HMA[1] + delta_per_bar;

def divergence = (HMA - next_bar) * 5000;
# divergence.setDefaultColor(color.red);

def concavity = if HMA > next_bar then 1 else -1;


#zscore @codydog

def min = Lowest(divergence, zlength);
def max = Highest(divergence, zlength);
plot Zscore = ( (divergence - Average(divergence, zlength)) / StDev(divergence, zlength));
ZScore.setdefaultColor(color.black);

plot turning_point =
        if concavity[1] != concavity
        and AbsValue(zscore) > threshold
        and absValue(ZScore) > AbsValue(ZScore[2])
        then Zscore else double.nan;
turning_point.SetStyle(CURVE.POINTS);
turning_point.SetDefaultColor(COLOR.BLACK);
turning_point.setLineWeight(3);


plot zero = 0;
zero.SetDefaultColor(COLOR.PLUM);

plot one = threshold;
one.SetDefaultColor(color = Color.PLUM);
one.SetStyle(Curve.short_DASH);
plot minusone = -threshold;
minusone.SetDefaultColor(color = Color.PLUM);
minusone.SetStyle(Curve.short_DASH);

addcloud(zscore, one, color.violet, color.white);
addCloud(zscore, minusone, color.white, color.plum);
 
Can you be more specific about what's not working... time frames (days x periods), behaviour, and expected behaviour?

It may be possible to tweak the calculation of average volume to get an eod value by finding the average cumulative volume for a day (not hard), the multiplier (already calculated as a ratio at a given time) and multiplying the two. You may not even need to go through adding up all the values over the day.

May look into it if I have a few spare minutes.

-mashume
You described it spot on, I just want a rough prediction of closing volume. All I want to do, which I think you described is get the volume total at 10:30 (for example) and then multiply it by a determined ratio to get a good idea of where volume where end up. I wouldn't know how to do this but I think a good formula for this would be , (average volume from 9:30 - 10:30/ average total volume) * current days volume from 9:30 - 10:30.

I would attempt it myself but I always run into a ton of issues when working with time and you seem to do it a lot effortlessly. If you do this I'll look at the code and see how you accomplished it to try and learn something.
 
Sorry to muddy the waters here, but i wonder if one needs to consider the impact of the surge in options trading that Covid has created as lots of folks stay home and enjoy gambling with options? Options skew has shifted (which many have noticed and talked about)

Problem for me is that tos throttles data when you try to calculate gamma across a wide number of strikes and expirations, so, to me, you cant really get a realistic idea of trading volumes intraday.

If anyone knows how to plot both underlying volumes and cumulative options volumes intraday, please say something! I'll add that dark pool data isnt really available until late so, its murky to me how to do this
 
You described it spot on, I just want a rough prediction of closing volume. All I want to do, which I think you described is get the volume total at 10:30 (for example) and then multiply it by a determined ratio to get a good idea of where volume where end up. I wouldn't know how to do this but I think a good formula for this would be , (average volume from 9:30 - 10:30/ average total volume) * current days volume from 9:30 - 10:30.

I would attempt it myself but I always run into a ton of issues when working with time and you seem to do it a lot effortlessly. If you do this I'll look at the code and see how you accomplished it to try and learn something.
You can add these to the end of the previous study:
Code:
def eod = if secondsTillTime(1600) < 1 then volumeProjection else if secondsFromTime(1600) > 0 then volumeProjection[1] else double.nan;

addLabel(yes, concat("Projected: ", round(eod, 0)), color.dark_orange);

I whipped this up after market close today so I haven't seen it run intraday yet.

Let me know what it does and doesn't does. ;-)

You can always make the lower study an upper study and turn off the plots and leave the Labels boxes.

-mashume
 
Nope. That didn't work.

Maybe this is closer:
Code:
def last_five_d_vol = (
GetValue(data = VOLUME(period = AggregationPeriod.DAY), "dynamic offset" = 1) +
GetValue(data = VOLUME(period = AggregationPeriod.DAY), "dynamic offset" = 2) +
GetValue(data = VOLUME(period = AggregationPeriod.DAY), "dynamic offset" = 3) +
GetValue(data = VOLUME(period = AggregationPeriod.DAY), "dynamic offset" = 4) +
GetValue(data = VOLUME(period = AggregationPeriod.DAY), "dynamic offset" = 5)) / 5;

def eod = last_five_d_vol * FirstHourRatio;

addLabel(yes, concat("Projected: ", round(eod, 0)), color.dark_orange);
 
Last edited:

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
297 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