#day20_low_then_hi_cls
#https://usethinkscript.com/threads/fresh-20-day-highs-and-lows.20570/
#Fresh 20-day Highs and Lows
#BranDonCMK 3/4
# put an arrow under the candle that closed above the high of a candle that created a new 20-day low. Image posted below with scenario circled...
#-------------------
# here is my method for making this,
# study the original rules.
# decide we don't need 2nd aggregation. don't need to say 'day'.
# instead of saying day , set the chart to day, and talk about bars.
# rewrite the rules , bar by bar.
# that way we know what to look for on each bar
# will also make code for the opposite, to find new highs
# to keep it simple, i will do the lowest code first, then code for the highest.
# i like to create formulas to evaluate the rules for the current bar. then when evaluating rule2, use an offset to check rule1.
# the other way would be to, do all the formulas from 1 bar, by using offsets as needed, that point to different bars.
# some of these formulas could be combined. but when you are learning, it is much easier to fix if you have several small formulas.
# you may see 2+ code lines that are near identical, and only 1 enabled. this # disables a code line. my way of version history. makes it easier to try different things. just change 1 character ,
# dont have to type out changes, then later try to remember how the code was a couple versions ago.
#-------------------
# rule1 - is the current low a new 20-day low?
# rule2 - on the next bar, did it close above the previous bar high?
# if rules 1 & 2 are true, draw an arrow under the candle in rule2
#------------------
# set up variables for values that will be used often.
# this way, the code makes only 1 external call to read the data/bar.
# i add these to every study
def na = double.nan;
def bn = barnumber();
def hi = high;
def lo = low;
def opn = open;
def cls = close;
#------------------
# rule1 - a new 20-day low
# the current bar low is a new low. this happens if low = lowest(low,20)
# set up an input to ask for a number, for the length of lowest. how many bars to look back for the lowest.
# if a constant is to be used, i always use an input , instead of def, so the user can change it.
input minmax_length = 20;
# find the lowest number in the past x bars. this includes the current bar.
def lolo = lowest(lo, minmax_length);
# if low = lowest, then it is a new low
def rule1_lo = lo == lolo;
#------------------
# rule2 - next bar, close is above the previous high
# use an offset on hi to compare to previous bar
def rule2_hicls = cls > hi[1];
#------------------
# draw an arrow under the candle in rule2
# check if rules are true. use an offset on rule1 to check the previous bar
# i tend to set variables for all important formulas.
# then make a different variable for plots. i tend to use z as 1st letter in plot variables.
# sometimes i want to be able to turn a plot off or on. if def up = was the plot , and it was turned off, i couldn't use the 'up' value in other formulas.
# this is checking rule2 on the current bar. so rule2 may alternate as true/fasle, as price fluctuates.
def up = rule1_lo[1] and rule2_hicls;
input show_arrows = yes;
# i don't like arrows touching bars. if they are spaced away a little, they are easier to see.
# also if shapes are not green or red, they are easier to see. why i used cyan for arrows.
# i use a vertical offset factor to move arrows away just a little. this way scales fairly well for many different prices.
input y = 0.001;
plot zup = if show_arrows and up then low*(1-y) else na;
zup.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
#zup.SetDefaultColor(Color.green);
zup.SetDefaultColor(Color.cyan);
zup.setlineweight(3);
zup.hidebubble();
#--------------------
# make code for opposite , highest
def hihi = highest(hi, minmax_length);
def rule1_hi = hi == hihi;
def rule2_locls = cls < lo[1];
def dwn = rule1_hi[1] and rule2_locls;
plot zdwn = if show_arrows and dwn then high*(1+y) else na;
zdwn.SetPaintingStrategy(PaintingStrategy.ARROW_down);
#zdwn.SetDefaultColor(Color.green);
#zdwn.SetDefaultColor(Color.cyan);
zdwn.SetDefaultColor(Color.yellow);
zdwn.setlineweight(3);
zdwn.hidebubble();
#