Average Daily Range Indicator for ThinkorSwim

I have the below script, but i dont know the functions to scan for stocks that have exceeded the low/high

input lenght = 5;
def dayHigh = DailyHighLow(AggregationPeriod.DAY).Dailyhigh;
def dayLow = DailyHighLow(AggregationPeriod.DAY).DailyLow;
def dayrange = dayHigh - dayLow;
def AvgRange = average(DayRange, lenght);
 
Last edited by a moderator:

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

@wussay The script in post#36 might be worth looking at. Otherwise, there are several other flavors of daily range in this thread that you can play with and modify to your needs.
 
Last edited:
Hi @Joshua I would like to create a scanner that can alert me to tickers that are within X% of the line).
It would alert when tickers are within X percentage of the upper and lower line plot (that is calculated as per my description above (line plot represents 2X the previous day range) with the goal being to get alerted ahead of a potential cross above the upper / cross below the lower.

I came across the work you have done on this thread and thought I would ask if you could take a look at something that I am working on. I have a chart setup with a Daily 3 period SMA and Daily 3 period EMA, both of which show on intraday charts. I also have a previous day high and low plot.

What I would appreciate help with is: I would like to plot two lines on the current day's chart that are the equivalent to 1X the previous day's range (above and below). The result would be the Previous Day High and Low plotted as you see on the chart, one line plotted above equal to the full previous day range and the same below.

I am including a link to the chart as it is currently setup (btw, if you are able to stop the previous day high / low lines from plotting all the way back in time (they should plot on the previous and current day only) that would be cool!
Screenshot (27).png

http://tos.mx/AgaGkeJ

I really appreciate your help. Thank you.
 
Last edited by a moderator:
This is how its shaping up so far, the orange area is where the alerts/scans would trigger, they are adjustable by input by percentage of the size of the range. In this particular case, it is set at ten percent. Is this correct? Let me know, I've got some time, just baby sitting this slow grind breakout on the S&P... ZzzZzz

O8F5b5x.png
 
This is how its shaping up so far, the orange area is where the alerts/scans would trigger, they are adjustable by input by percentage of the size of the range. In this particular case, it is set at ten percent. Is this correct? Let me know, I've got some time, just baby sitting this slow grind breakout on the S&P... ZzzZzz

O8F5b5x.png
You're the man! Looks perfect.

I can see the upper and lower plot line that is twice the previous day range, the actual previous day range (shaded box) and the alert zones that can be user defined by adjusting the percentage so that, using your screenshot as an example, an alert would be triggered when the price is within 10% of hitting the upper plot. Looks great! I really appreciate this Joshua.

Nice grind on the S&P. Better to be grinding up!
 
@DMacTrades This is the indicator, with optional alerts, etc. Though, I have yet to test it in a live market environment. @ me if you have any issues.
Ruby:
input AlertBuffer = 10;
input EnableAlerts = Yes;
def prev_high; def prev_low;
def cur_day = GetLastDay() == GetDay();
def prev_day =
    GetLastDay() - GetDay() == 1
    and SecondsFromTime(0930) >= 0
    and SecondsTillTime(1600) >= 0
;
if prev_day and !prev_day[1] {
    prev_high = high;
    prev_low = low;
} else if prev_day{
    prev_high =
        if high > prev_high[1]
        then high
        else prev_high[1]
    ;
    prev_low =
        if low < prev_low[1]
        then low
        else prev_low[1]
    ;
} else {
    prev_high = prev_high[1];
    prev_low = prev_low[1];
}
def prev_range = prev_high - prev_low;
def double_high = prev_high + prev_range;
def double_low = prev_low - prev_range;
def buffer_size = prev_range * (AlertBuffer * 0.01);
def high_buffer = if cur_day then double_high -  buffer_size else double.nan;
def low_buffer = if cur_day then double_low + buffer_size else double.nan;
plot DoubleHigh = if cur_day then double_high else double.nan;
plot DoubleLow = if cur_day then double_low else Double.NaN;
plot PrevLow = if cur_day then prev_low else double.nan;
plot PrevHigh = if cur_day then prev_high else double.nan;
PrevLow.setDefaultColor(color.cyan);
PrevHigh.setDefaultColor(color.cyan);
DoubleHigh.setDefaultColor(color.cyan);
DoubleLow.setDefaultColor(color.cyan);
addcloud(PrevHigh,PrevLow,color.Light_Green);
addCloud(low_buffer,double_low,color.light_orange);
addCloud(double_high,high_buffer,color.light_orange);
def alert_high_armed = Between(close,high_buffer,double_high);
def alert_low_armed = Between(close,double_low,low_buffer);
alert(
    EnableAlerts and alert_high_armed and !alert_high_armed[1],
    "Near Double High",
    Alert.TICK,
    Sound.Ding
);
alert(
    EnableAlerts and alert_low_armed and !alert_low_armed[1],
    "Near Double Low",
    Alert.TICK,
    Sound.Ding
);

This is the same thing, purely for scanning.
Ruby:
input AlertBuffer = 10;
def prev_high; def prev_low;
def cur_day = GetLastDay() == GetDay();
def prev_day =
    GetLastDay() - GetDay() == 1
    and SecondsFromTime(0930) >= 0
    and SecondsTillTime(1600) >= 0
;
if prev_day and !prev_day[1] {
    prev_high = high;
    prev_low = low;
} else if prev_day{
    prev_high =
        if high > prev_high[1]
        then high
        else prev_high[1]
    ;
    prev_low =
        if low < prev_low[1]
        then low
        else prev_low[1]
    ;
} else {
    prev_high = prev_high[1];
    prev_low = prev_low[1];
}
def prev_range = prev_high - prev_low;
def double_high = prev_high + prev_range;
def double_low = prev_low - prev_range;
def buffer_size = prev_range * (AlertBuffer * 0.01);
def high_buffer = if cur_day then double_high -  buffer_size else double.nan;
def low_buffer = if cur_day then double_low + buffer_size else double.nan;
def DoubleHigh = if cur_day then double_high else double.nan;
def DoubleLow = if cur_day then double_low else Double.NaN;
def PrevLow = if cur_day then prev_low else double.nan;
def PrevHigh = if cur_day then prev_high else double.nan;
plot at_high = Between(close,high_buffer,double_high);
plot at_low = Between(close,double_low,low_buffer);
plot at_either = Between(close,high_buffer,double_high)
    or Between(close,double_low,low_buffer);
 
@DMacTrades This is the indicator, with optional alerts, etc. Though, I have yet to test it in a live market environment. @ me if you have any issues.


This is the same thing, purely for scanning.
Hi Joshua. I hope that your weekend is going well. First off, a huge thank you for your help. What you did is great and is a huge help. We are going to do live testing this week on actual trades as we fine tune the strategy, and I will make sure to reach out with the results / the detailed plan.

While reviewing tickers today using what you created I had the thought to add a buffer zone & corresponding alerts to the PrevHigh and PrevLow levels, and I was able to do that using your work as a guide. The only other thing that I did was set the alerts to .ONCE as they were firing with each tick.

Re the scanner code, I have set up the scanners, however will need to see them in action with live data starting tomorrow. I'll update you on that as well.

Here is your code with what I added as detailed above in case anyone else is interested. Thanks again and speak soon!
Ruby:
# ToS ThinkScript Double High / Double Low Indicator by @Joshua August 28 2021

input AlertBuffer = 10;
input EnableAlerts = Yes;
def prev_high;
def prev_low;
def cur_day = GetLastDay() == GetDay();
def prev_day =
GetLastDay() - GetDay() == 1
and SecondsFromTime(0930) >= 0
and SecondsTillTime(1600) >= 0
;
if prev_day and !prev_day[1] {
prev_high = high;
prev_low = low;
} else if prev_day {
prev_high =
if high > prev_high[1]
then high
else prev_high[1]
;
prev_low =
if low < prev_low[1]
then low
else prev_low[1]
;
} else {
prev_high = prev_high[1];
prev_low = prev_low[1];
}
def prev_range = prev_high - prev_low;
def double_high = prev_high + prev_range;
def double_low = prev_low - prev_range;
def buffer_size = prev_range * (AlertBuffer * 0.01);
def double_high_buffer = if cur_day then double_high - buffer_size else Double.NaN;
def double_low_buffer = if cur_day then double_low + buffer_size else Double.NaN;
def high_buffer = if cur_day then prev_high - buffer_size else Double.NaN;
def low_buffer = if cur_day then prev_low + buffer_size else Double.NaN;
plot DoubleHigh = if cur_day then double_high else Double.NaN;
plot DoubleLow = if cur_day then double_low else Double.NaN;
plot PrevLow = if cur_day then prev_low else Double.NaN;
plot PrevHigh = if cur_day then prev_high else Double.NaN;
PrevLow.SetDefaultColor(Color.CYAN);
PrevHigh.SetDefaultColor(Color.CYAN);
DoubleHigh.SetDefaultColor(Color.CYAN);
DoubleLow.SetDefaultColor(Color.CYAN);
AddCloud(PrevHigh, PrevLow, Color.LIGHT_GREEN);
AddCloud(double_low_buffer, double_low, Color.LIGHT_ORANGE);
AddCloud(double_high, double_high_buffer, Color.LIGHT_ORANGE);
AddCloud(PrevHigh, high_buffer, Color.LIGHT_ORANGE);
AddCloud(low_buffer, PrevLow, Color.LIGHT_ORANGE);
def alert_double_high_armed = Between(close, double_high_buffer, double_high);
def alert_double_low_armed = Between(close, double_low, double_low_buffer);
def alert_high_armed = Between(close,high_buffer,high);
def alert_low_armed = Between(close,low_buffer,low);
alert(
EnableAlerts and alert_double_high_armed and !alert_double_high_armed[1],
"Near Double High",
Alert.ONCE,
Sound.Ding
);
alert(
EnableAlerts and alert_double_low_armed and !alert_double_low_armed[1],
"Near Double Low",
Alert.ONCE,
Sound.Ding
);
alert(
EnableAlerts and alert_high_armed and !alert_high_armed[1],
"Near High",
Alert.ONCE,
Sound.Ding
);
alert(
EnableAlerts and alert_low_armed and !alert_low_armed[1],
"Near Low",
Alert.ONCE,
Sound.Ding
);
 
Last edited by a moderator:
Oh that's right, I was testing on inactive data. I'll update a few lines at some point, I would like for it to be able to fire more than once, but only if it actually leaves the zone and then enters the zone again on a totally independent occurrence. Its doable.
 
Oh that's right, I was testing on inactive data. I'll update a few lines at some point, I would like for it to be able to fire more than once, but only if it actually leaves the zone and then enters the zone again on a totally independent occurrence. Its doable.
That would be good. I like that idea.

Also, I am seeing that it isn't working on the chart this morning (Monday). I have tested it in OnDemand and it works all days except Mondays. This must have to do with the weekend, but I'm not sure how to adjust it. Thoughts?
 
That would be good. I like that idea.

Also, I am seeing that it isn't working on the chart this morning (Monday). I have tested it in OnDemand and it works all days except Mondays. This must have to do with the weekend, but I'm not sure how to adjust it. Thoughts?
I see what the issue with Mondays... the value between GetLastDay and GetDay, on Mondays, is 3, whereas every other day it is 1. A manual edit each Monday morning for the following line fixes. Just need to remember to make the change on Tuesday morning. :)

Tuesday through Friday
def prev_day = GetLastDay() - GetDay() == 1

Mondays:
def prev_day = GetLastDay() - GetDay() == 3

If you have a method of making it less manual, let me know. But not a big deal to make the change.
 
Yeah there is a much better way of doing it, not using those day functions at all actually. How important is it for it to show up premarket? I wasn't sure if that was intentional in your original example, or if you just didn't know how to do it otherwise. Now would be a good time to clear that up.
 
Yeah there is a much better way of doing it, not using those day functions at all actually. How important is it for it to show up premarket? I wasn't sure if that was intentional in your original example, or if you just didn't know how to do it otherwise. Now would be a good time to clear that up.
Hi Joshua. Pre-market is important as there is more and more liquidity before the bell and a lot of breaks of these levels that we are creating the indicators for happen then.

If manually changing the # of days is how it has to be then it isn't the end of the world. I am thinking that the scanners will have to be adjusted manually as well on Mondays (and then back on Tuesdays), correct?
 
Try this, it should take care of the weekend transitions and the alerts.

Ruby:
input AlertBuffer = 10;
input EnableAlerts = Yes;
def isOpen = GetTime() >= RegularTradingStart(GetYYYYMMDD())
         and GetTime() <= RegularTradingEnd(GetYYYYMMDD());
def cur_day = GetDay() == GetLastDay();
def cHigh; def prev_high;
def cLow; def prev_low;
if GetDay() != GetDay()[1] {
    prev_high = chigh[1];
    prev_low = cLow[1];
    cHigh = cHigh[1];
    cLow = cLow[1];
} else if IsOpen and !IsOpen[1] {
    cHigh = High;
    cLow = Low;
    prev_high = chigh[1];
    prev_low = cLow[1];
} else if IsOpen{
    cHigh = Max(high,cHigh[1]);
    prev_high = prev_high[1];
    cLow = Min(low,cLow[1]);
    prev_low = prev_low[1];
} else {
    cHigh = cHigh[1];
    prev_high = prev_high[1];
    cLow = cLow[1];
    prev_low = prev_low[1];
}
def prev_range = prev_high - prev_low;
def double_high = prev_high + prev_range;
def double_low = prev_low - prev_range;
def buffer_size = prev_range * (AlertBuffer * 0.01);
def high_buffer = if cur_day  then double_high -  buffer_size else double.nan;
def low_buffer = if cur_day  then double_low + buffer_size else double.nan;
plot DoubleHigh = if cur_day then double_high else double.nan;
plot DoubleLow = if cur_day then double_low else Double.NaN;
plot PrevLow = if cur_day then prev_low else double.nan;
plot PrevHigh = if cur_day then prev_high else double.nan;
PrevLow.setDefaultColor(color.cyan);
PrevHigh.setDefaultColor(color.cyan);
DoubleHigh.setDefaultColor(color.cyan);
DoubleLow.setDefaultColor(color.cyan);
addcloud(PrevHigh,PrevLow,color.Light_Green);
addCloud(low_buffer,double_low,color.light_orange);
addCloud(double_high,high_buffer,color.light_orange);
def alert_high_armed = High[1] < high_buffer
    and Between(close,high_buffer,double_high);
def alert_low_armed = Low[1] > low_buffer
    and Between(close,double_low,low_buffer);
alert(
    EnableAlerts and alert_high_armed,
    "Near Double High",
    Alert.BAR,
    Sound.Ding
);
alert(
    EnableAlerts and alert_low_armed,
    "Near Double Low",
    Alert.BAR,
    Sound.Ding
);
 
Try this, it should take care of the weekend transitions and the alerts.
Joshua... I don't know what part of the world you are in but should our paths ever cross dinner is on me. Working perfectly. Thank you so much. And, as I mentioned, we will be testing a specific setup around what you have helped with and I will make sure to reach out and share our findings with you as soon as we have meaningful data. Speak soon and have a great evening.
 
Has anyone tried this in a watch list for an ADR crossover indicator. Watchlist cell would be green is above top ADR or red is below lower ADR for example? I’m looking for something like this..
 
I have this code I am trying to covert to TOS. I been studying the codes in TOS to see how to recode it from Pinescript. I have the code from Pinescript and the one I have done so far in TOS. Looking for some advise as I got as far as I can learned.

This code shows the difference between the high and low of each candle over a given time and plots it like a stochastic study but with one line.
Pinescript Code:
Ruby:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ceyhun

//@version=4

study(title="ADR - Average Day Range", overlay=false)
Length = input(14, title="length")

dhigh = security(syminfo.tickerid, 'D', high)
dlow = security(syminfo.tickerid, 'D', low)

ADR = sma(dhigh, Length) - sma(dlow, Length)
plot(ADR, color=color.red,title="ADR",linewidth=2)

My Code that I have attempted.
Ruby:
# ADR AVERAGE DAILY RANGE

declare lower;

input length = 14;
input Dhigh = high;
input Dlow = low;
input ADR = (Dhigh,length) - (Dlow,length);

plot ADR;

ADR.SetDefaultColor(getcolor);
 
Last edited by a moderator:
Try this, it should take care of the weekend transitions and the alerts.
Joshua,
I am interested in this scan, I tried pasting into custom scan filter in the thinkscript editor. I received a "Exactly one plot expected" I am sure I am making a simple mistake. Any ideas?

Joshua... I don't know what part of the world you are in but should our paths ever cross dinner is on me. Working perfectly. Thank you so much. And, as I mentioned, we will be testing a specific setup around what you have helped with and I will make sure to reach out and share our findings with you as soon as we have meaningful data. Speak soon and have a great evening.
Hi DMac Trades, are you using this ADR scan? I tried installing and I received an error "Exactly 1 plot expected" any ideas? I installed under scan custom study on TOS. Do you have any ideas?
 
Last edited by a moderator:
Save it as a study, and then select it from the menu in the bottom right of this image:

AAmVjgZ.png


Then it will give you a list of plots you can work with below that, and you won't receive the error.

It should give you something like StudyName().PlotName, and from there you can code around it.

Close < StudyName().DoubleLow for example.

But otherwise, this code was never intended to be a scan, iirc, its been a while since I wrote it.
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

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