Highest high and lowest low within 2% over time

Smile

New member
Looking for a indicator for a scan that chooses those stocks whose highest high and lowest low is within a given percent of each other over a period of time.
 
Solution
Looking for a indicator for a scan that chooses those stocks whose highest high and lowest low is within a given percent of each other over a period of time.


EDIT 23-06-13

---------------

here is a lower study that should work as a scanner

Code:
#  hilo_within_wper_xmin_lower2

# https://usethinkscript.com/threads/highest-high-and-lowest-low-within-2-over-time.10068/
# Highest high and lowest low within 2% over time
#  Smile  Feb 9, 2022

# Looking for a indicator for
#  a scan that finds stocks,
#   highest high and lowest low is within a given percent of each other,
#    over a period of time.

declare lower;

def na = Double.NaN;
def bn = BarNumber();

input bars_back = 30;
def hi = Highest(high, bars_back);
def lo =...
Looking for a indicator for a scan that chooses those stocks whose highest high and lowest low is within a given percent of each other over a period of time.


EDIT 23-06-13

---------------

here is a lower study that should work as a scanner

Code:
#  hilo_within_wper_xmin_lower2

# https://usethinkscript.com/threads/highest-high-and-lowest-low-within-2-over-time.10068/
# Highest high and lowest low within 2% over time
#  Smile  Feb 9, 2022

# Looking for a indicator for
#  a scan that finds stocks,
#   highest high and lowest low is within a given percent of each other,
#    over a period of time.

declare lower;

def na = Double.NaN;
def bn = BarNumber();

input bars_back = 30;
def hi = Highest(high, bars_back);
def lo = Lowest(low, bars_back);

input max_percent = 2.0;
def per = Round(100 * (hi - lo) / lo, 2);

plot per_ok = (per < max_percent);
per_ok.SetDefaultColor(Color.CYAN);


#----------------------
# test data if used in a lower
input test_labels = no;
AddLabel(test_labels, "look back " + bars_back + " bars", Color.YELLOW);
AddLabel(test_labels, "highest " + hi, Color.YELLOW);
AddLabel(test_labels, "lowest " + lo, Color.YELLOW);
AddLabel(test_labels, "diff " + (hi - lo), Color.YELLOW);
AddLabel(test_labels, per + "%", ( if per_ok then Color.GREEN else Color.GRAY));
#

---------------

-----------------------------------

i think the lower study will work as a scan. the upper can be used to verify the data.

i don't scan, so i made 2 chart studies, to test my formulas, an upper and a lower.


both studies,
. ask for how many bars back to compare the highest and lowest, from the last bar.
. calculate the ratio of the range to the lowest. (highest - lowest)/lowest
. compare the ratio (percent) to a target percent(2).


the upper study,
. draws horizontal lines, at the highest and lowest prices, for x bars back from the last bar.
. has labels to display values. the % label turns green when the % is less than the target %.


the lower study,
. plots a line,
. = 1 if the hi-lo range % < target %
. = 0 if not
. draws a label, listing how many bars back.


Upper
Ruby:
#  hilo_within_wper_xmin
# upper study

def na= double.nan;
def bn = barnumber();
def lastbar = (!isnan(close[0]) and isnan(close[-1]));
input bars_back = 30;
def len = bars_back;
def len_rng = if (!isnan(close[0]) and isnan(close[-len])) then 1 else 0;

def hi = if bn == 1 then na
  else if lastbar[-(len-1)] then highest(high[-(len-1)], len+0)
  else if lastbar[1] then na
  else hi[1];

def lo = if bn == 1 then na
  else if lastbar[-(len-1)] then lowest(low[-(len-1)], len+0)
  else if lastbar[1] then na
  else lo[1];

input max_percent = 2.0;
def per = round(100 * (hi-lo)/lo, 2);
def per_ok = (per < max_percent);

addlabel(1, "look back " + len + " bars", color.yellow);
addlabel(1, "highest " + hi, color.yellow);
addlabel(1, "lowest " + lo, color.yellow);
addlabel(1, "diff " + (hi - lo), color.yellow);
addlabel(1, per + "%", ( if per_ok then color.green else color.gray));

plot hiz = hi;
plot loz = lo;
hiz.SetDefaultColor(Color.cyan);
loz.SetDefaultColor(Color.cyan);
#



Lower / scan
Ruby:
#  hilo_within_wper_xmin_lower
# lower study

declare lower;

def na= double.nan;
def bn = barnumber();
def lastbar = (!isnan(close[0]) and isnan(close[-1]));

input bars_back = 30;
def len = bars_back;
#def len_rng = if (!isnan(close[0]) and isnan(close[-len])) then 1 else 0;

def hi = if bn == 1 then na
  else if lastbar[-(len-1)] then highest(high[-(len-1)], len+0)
  else if lastbar[1] then na
  else hi[1];

def lo = if bn == 1 then na
  else if lastbar[-(len-1)] then lowest(low[-(len-1)], len+0)
  else if lastbar[1] then na
  else lo[1];

input max_percent = 2.0;
def per = round(100 * (hi-lo)/lo, 2);
def per_ok = (per < max_percent);

plot z = if bn == 1 then 0 else
 if !isnan(per_ok) then per_ok
else 0;


# may have to disable this label when used in a scan
addlabel(1, "look back " + len + " bars", color.yellow);
#

this shows the upper and lower chart studies. BK 5min 2/28/22
j8QZxaA.jpg
 
Last edited:
Solution
i think the lower study will work as a scan. the upper can be used to verify the data.

i don't scan, so i made 2 chart studies, to test my formulas, an upper and a lower.


both studies,
. ask for how many bars back to compare the highest and lowest, from the last bar.
. calculate the ratio of the range to the lowest. (highest - lowest)/lowest
. compare the ratio (percent) to a target percent(2).


the upper study,
. draws horizontal lines, at the highest and lowest prices, for x bars back from the last bar.
. has labels to display values. the % label turns green when the % is less than the target %.


the lower study,
. plots a line,
. = 1 if the hi-lo range % < target %
. = 0 if not
. draws a label, listing how many bars back.


Upper
Ruby:
#  hilo_within_wper_xmin
# upper study

def na= double.nan;
def bn = barnumber();
def lastbar = (!isnan(close[0]) and isnan(close[-1]));
input bars_back = 30;
def len = bars_back;
def len_rng = if (!isnan(close[0]) and isnan(close[-len])) then 1 else 0;

def hi = if bn == 1 then na
  else if lastbar[-(len-1)] then highest(high[-(len-1)], len+0)
  else if lastbar[1] then na
  else hi[1];

def lo = if bn == 1 then na
  else if lastbar[-(len-1)] then lowest(low[-(len-1)], len+0)
  else if lastbar[1] then na
  else lo[1];

input max_percent = 2.0;
def per = round(100 * (hi-lo)/lo, 2);
def per_ok = (per < max_percent);

addlabel(1, "look back " + len + " bars", color.yellow);
addlabel(1, "highest " + hi, color.yellow);
addlabel(1, "lowest " + lo, color.yellow);
addlabel(1, "diff " + (hi - lo), color.yellow);
addlabel(1, per + "%", ( if per_ok then color.green else color.gray));

plot hiz = hi;
plot loz = lo;
hiz.SetDefaultColor(Color.cyan);
loz.SetDefaultColor(Color.cyan);
#



Lower / scan
Ruby:
#  hilo_within_wper_xmin_lower
# lower study

declare lower;

def na= double.nan;
def bn = barnumber();
def lastbar = (!isnan(close[0]) and isnan(close[-1]));

input bars_back = 30;
def len = bars_back;
#def len_rng = if (!isnan(close[0]) and isnan(close[-len])) then 1 else 0;

def hi = if bn == 1 then na
  else if lastbar[-(len-1)] then highest(high[-(len-1)], len+0)
  else if lastbar[1] then na
  else hi[1];

def lo = if bn == 1 then na
  else if lastbar[-(len-1)] then lowest(low[-(len-1)], len+0)
  else if lastbar[1] then na
  else lo[1];

input max_percent = 2.0;
def per = round(100 * (hi-lo)/lo, 2);
def per_ok = (per < max_percent);

plot z = if bn == 1 then 0 else
 if !isnan(per_ok) then per_ok
else 0;


# may have to disable this label when used in a scan
addlabel(1, "look back " + len + " bars", color.yellow);
#

this shows the upper and lower chart studies. BK 5min 2/28/22
View attachment 13680
Can't quite wrap my head around the bar number logic. How can you shift those hi and low snippets to only find the highest highs that occur after the lows. So we're looking for low to high gain percentage and not including high to low moves.

*edit: For clarification, I'm trying to learn the logic of how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.
 
Last edited:
Can't quite wrap my head around the bar number logic. How can you shift those hi and low snippets to only find the highest highs that occur after the lows. So we're looking for low to high gain percentage and not including high to low moves.

*edit: For clarification, I'm trying to learn the logic of how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.

i edited my post 2 to include a scanner code

--------------
my original answer in post2 was overly complicated, because it is an upper chart study that draws lines.
in order to draw the lines, you need to read data from future bars.

-------------

a description of the upper code in post2

if the lastbar on the chart is x bars away, then find the highest high, between current bar and lastbar.


def lastbar = (!isnan(close[0]) and isnan(close[-1]));
...this is true on the last bar on chart. when the current bar is not an error and trying to read the next bar (-1) has an error.

input bars_back = 30;
def len = bars_back;

...if the lastbar is 29 bars away, then figure out what the highest high is in the next 29 bars, including current bar.

def hi = if bn == 1 then na
else if lastbar[-(len-1)] then
...if we look -29 bars , to the right, and lastbar is true, then find the highest high, from the lastbar.

highest(high[-(len-1)], len)
...jump to a future bar, then use highest() to look back and find the highest.

...the lastbar is 29 bars away, so use the same offset on the variable , high, to move the reference 29 bars to the right.
high[-(len-1)]

...then , len says to look back to the left 30 bars and find the highest high.
highest( - , len ) .
...this includes the lastbar and the 29 bars to the left. the left most bar will be where this whole formula started from.

else if lastbar[1] then na
...set to na after lastbar, to stop drawing a line

else hi[1];
...repeat previous values
 
Can't quite wrap my head around the bar number logic. How can you shift those hi and low snippets to only find the highest highs that occur after the lows. So we're looking for low to high gain percentage and not including high to low moves.

*edit: For clarification, I'm trying to learn the logic of how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.


*edit: For clarification, I'm trying to learn the logic of how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.


you can't scan for a number. scanning finds true conditions.
you will have to come up with some percent to compare the % numbers to.

maybe this will help you

Code:
#  hilo_within_wper_xmin3

# https://usethinkscript.com/threads/highest-high-and-lowest-low-within-2-over-time.10068/
# post3
#  how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.

#declare lower;

def na = Double.NaN;
def bn = BarNumber();

input bars_back = 50;
def hi = Highest(high, bars_back);
def lo = Lowest(low, bars_back);

input max_percent = 2.0;
def per = Round(100 * (hi - lo) / lo, 2);

def per_ok = (per < max_percent);
def chg = (per - per[1]);
def biggest_change = highest(chg, bars_back);


input test_bubble = yes;
addchartbubble(test_bubble, low * 0.999,
hi + " hi\n" + 
lo + " lo\n" +
(hi - lo) + " diff\n" + 
per + " %\n" +
chg + " chg"
, ( if per_ok then Color.GREEN else Color.GRAY), no);


#per_ok.SetDefaultColor(Color.CYAN);

#----------------------
# test data if used in a lower
input test_labels = no;
AddLabel(test_labels, "look back " + bars_back + " bars", Color.YELLOW);
AddLabel(test_labels, "highest " + hi, Color.YELLOW);
AddLabel(test_labels, "lowest " + lo, Color.YELLOW);
AddLabel(test_labels, "diff " + (hi - lo), Color.YELLOW);
AddLabel(test_labels, per + "%", ( if per_ok then Color.GREEN else Color.GRAY));
#
 
*edit: For clarification, I'm trying to learn the logic of how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.


you can't scan for a number. scanning finds true conditions.
you will have to come up with some percent to compare the % numbers to.

maybe this will help you

Code:
#  hilo_within_wper_xmin3

# https://usethinkscript.com/threads/highest-high-and-lowest-low-within-2-over-time.10068/
# post3
#  how to scan for (and check by plotting the high and lows) the largest % gain from lowest low to highest high within 50 bars.

#declare lower;

def na = Double.NaN;
def bn = BarNumber();

input bars_back = 50;
def hi = Highest(high, bars_back);
def lo = Lowest(low, bars_back);

input max_percent = 2.0;
def per = Round(100 * (hi - lo) / lo, 2);

def per_ok = (per < max_percent);
def chg = (per - per[1]);
def biggest_change = highest(chg, bars_back);


input test_bubble = yes;
addchartbubble(test_bubble, low * 0.999,
hi + " hi\n" +
lo + " lo\n" +
(hi - lo) + " diff\n" +
per + " %\n" +
chg + " chg"
, ( if per_ok then Color.GREEN else Color.GRAY), no);


#per_ok.SetDefaultColor(Color.CYAN);

#----------------------
# test data if used in a lower
input test_labels = no;
AddLabel(test_labels, "look back " + bars_back + " bars", Color.YELLOW);
AddLabel(test_labels, "highest " + hi, Color.YELLOW);
AddLabel(test_labels, "lowest " + lo, Color.YELLOW);
AddLabel(test_labels, "diff " + (hi - lo), Color.YELLOW);
AddLabel(test_labels, per + "%", ( if per_ok then Color.GREEN else Color.GRAY));
#
oh nono, i get how the scans work, I just didn't explain it very well (was gettin late haha) Let's say you set 50 bars and you want to see if at some point within those last 50 days, was there a move of at least 50%. You don't know if that took place over 3 days or 20 days, etc all that matters is that from the lowest low to the highest high that comes after the low, did it hit that 50% threshold. Finding the highest 1 day change would be the easy part, its the not knowing the exact beginning and end point or the length between the 2, or stipulating that the high comes after the low is where my head goes full-on 100% derp mode. As a scan, the true condition in this case would effectively be "yes, within the last 50 bars there was a low to high move of at least 50% " Thanks for your help btw
 
I was thinking you could use the getminvalueoffset to get the lowest low bar number, but how do I proceed to get the high that's after the low since you cant do like "bar number +1" in the length bracket?
 
oh nono, i get how the scans work, I just didn't explain it very well (was gettin late haha) Let's say you set 50 bars and you want to see if at some point within those last 50 days, was there a move of at least 50%. You don't know if that took place over 3 days or 20 days, etc all that matters is that from the lowest low to the highest high that comes after the low, did it hit that 50% threshold. Finding the highest 1 day change would be the easy part, its the not knowing the exact beginning and end point or the length between the 2, or stipulating that the high comes after the low is where my head goes full-on 100% derp mode. As a scan, the true condition in this case would effectively be "yes, within the last 50 bars there was a low to high move of at least 50% " Thanks for your help btw

i might be away a few days, so i typed this on my cell. untested.

find offset back to lowest low.
run a loop, starting from the lowest low, to current bar.
looking to see if high - (lowest low) is a 50% rise. if it is, stop loop and and save loop index number.

scan code. true if it finds a rise of x %

Code:
# scan - was there a 50% rise?
input bars_back = 50;
input percent_rise = 50.0;

#  find bar with lowest low
def lo_off = getminvalueoffset( bars_back );

# get low price from lowest low
def lolo = getvalue( low, lo_off );

# calc the price at a 50% rise
def dollar_rise = lolo * (1 + (percent_rise/100));

# loop, find bar qty after lowest low, when/if price rises more than x %

# use this for offset,  (lo_off - i))
#  so loop starts at bar after the lowest low, not current bar.

def rise_off = fold i = 1 to lo_off+1
with p
while getvalue(high, (lo_off - i)) <= dollar_rise
do p + 1;

# check if loop ran thru all the numbers.
# if it didn't rise high enough, set to 0.
def rise_off2 = if rise_off == lo_off and high < dollar_rise then 0 else rise_off;

# if rise_off2 is > 0 then should mean a rise of 50% was found

# lo_off , offset back to the lowest low.
# rise_off2 , bars after lowest low, when price was x % higher. if 0 then it didn't get x% higher.

plot scan = rise_off2 > 0;

https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/GetMinValueOffset
 
i might be away a few days, so i typed this on my cell. untested.

find offset back to lowest low.
run a loop, starting from the lowest low, to current bar.
looking to see if high - (lowest low) is a 50% rise. if it is, stop loop and and save loop index number.

scan code. true if it finds a rise of x %

Code:
# scan - was there a 50% rise?
input bars_back = 50;
input percent_rise = 50.0;

#  find bar with lowest low
def lo_off = getminvalueoffset( bars_back );

# get low price from lowest low
def lolo = getvalue( low, lo_off );

# calc the price at a 50% rise
def dollar_rise = lolo * (1 + (percent_rise/100));

# loop, find bar qty after lowest low, when/if price rises more than x %

# use this for offset,  (lo_off - i))
#  so loop starts at bar after the lowest low, not current bar.

def rise_off = fold i = 1 to lo_off+1
with p
while getvalue(high, (lo_off - i)) <= dollar_rise
do p + 1;

# check if loop ran thru all the numbers.
# if it didn't rise high enough, set to 0.
def rise_off2 = if rise_off == lo_off and high < dollar_rise then 0 else rise_off;

# if rise_off2 is > 0 then should mean a rise of 50% was found

# lo_off , offset back to the lowest low.
# rise_off2 , bars after lowest low, when price was x % higher. if 0 then it didn't get x% higher.

plot scan = rise_off2 > 0;

https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/GetMinValueOffset
This helped alot in trying to understand the fold function, but there's some kind of error as far as getting the actual pass/fail and I cant seem to find it.
 
Fixed code. Returns a scan result for stocks that have gone UP 50% within the last 50 days.

Code:
# scan - was there a 50% rise?
input bars_back = 50;
input percent_rise = 50.0;


#  find bar with lowest low
def lo_off = getminvalueoffset(low, bars_back );

# get low price from lowest low
def lolo = getvalue( low, lo_off );

# calc the price at a 50% rise
def dollar_rise = lolo * (1 + (percent_rise/100));

# loop, find bar qty after lowest low, when/if price rises more than x %

# use this for offset,  (lo_off - i))
#  so loop starts at bar after the lowest low, not current bar.
def rise_off = fold i = 1 to bars_back + 1
               with p
               while getValue(high, lo_off - i) <= dollar_rise
               do p + 1;

# check if loop ran thru all the numbers.
# if it didn't rise high enough, set to 0.

def rise_off2 = if high < dollar_rise then 0 else rise_off; #  rise_off == lo_off and

# if rise_off2 is > 0 then should mean a rise of 50% was found

# lo_off , offset back to the lowest low.
# rise_off2 , bars after lowest low, when price was x % higher. if 0 then it didn't get x% higher.

plot scan = rise_off2 > 0;
 

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