Calculate sum of formula values based on multiple aggregations and display this sum as label on daily chart?

L

lmk99

Member
VIP
Hi all,

I have an indicator on the daily chart that sums various conditions, based on various study results, into a "score" of how bullish the stock is.

I want to keep using the "DAY" aggregation period for displaying this score as a label on the daily chart.

However, I also want to sum the score that is calculated for various intraday aggregation periods - 1 hour, 5 minute, and 15 minute - and then display this sum as an additional, second label on the daily chart.

(For example, if the score for the day period is 10, the chart label says: "Day Score: 10" and if the scores on the 1 hour, 5 minute, and 15 minute charts are 9, 3, and 11 then I want a second label to say "Intraday Score: 23.")

The script for the scoring is too long to just copy/paste duplicates of the entire script for each intraday aggregation period defined individually (it will produce an error in TOS saying the the script is too complex). So is there some shortcut method to calculate each of the four aggregation periods (i.e. without modifying each section of code into a different duplicate section that only differs from the others in the aggregation period used)?

For example, one component of the total score is a volume trend calculation. If the condition of the bullish volume trend is met, this makes the total score increase by two using a counter variable like this:

Code:
def VolTrndCounter = if VolTrndScan then 2 else 0;

Without duplicating the entire code for the VolTrndScan component individually, i.e. for each aggregation period that I want summed, to get a combined intraday score using the three time frames, is it possible to add three lines of code like this?

Code:
def VolTrndCounter5min = if VolTrndScan(use.aggregation.period.5MIN) then 2 else 0;
def VolTrndCounter15min = if VolTrndScan(use.aggregation.period.15MIN) then 2 else 0;
def VolTrndCounter1hour = if VolTrndScan(use.aggregation.period.1HOUR) then 2 else 0;

The syntax is totally made up in the above example, it's just meant to show the kind of solution that I'm looking for: a simple way to make the code for the entire VolTrndScan calculation just use a different aggregation period than the default that is inherited from the current chart time frame (which in this case is 1D since I want this "Intraday Score" summed and displayed on the 1D chart).

Is this making sense? Is there a solution?
 
Last edited:
BenTen

BenTen

Administrative
Staff
VIP
As far as I know, you can only display data from a higher timeframe onto a lower timeframe and not the other way around. I'm not sure if this restriction would affect what you're trying to do.
 
L

lmk99

Member
VIP
Thanks, that's helpful to know! I played around with what appears to be the relevant parameter:

Code:
def agg5min = AggregationPeriod.FIVE_MIN;
def VolTrndCounter5min = VolTrndCounter(period = agg5min);

That doesn't work, it results in an "incompatible parameter" error. So the "period = X" parameter seems to only work for some things, like LAST, CLOSE, etc. I also tried this on the 5min chart instead of the 1D chart, since you said using data of lower time frames on the chart of a higher time frame could be a confounding problem:

Code:
def agg15min = AggregationPeriod.FIFTEEN_MIN;
def VolTrnd5min = VolTrnd(period = agg15min);

However, I get the same error: "incompatible parameter."

Is there a relatively efficient way to make use of variable time frames for the code of each "score" study? To make it more clear, this is the code on the 5min chart for the "VolTrnd" score calculation (plus the counter variable at the end that makes it increase the total bullishness score displayed on a chart label):

Code:
#VolTrnd Filter

# UNUSUALVOLUME
# DREWGRIFFITH15 (C) 2014

input UVprice = volume;
#input percentdecr = 20;
input percentincr = 120;
input UVlength = 10;
def UVavg = average(UVprice, UVlength)[1];
def UVchg1 = 100 * (UVprice/UVavg -1);
def UVchg2 = 100 * (UVprice[1]/UVavg -1);
def VolTrndScan =  (UVchg1 >= percentincr) or  (UVchg2 >= percentincr);

def VolTrndCounter = if VolTrndScan then 2 else 0;

If I wanted to make a "VolTrndScan" for three different time frames - the default of 5min and also two others which are 1hour and 15min, then what would be the most efficient way to do that in the above code that is being used on the 5min chart?
 
Last edited:
L

lmk99

Member
VIP
PS: I found this explanation of coding multiple time frames into an indicator (from https://futures.io/thinkorswim/42974-plotting-agg-variables.html#post654796):

To plot variable timeframes, you have to adjust the coding as follows....

first, add adjustable TF....
then, adjust "close" to show that TF....
any coding that goes into the adjustable TF has to be fixed as well.... So, for Span A, you have to correct the Tenkan and Kijun coding....

Code:
input Period1 = aggregationPeriod.DAY;
input Period2 = aggregationPeriod.WEEK;

def Period1_Tenkan = (Highest(high(Period = Period1), tenkan_period) + Lowest(low(Period = Period1), tenkan_period)) / 2;
def Period1_Kijun = (Highest(high(Period = Period1), kijun_period) + Lowest(low(Period = Period1), kijun_period)) / 2;
plot Period1_SpanA = (Period1_Tenkan[kijun_period] + Period1_Kijun[kijun_period]) / 2;

def Period2_Tenkan = (Highest(high(Period = Period2), tenkan_period) + Lowest(low(Period = Period2), tenkan_period)) / 2;
def Period2_Kijun = (Highest(high(Period = Period2), kijun_period) + Lowest(low(Period = Period2), kijun_period)) / 2;
plot Period2_SpanA = (Period2_Tenkan[kijun_period] + Period2_Kijun[kijun_period]) / 2;

Now, the Kijun and Tenkan are looking for highs and lows from your input value, which is day and week.
Then, your different SPAN A's are using the adjusted TF values accordingly.

So in the example code section from my scoring indicator that I showed in my previous post, the VolTrnd study, I guess it would be done like something like this but none of these work:

Code:
#VolTrnd Filter

# UNUSUALVOLUME
# DREWGRIFFITH15 (C) 2014

input Period1 = aggregationPeriod.FIVE_MIN;
input Period2 = aggregationPeriod.FIFTEEN_MIN;
input Period3 = aggregationPeriod.HOUR;

input UVprice = volume(period = Period1);  ###doesn't work, gives an error
#input percentdecr = 20;
input percentincr = 120;
input UVlength = 10;
def UVavg = average(UVprice(period = Period1), UVlength)[1];  ###doesn't work, gives an error
def UVchg1 = 100 * (UVprice/UVavg -1);
def UVchg2 = 100 * (UVprice[1]/UVavg -1);
def VolTrndScan =  (UVchg1 >= percentincr) or  (UVchg2 >= percentincr);

def VolTrndCounter = if VolTrndScan then 2 else 0;

It seems there is no easy way to just include multiple time frames in the same study. It also seems that there is no such thing as global variables. For example, if I could just define each "VolTrndCounter" score as a different global value and then make a separate script that added them together from where they're calculated on the other charts, that would be the most obvious, intuitive way to do it (since that is what I'm doing manually when I eyeball the charts that are open on my screen) but from my understanding it's not possible for one study instance running in one chart to know about what happens in another study instance running on another chart.
 
R

RickAns

Member
VIP
Interesting, please let us know if you get this sorted out.
 
Welkin

Welkin

Active member
VIP
PS: I found this explanation of coding multiple time frames into an indicator (from https://futures.io/thinkorswim/42974-plotting-agg-variables.html#post654796):



So in the example code section from my scoring indicator that I showed in my previous post, the VolTrnd study, I guess it would be done like something like this but none of these work:

Code:
#VolTrnd Filter

# UNUSUALVOLUME
# DREWGRIFFITH15 (C) 2014

input Period1 = aggregationPeriod.FIVE_MIN;
input Period2 = aggregationPeriod.FIFTEEN_MIN;
input Period3 = aggregationPeriod.HOUR;

input UVprice = volume(period = Period1);  ###doesn't work, gives an error
#input percentdecr = 20;
input percentincr = 120;
input UVlength = 10;
def UVavg = average(UVprice(period = Period1), UVlength)[1];  ###doesn't work, gives an error
def UVchg1 = 100 * (UVprice/UVavg -1);
def UVchg2 = 100 * (UVprice[1]/UVavg -1);
def VolTrndScan =  (UVchg1 >= percentincr) or  (UVchg2 >= percentincr);

def VolTrndCounter = if VolTrndScan then 2 else 0;

It seems there is no easy way to just include multiple time frames in the same study. It also seems that there is no such thing as global variables. For example, if I could just define each "VolTrndCounter" score as a different global value and then make a separate script that added them together from where they're calculated on the other charts, that would be the most obvious, intuitive way to do it (since that is what I'm doing manually when I eyeball the charts that are open on my screen) but from my understanding it's not possible for one study instance running in one chart to know about what happens in another study instance running on another chart.
UVprice must be set as a def variable not an input if you are introducing multiple aggregations
Code:
def UVprice = volume(period = Period1);
once set all instances of UVprice will use volume with the aggregation set for Period1, so removing (period = Period1) from UVprice in the UVavg line will get rid of the error. Only certain fundamental functions(open, high, low, close, volume, tick_count, hl2, hlc3, ohlc4, etc...) can be assigned periods
Code:
def UVavg = average(UVprice, UVlength)[1];
 
L

lmk99

Member
VIP
@Welkin Thanks so much for your reply. I'm a big fan of your work such as the tick based volume projection lower study. It's helpful to know that inputs can't be used and I need to use a def variable in MTF studies!

Regarding that "only certain fundamental functions can be assigned periods," it also occurs to me that when making a custom quote appear in a watch list column, it seems to not be possible to make the study that is being generated in the custom quote run using a period other than day which is the default.

So if I apply my bullishness scoring script as a chart label on a 15min chart, for example, the score for that aggregation period will be different than for other periods. And I can use the Stock Hacker drop-down to likewise select an intraday period when I use the scoring script as a scanner (e.g. 15min bullishness score is a period to use for finding breakouts). But when I replicate the script into a custom quote that appears in a watchlist column, it defaults to using the day period, and so it doesn't seem there is any way to use it as a custom quote but be able to easily toggle the period as I am able to do in the Stock Hacker interface.

I guess that it may be possible to code multiple aggregations to be fully functional, but some of the code that I've grafted from various places would be difficult to rewrite. If there's an easy way to make the watchlist column use an intraday period like it's easy to do so for the stock hacker that would be nice but if not easily doable, it's actually good enough for me to be able to save an intraday scan version of this: setting that as a watchlist lets me know that I'm getting the intraday score range that I want, on whatever time frame was selected in the Stock Hacker interface. As for the idea of summing several intraday scores into an aggregate super-score, I've just rearranged my layout so that it's easier for me to eyeball the sum of the intraday scores that are displayed as labels across the intraday charts I use.
 
Welkin

Welkin

Active member
VIP
@Welkin Thanks so much for your reply. I'm a big fan of your work such as the tick based volume projection lower study. It's helpful to know that inputs can't be used and I need to use a def variable in MTF studies!

Regarding that "only certain fundamental functions can be assigned periods," it also occurs to me that when making a custom quote appear in a watch list column, it seems to not be possible to make the study that is being generated in the custom quote run using a period other than day which is the default.

So if I apply my bullishness scoring script as a chart label on a 15min chart, for example, the score for that aggregation period will be different than for other periods. And I can use the Stock Hacker drop-down to likewise select an intraday period when I use the scoring script as a scanner (e.g. 15min bullishness score is a period to use for finding breakouts). But when I replicate the script into a custom quote that appears in a watchlist column, it defaults to using the day period, and so it doesn't seem there is any way to use it as a custom quote but be able to easily toggle the period as I am able to do in the Stock Hacker interface.

I guess that it may be possible to code multiple aggregations to be fully functional, but some of the code that I've grafted from various places would be difficult to rewrite. If there's an easy way to make the watchlist column use an intraday period like it's easy to do so for the stock hacker that would be nice but if not easily doable, it's actually good enough for me to be able to save an intraday scan version of this: setting that as a watchlist lets me know that I'm getting the intraday score range that I want, on whatever time frame was selected in the Stock Hacker interface. As for the idea of summing several intraday scores into an aggregate super-score, I've just rearranged my layout so that it's easier for me to eyeball the sum of the intraday scores that are displayed as labels across the intraday charts I use.
Appreciate the kind words!

You can use different periods for custom quotes, you just can't assign different periods inside the script. When you go to edit the custom quote formula you will see the button for changing the aggregation period next to where you edit the column name. Just add your custom quote column multiple times and set a different period for each individual column.

for the scan have you considered combining multiple scans into one with the 'scan in'/'intersect with' options in the stock hacker? you can combine multiple scans this way and have the 'mother scan' linked to a watchlist.

as for the aggregate super-score you are referring to, that can all be combined onto a single chart or lower study, as long as you are trying to pull the data from higher time frames onto a lower one. It won't work the other way around(lower to higher).
 
L

lmk99

Member
VIP
You can use different periods for custom quotes, you just can't assign different periods inside the script. When you go to edit the custom quote formula you will see the button for changing the aggregation period next to where you edit the column name. Just add your custom quote column multiple times and set a different period for each individual column.

This was hugely helpful! I caught some good momentum today thanks to doing this.

for the scan have you considered combining multiple scans into one with the 'scan in'/'intersect with' options in the stock hacker? you can combine multiple scans this way and have the 'mother scan' linked to a watchlist.

It's a great suggestion. I worry that the scanner results in a watchlist are already so slow / delayed (when not manually pressing the "scan" button; but even pressing scan, there is still the wait time for the script to execute) - like maybe one minute or more behind real time - that nesting multiple scans might make the results lag even further behind. Nonetheless I'm interested to try it, thank you!
 
D

dinodotcom

Member
2019 Donor
@lmk99 , Did you ever resolve your quest to make this happen? I to am looking to do such an indicator. Please let me know!
 
L

lmk99

Member
VIP
@lmk99 , Did you ever resolve your quest to make this happen? I to am looking to do such an indicator. Please let me know!
I think it's impossible because of the limitation Welkin mentioned that "Only certain fundamental functions(open, high, low, close, volume, tick_count, hl2, hlc3, ohlc4, etc...) can be assigned periods". Well, it might be possible but it would require rewriting every one of the studies that I used as sub-components to aggregate my "score" into a version that accepts period modifiers and in my case I think it might make the script too complex for TOS to execute in real-time (it gives an error message in such cases when trying to save scripts that won't run fast enough for real-time use). I ended up using a flexible grid layout with a row of cells above my scalping chart that each contain nothing except the label showing the score for each intraday period and so I'm just eyeballing them as a group instead of trying to code an aggregate score that sums scores from multiple time frames.
 

Similar threads

Top