Help coding Joseph Stowell 3 bar net line as a paintbar study

Platform
  1. Thinkorswim
Joseph Stowell was a trader back in the 80-90's trading US Bond futures. Mostly by hand with charts and pencil and ruler, but his 3 bar net line indicator is still a great indicator for current trend. Here is a link that best describes everything about 3bar net line .I would like some help coding a paintbar study for TOS. Red bars when below 3 bar net line, and green when above. This would be a useful indicator as a confirmation you are trading in the right direction. I would love having the cups and caps also coded showing signal arrows or something. Any help is greatly appreciated.
 
Here is some code I got help with from elsewhere (very generously), but it doesn't make paintbars which is what I am looking for. The cups and caps are nice, but what I really want are paintbars red/green depending on long or short status based on 3ar net line. Here is the code I have so far.

Code:
# bar3_net_cupcap_01n4

#---------------------

# https://usethinkscript.com/threads/help-coding-joseph-stowell-3-bar-net-cup-cap.5746/
# Help coding Joseph Stowell 3 bar net, cup, cap.
# https://thepatternsite.com/CupsAndCaps.html


# 3 bar net line
# up trend , higher highs , higher lows
# both have to happen to count as 1 of the 3 bars

# bar1 , current bar , a peak
# bar2 low < bar1 low , high <= bar1 high
# bar3 low < bar2 low , high <= bar2 high
#  bar3 low is horz line level, stop limit


#-----------------

def na = double.nan;
def bn = barnumber();

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

def chartagg = GetAggregationPeriod();
def chartmin = (chartagg / 1000) / 60;
# used at 594 vert adj of cup shading


#-----------------------------
#/////////////////////////////////////////
#/////////////////////////////////////////

# common code, for up trend and down trend


# how many bars back from last bar, to look for a peak or dip, first bar in pattern
#input peak_bar_range = 15;
input net_bar_range = 15;
def nbr = net_bar_range;

# find a bar, x bars before the last bar
#def bar1_rng = !isnan(close[-(nbr-1)]) and isnan(close[-(nbr+0)]);
def netrng_bar1 = !isnan(close[-(nbr-1)]) and isnan(close[-(nbr+0)]);

# find barnumber, 1st bar in net line range
def netrng_bn1 = lastbn - nbr + 1;

# group of bars, near the last bar
# this only used in bubbles , 672 , 690
def isnetrng = !isnan(close[0]) and isnan(close[-(nbr+0)]);

input show_vert_line_start_of_range = yes;
addverticalline(show_vert_line_start_of_range and netrng_bar1, "   " + nbr + "   bars back to look for a peak", color.yellow);

# bars to look back to find net bar 2 and net bar 3
def netlookback = 20;

#/////////////////////////////////////////
#/////////////////////////////////////////

# up trend - 3 bar net line


# find the highest high , near last bar of chart
# find 3 up bars.
# up bar1 is a peak and closest to last bar.
# up bar2 is before bar1
# up bar3 is before bar2





#===========================================
# find up bar #1

# ref , find a peak
# https://usethinkscript.com/threads/zigzag-high-low-with-supply-demand-zones-for-thinkorswim.172/#post-7048
# post10  robert

# find net bar1 peak, close to last bar
input net_3bar_peak_bars = 5;
def netoffset = Min(net_3bar_peak_bars - 1, lastBn - bn);
# orig , future includes current high
#def up1peak = high >= highest(high[1], peak_len - 1) and high == GetValue(highest(high, peak_len), -offset);
# chg future code, to not  include current bar, so its  is high > future high ..
# orig
#def up1peak = (high >= highest(high[1], net_3bar_peak_bars - 1) and high == GetValue(highest(high, net_3bar_peak_bars), -netoffset) );

def netpast = highest(high[1], net_3bar_peak_bars - 1);
def netfuture = GetValue(highest(high, net_3bar_peak_bars-1), -netoffset);
def up1peak = (high >= netpast and high >= netfuture);
def up1peakbn = if up1peak then bn else 0;


addchartbubble(0, low*0.996,
bn + "\n" +
round(high,2) + " hi\n" +
round(netpast,2) + " p_hi" + "\n" +
#round(f,3) + " f_hi" + "\n" +
round(netfuture,3) + " f2_hi" + "\n" +
up1peak + "\n" +
"165"
, (if up1peak then color.yellow else color.gray), no);


# find bar1 bn and save to all bars in last x bars range
def upbar1bn = if netrng_bar1 then highest(up1peakbn[-(nbr-1)], nbr)
  else upbar1bn[1];


input test5_peak = no;
addchartbubble(test5_peak, high*1.004,
net_3bar_peak_bars + "\n" +
netoffset + "\n" +
high + "\n" +
GetValue(highest(high, net_3bar_peak_bars), -netoffset) + "\n"
#GetValue(highest(high, offset), -peak_len)
, color.cyan, yes);



#===========================================
# find up bar #2
# start on bar 1 and look back

def upbar2off = if bn == upbar1bn then
 (fold d2 = 0 to netlookback
 with k2 = 0
 while (high[0] >= getvalue(high, d2) and low[0] > getvalue(low, d2)) == 0
 do k2 + 1)
 else 0;

# find bar2 bn and save to all bars in last x bars range
def upbar2off2 = if netrng_bar1 then
  highest( upbar2off[-(nbr-1)], nbr )
  else upbar2off2[1];

def upbar2bn = upbar1bn - upbar2off2;

#===========================================
# find up bar #3
# start on bar 2 and look back

def upbar3off = if bn == upbar2bn then
 (fold d3 = 0 to netlookback
 with k3 = 0
 while (high[0] >= getvalue(high, d3) and low[0] > getvalue(low, d3)) == 0
 do k3 + 1)
 else 0;


# find bar3 bn and save to all bars in last x bars range
# yyyy  ??
# ?? this doesnt test if bar3 is still in the range, just if bar2 is
# get value from future and save it in other bars
def upbar3off2 =
#  if (upbar2bn - upbar3off) < (lastbn - xbars_to_lastbn) then 0 else
# if !bar1_rng then 0 else
 if netrng_bar1 then
  highest( upbar3off[-(nbr-1)], nbr )
  else upbar3off2[1];


def upbar3off3 = if (upbar2bn - upbar3off2) < netrng_bn1 then 0 else 1;


input test4 = no;
addchartbubble(test4, high*1.005,
upbar2bn + " 2bn\n" +
upbar3off2 + " off2\n" +
(upbar2bn - upbar3off2) + " 2diff\n" +
lastbn + " last\n" +
netrng_bn1 + " net\n" +
upbar3off3 + "  off3"
, color.cyan, yes);


#def upbar3bn = upbar2bn - upbar3off2;
def upbar3bn = if upbar3off3 then (upbar2bn - upbar3off2) else 0;

# -------------------------------------

# add numbers of the 3 bar net patterns to a var
def upbarz = if bn < netrng_bn1 then 0 else
  if bn == upbar1bn then 1
  else if bn == upbar2bn then 2
  else if bn == upbar3bn then 3
  else 0;

# ------------------------------------
# stop line
# up trend - calc a stop line, from low of bar3
def up3bar_netline =
  if bn == 1 or isnan(close) then 0
  else if bn == upbar3bn then low
  else up3bar_netline[1];

# ------------------------------------
# warn line
# up trend - calc a warn line, from high of bar3
def up3bar_warnline =
  if bn == 1 or isnan(close) then 0
  else if bn == upbar3bn then high
  else up3bar_warnline[1];

# -------------------------------------




# yyyy  can have 2+ red arrows when crosses red line level
#  need to check ..? and only have 1 arrow
# reorganize the code sections



# cancel up trend , sell
# draw red down arrow, when price cosses below the  'up stop line' , net line
def upsell = if bn == 1 then 0 else if close crosses below up3bar_netline then 1 else 0;
plot upcancel = if upsell then high*1.001 else na;
upcancel.setpaintingStrategy(PaintingStrategy.arrow_down);
upcancel.setdefaultcolor(color.red);
upcancel.setlineweight(2);
upcancel.hidebubble();


# -------------------------------------

# draw a stop line.  end it if a red down arrow
def upstopb = if bn == 1 then 0
# look at prev bar, so line cont onto cancel bar
 else if upsell[1] then -1
 else if upstopb[1] == -1 then -1
 else if up3bar_netline > 0 then up3bar_netline
 else upstopb[1];

plot upstop = if upstopb > 0 then upstopb else na;
upstop.setdefaultcolor(color.red);
upstop.setlineweight(2);
#upstop.hidebubble();

#--------------------------------------
# bubble under stop line

input show_up_reversal_bubble = yes;
addchartbubble(show_up_reversal_bubble and (bn == upbar3bn), low*0.9995,
"Up trend" + "\n" +
"Reversal" + "\n" +
"Line"
, color.magenta, no);



# -------------------------------------

# draw a warn line, above stop line.  end it if a red down arrow
def upwarnb = if bn == 1 then 0
# else if upsell then -1
# look at prev bar, so line cont onto cancel bar
 else if upsell[1] then -1
 else if upwarnb[1] == -1 then -1
 else if up3bar_warnline > 0 then up3bar_warnline
 else upwarnb[1];

plot upwarn = if upwarnb > 0 then upwarnb else na;
#upwarn.setdefaultcolor(color.yellow);
upwarn.setdefaultcolor(color.light_gray);
upwarn.setlineweight(1);
upwarn.hidebubble();


# ----------------------------------
# warn of possible end of up trend
# draw yellow down arrow, when low cosses below the  'up stop line'
def upsellwarn = if !upsell and high > upstop and low < upstop then 1 else 0;
plot upwarnarrow = if upsellwarn then high*1.001 else na;
upwarnarrow.setpaintingStrategy(PaintingStrategy.arrow_down);
upwarnarrow.setdefaultcolor(color.yellow);
upwarnarrow.setlineweight(2);

# -------------------------------------

input show_sequence_numbers_above_up_bars = yes;
plot zup = if show_sequence_numbers_above_up_bars and upbarz > 0 then upbarz else na;
zup.setpaintingStrategy(PaintingStrategy.VALUES_ABOVE);
zup.setdefaultcolor(color.white);
zup.hidebubble();


#-----------------
# white dots above net3 up bars
def point_vert = 0.0024;
input show_points_above_up_bars = yes;
plot wup = if show_points_above_up_bars and upbarz > 0 then (high * (1 + point_vert)) else na;
wup.setpaintingStrategy(PaintingStrategy.points);
wup.setdefaultcolor(color.white);
wup.setlineweight(3);
wup.hidebubble();


# -------------------------------------
# -------------------------------------

# =====================================
# alerts , sounds
# alert(condition, text, alert type, sound);
# Sound.Ding,  higher , up sound
# Sound.Bell,  lower , down sound
#def a = no;
#alert(a, "crossed up" ,alert.BAR, sound.DING);
alert(upsell, "crossed down" ,alert.BAR, sound.bell);
# =====================================




#/////////////////////////////////////////
#/////////////////////////////////////////

# down trend - 3 bar net line

#  down trend-------------------







#/////////////////////////////////////////
#/////////////////////////////////////////
#/////////////////////////////////////////
#/////////////////////////////////////////

# common code for cup and cap


input show_cup_data = yes;
input show_cap_data = yes;

# find a peak for bar1 of a cup or cap. highest in +- x bars
input cupcap_bar1_peak_bars = 5;
def coffset = Min(cupcap_bar1_peak_bars - 1, lastBn - bn);
# chg future code, to not  include current, so its x > future...

def big = 999999;

# cup , cap stop line,
#  does price cross below cup line within x bars?  sell
#  does price cross above cap line within x bars?  buy
# orig rules, define 3 bars after cup, to look for a lower low
input c_cross_within_bars = 6;

# cup,  price has to be 0.01 lower than sell line
# cap,  price has to be 0.01 higher than buy line
def cdiff1 = 0.01;


#/////////////////////////////////////////
#/////////////////////////////////////////

# cup reversal pattern , sell


#up trend
#cup, at a peak

#3 bars , middle bar lower

#bar1 high is the peak, this is bar1 of the netline pattern
#bar2 low is lower
#bar3 low is higher

# draw a line from bar2 low
#sell when,  price < (middle bar low - $0.03) , within 3 bars of cup bar3

# ----------------------



# ref  net up peak
#  def netpast = highest(high[1], net_3bar_peak_bars - 1);
#  def netfuture = GetValue(highest(high, net_3bar_peak_bars-1), -netoffset);
#  def up1peak = (high >= netpast and high >= netfuture);

#def cupbar1peak = high >= highest(high[1], cupcap_bar1_peak_bars - 1) and high == GetValue(highest(high, cupcap_bar1_peak_bars), -coffset);
def cupbar1peak = high >= highest(high[1], cupcap_bar1_peak_bars - 1) and high >= GetValue(highest(high, cupcap_bar1_peak_bars-1), -coffset);

def cbar1peakbn = if cupbar1peak then bn else 0;

# ----------------

# cup , sell pattern

#def cupbar1 = if bn <= peak_len then 0 else if up1peak then 1 else 0;
def cupbar1 = if bn <=  cupcap_bar1_peak_bars then 0 else if cupbar1peak then 1 else 0;
def cupbar2 = if cupbar1[1] and low < low[1] then 1 else 0;
def cupbar3 = if cupbar2[1] and low > low[1] then 1 else 0;

def cupbar1_high = if cupbar1 then high else cupbar1_high[1];
def cupbar1_low = if cupbar1 then low else cupbar1_low[1];
def cupbar2_low = if cupbar2 and cupbar3[-1] then low else cupbar2_low[1];

def cupbar3bn = if bn == 1 then big else
if (lastbn - bn) <= 3 then  cupbar3bn[1]
else if cupbar3[-2] then bn+2 else cupbar3bn[1];






def cupline_stop = if bn == 1 then 0
# did price cross below line?

# this is true on yellow arrow ? and stopping line
# else if bn > cupbar3bn and close < (cupbar2_low + cdiff1) then 1
# chg +diff  to  -diff
# yyyy
 else if bn > cupbar3bn and close <= (cupbar2_low - cdiff1) then 1

# -3 offset below. if within 3 bars of last bar, then 0 , keep line going
 else if (lastbn - bn) <= 3 then 0
# if a valid cup, start another line, dont stop old line
 else if cupbar2[0] and cupbar3[-1] then 0
# was the prev bar a crossing?
 else if cupline_stop[1] then 0
# has the line gone x bars with no crossing ?  2 close cups will false trigger
# else if cupbar3[xwithin_bars] then 1
# chg to check recent bar3 bn
 else if bn >= (cupbar3bn + c_cross_within_bars) then 1
# did another cup appear?  check for bar3, not bar1
# else if cupbar1[-1] then 1
# else if isnan(cupbar3[-3]) then 0
#else if (lastbn - bn) <= 3 then 0
 else if cupbar3[-3] then 1
## did price cross below line?
# else if bn > cupbar3bn and close < (cupbar2_low + cdiff1) then 1
 else cupline_stop[1];



def cupsell_price = if bn == 1 then na
 else if cupline_stop[1] or isnan(close) then na
#  -1 offset ,  so check if 1 bar from lastbar
 else if (lastbn - bn) <= 1 then cupsell_price[1]
 else if cupbar3[-1] then cupbar2_low
 else cupsell_price[1];


input test6_cup = no;
addchartbubble(test6_cup, low*0.9960,
bn  + "\n" +
cupbar3bn + " 3bn\n" +
(cupbar3bn + c_cross_within_bars) + " 3+\n" +
cupline_stop + " stp\n" +
cupsell_price + " sell$\n" +
(cupbar2_low + cdiff1) + " 2low+\n" +
close + " cls"
, color.yellow, no);






# cup sell line
plot cupsell2 = cupsell_price;
cupsell2.setdefaultcolor(color.light_red);
#  Strategy.DASHES: 1 dash per candle, no matter the zoom level
cupsell2.SetPaintingStrategy(PaintingStrategy.DASHES);
cupsell2.hidebubble();
cupsell2.setlineweight(2);
#  Curve.._DASH: qty of dashes changes based on zoom level.
#  zoom in = many dashes, narrower than candle. zoom out = fewer, dashes, wider than candle
# cupsell2.SetStyle(Curve.MEDIUM_DASH);


# show a price bubble, when last bar has a cup sell line
def bub_off1 = 1;
addchartbubble( (lastbar[bub_off1] and !isnan(cupsell_price[bub_off1])) , cupsell_price[bub_off1],
 round(cupsell_price[bub_off1],2)
, color.light_red, no);



def cupsell_a = (!isnan(cupsell_price) and cupline_stop and close < (cupbar2_low - cdiff1));
#plot cupsellz = if (!isnan(sellzz) and cupsell and close < (cupbar2_low + diff1)) then high*1.001 else na;
plot cupsellz = if cupsell_a then high*1.001 else na;
cupsellz.setpaintingStrategy(PaintingStrategy.arrow_down);
#cupsellz.setdefaultcolor(color.magenta);
cupsellz.setdefaultcolor(color.white);
cupsellz.setlineweight(4);
cupsellz.hidebubble();





# yyyy   need to stop arrows, only 1 .  change the bar2 price level?  to na ?  after 6 bars?
#  chk if line exists

# warn of possible down trend
# draw yellow down arrow, when low cosses below the  'cup stop line'
def cupsell_warn = if !isnan(cupsell_price) and !cupsell_a and high > cupbar2_low and low < (cupbar2_low - cdiff1) then 1 else 0;
#def cupsell_warn = if !isnan(cupsell_a) and !cupsell_a and high > cupbar2_low and low < (cupbar2_low - cdiff1) then 1 else 0;
plot cupwarn_arrow = if cupsell_warn then high*1.001 else na;
cupwarn_arrow.setpaintingStrategy(PaintingStrategy.arrow_down);
cupwarn_arrow.setdefaultcolor(color.yellow);
cupwarn_arrow.setlineweight(2);
cupwarn_arrow.hidebubble();


# ---------------------

# shade cup pattern in red
# get highest of 3 cup bars, after bar3 exists
# this doesn't work when cup is the last 3 bars on chart
# shades first half of the cup when 1 bar after bar3

# yyyy
# make dup cond, copy these cond and add a chk for lastbar
def cup_hi = if cupbar3[-2] then max(high, max(high[-1], high[-2] ))
 else if cupbar3[-1] then cup_hi[1]
 else if cupbar3[0] then cup_hi[1]
 else na;

# lowest is bar2
def cup_lo = if cupbar3[-2] then low[-1]
 else if cupbar3[-1] then cup_lo[1]
 else if cupbar3[0] then cup_lo[1]
 else na;

# this causes error .  no recs in addcloud
#   addcloud(cup_hi*1.005, cup_lo*0.995, color.light_red, color.light_red);
# assign new vars , and ref them in addcloud.  then it works

# on 1 min, red shading is very tall, scale is down
 def vert3 = if chartmin <= 5 then 0.001 else 0.002;
 def vert2 = vert3;
#def vert2 = 0.002;
def cuphi2 = cup_hi * (1 + vert2);
def cuplo2 = cup_lo * (1 - vert2);
addcloud(cuphi2, cuplo2, color.red, color.red);

#addlabel(1, "vert2 " + vert2, color.pink);


# cup bubble above cup pattern, chk if cup bar3 exists
addchartbubble( cupbar3[-2], cuphi2,  "CUP", color.light_red);
# this will label a cup on last 3 bars.   but it wont be shaded red or have numbers 2 and 3



#----------------
# cup stats

def cupqty = if bn == 1 then 0 else if cupbar3 then cupqty[1] + 1 else cupqty[1];
def cupsellqty = if bn == 1 then 0
 else if isnan(cupsell_a) then cupsellqty[1]
 else if cupsell_a then cupsellqty[1] + 1
 else cupsellqty[1];
def cupsellper = round(100*cupsellqty/cupqty, 1);

addlabel(1, "Cups: " + cupqty + " , Sells: " + cupsellqty, color.light_red);
addlabel(1, "Cup sell: " + cupsellper + "%", color.light_red);

#---------------------------------

# cup , number the bars
# add numbers to the 3 bars. check if bar3 exists
def cupnum = if cupbar1 and cupbar3[-2] then 1
  else if cupbar2 and cupbar3[-1] then 2
  else if cupbar3 then 3
  else 0;

# cup bar1
plot cupnumz = if cupnum > 0 then cupnum else na;
cupnumz.setpaintingStrategy(PaintingStrategy.VALUES_below);
cupnumz.setdefaultcolor(color.white);
cupnumz.hidebubble();


#---------------------------------
# cup test stuff

#addverticalline(cupbar3[-1] , "   cup bar2", color.cyan);

input test5_cup = no;
addchartbubble(test5_cup, low*0.997,
"cup" + "\n" +
 bn + "\n" +
 upbar1bn + "  1\n" +
 upbar3bn + "  3\n" +
cupbar1_high + "  hi\n" +
cupbar1_low + "  lo\n" +
upbar3off3 + "\n" +
cupbar2_low + "\n" +
#sellzz + "\n" +
cupsell_price + "\n" +
cupbar3bn
, (if bn == upbar1bn then color.yellow else if bn == upbar3bn then color.cyan else color.gray), no);



input test6_cupnum = no;
addchartbubble(test6_cupnum, low*0.997,
cupbar1 + "\n" +
cupbar2 + "\n" +
cupbar3 + "\n" +
cupnum + "\n" +
high + "\n" +
low + "\n" +
cupbar2_low
, (if bn == upbar1bn then color.yellow else if bn == upbar3bn then color.cyan else color.gray), no);

#---------------------------------








#/////////////////////////////////////////
#/////////////////////////////////////////

# cap reversal pattern , buy




#/////////////////////////////////////////
#/////////////////////////////////////////





#==========================================
# test stuff


# up bar3 line stats
addchartbubble(0, low*0.994,
bn + "\n" +
up3bar_warnline + " w\n" +
up3bar_netline + " s\n" +
upsell + "\n" +
upstopb + "\n" +
upstop + "\n"
,color.cyan, no);


addchartbubble(0, high*1.003,
(high[0] >= getvalue(high, 1) and low[0] > getvalue(low, 1))
, color.cyan, yes);


addchartbubble(0 and isnetrng, low*0.995,
 bn + "\n" +
high + "\n" +
#jj + " jj2\n" +
#upbar1peakbn + "\n" +
 upbar1bn + " 1bn\n" +
#upbar1bn4 + " 4\n" +
# upbar2bn2 + " 2off\n" +
 upbar2off + " 2off\n" +
 upbar2off2 + " 2off2\n" +
 upbar2bn + " 2bn\n" +
# upbar1bn + " 1c"
 upbar3off + " 3off\n" +
 upbar3off2 + " 3off2\n" +
 upbar3bn + " 3bn\n"
, (if upbar2off > 0 then color.cyan else if upbar3off > 0 then color.magenta else color.gray), no);
#, color.cyan, no);

addchartbubble(0 and isnetrng, low*0.995,
 bn + "\n" +
 upbar1bn + "  1\n" +
 upbar2bn + "  2\n" +
 upbar3off + " 3off\n" +
 upbar3off2 + " 3off2\n" +
 upbar3bn + " 3\n"
, color.cyan, no);


#--------------------------------------


#plot x =
# x.setdefaultcolor(color.light_red);
#  Curve.._DASH: qty of dashes changes based on zoom level.
#  zoom in = many dashes, narrower than candle. zoom out = fewer, dashes, wider than candle
# x.SetStyle(Curve.MEDIUM_DASH);
# x.SetDefaultColor(Color.red);
# x.setlineweight(1);
# x.hidebubble();
# x.SetPaintingStrategy(PaintingStrategy.LINE);
#  Strategy.DASHES: 1 dash per candle, no matter the zoom level
# x.SetPaintingStrategy(PaintingStrategy.DASHES);

# x.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
# x.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
# x.SetPaintingStrategy(PaintingStrategy.POINTS);
# x.SetPaintingStrategy(PaintingStrategy.SQUARES);
# x.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#
 
Here is some code I got help with from elsewhere (very generously), but it doesn't make paintbars which is what I am looking for. The cups and caps are nice, but what I really want are paintbars red/green depending on long or short status based on 3ar net line. Here is the code I have so far.

Code:
# bar3_net_cupcap_01n4

#---------------------

# https://usethinkscript.com/threads/help-coding-joseph-stowell-3-bar-net-cup-cap.5746/
# Help coding Joseph Stowell 3 bar net, cup, cap.
# https://thepatternsite.com/CupsAndCaps.html


# 3 bar net line
# up trend , higher highs , higher lows
# both have to happen to count as 1 of the 3 bars

# bar1 , current bar , a peak
# bar2 low < bar1 low , high <= bar1 high
# bar3 low < bar2 low , high <= bar2 high
#  bar3 low is horz line level, stop limit


#-----------------

def na = double.nan;
def bn = barnumber();

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

def chartagg = GetAggregationPeriod();
def chartmin = (chartagg / 1000) / 60;
# used at 594 vert adj of cup shading


#-----------------------------
#/////////////////////////////////////////
#/////////////////////////////////////////

# common code, for up trend and down trend


# how many bars back from last bar, to look for a peak or dip, first bar in pattern
#input peak_bar_range = 15;
input net_bar_range = 15;
def nbr = net_bar_range;

# find a bar, x bars before the last bar
#def bar1_rng = !isnan(close[-(nbr-1)]) and isnan(close[-(nbr+0)]);
def netrng_bar1 = !isnan(close[-(nbr-1)]) and isnan(close[-(nbr+0)]);

# find barnumber, 1st bar in net line range
def netrng_bn1 = lastbn - nbr + 1;

# group of bars, near the last bar
# this only used in bubbles , 672 , 690
def isnetrng = !isnan(close[0]) and isnan(close[-(nbr+0)]);

input show_vert_line_start_of_range = yes;
addverticalline(show_vert_line_start_of_range and netrng_bar1, "   " + nbr + "   bars back to look for a peak", color.yellow);

# bars to look back to find net bar 2 and net bar 3
def netlookback = 20;

#/////////////////////////////////////////
#/////////////////////////////////////////

# up trend - 3 bar net line


# find the highest high , near last bar of chart
# find 3 up bars.
# up bar1 is a peak and closest to last bar.
# up bar2 is before bar1
# up bar3 is before bar2





#===========================================
# find up bar #1

# ref , find a peak
# https://usethinkscript.com/threads/zigzag-high-low-with-supply-demand-zones-for-thinkorswim.172/#post-7048
# post10  robert

# find net bar1 peak, close to last bar
input net_3bar_peak_bars = 5;
def netoffset = Min(net_3bar_peak_bars - 1, lastBn - bn);
# orig , future includes current high
#def up1peak = high >= highest(high[1], peak_len - 1) and high == GetValue(highest(high, peak_len), -offset);
# chg future code, to not  include current bar, so its  is high > future high ..
# orig
#def up1peak = (high >= highest(high[1], net_3bar_peak_bars - 1) and high == GetValue(highest(high, net_3bar_peak_bars), -netoffset) );

def netpast = highest(high[1], net_3bar_peak_bars - 1);
def netfuture = GetValue(highest(high, net_3bar_peak_bars-1), -netoffset);
def up1peak = (high >= netpast and high >= netfuture);
def up1peakbn = if up1peak then bn else 0;


addchartbubble(0, low*0.996,
bn + "\n" +
round(high,2) + " hi\n" +
round(netpast,2) + " p_hi" + "\n" +
#round(f,3) + " f_hi" + "\n" +
round(netfuture,3) + " f2_hi" + "\n" +
up1peak + "\n" +
"165"
, (if up1peak then color.yellow else color.gray), no);


# find bar1 bn and save to all bars in last x bars range
def upbar1bn = if netrng_bar1 then highest(up1peakbn[-(nbr-1)], nbr)
  else upbar1bn[1];


input test5_peak = no;
addchartbubble(test5_peak, high*1.004,
net_3bar_peak_bars + "\n" +
netoffset + "\n" +
high + "\n" +
GetValue(highest(high, net_3bar_peak_bars), -netoffset) + "\n"
#GetValue(highest(high, offset), -peak_len)
, color.cyan, yes);



#===========================================
# find up bar #2
# start on bar 1 and look back

def upbar2off = if bn == upbar1bn then
 (fold d2 = 0 to netlookback
 with k2 = 0
 while (high[0] >= getvalue(high, d2) and low[0] > getvalue(low, d2)) == 0
 do k2 + 1)
 else 0;

# find bar2 bn and save to all bars in last x bars range
def upbar2off2 = if netrng_bar1 then
  highest( upbar2off[-(nbr-1)], nbr )
  else upbar2off2[1];

def upbar2bn = upbar1bn - upbar2off2;

#===========================================
# find up bar #3
# start on bar 2 and look back

def upbar3off = if bn == upbar2bn then
 (fold d3 = 0 to netlookback
 with k3 = 0
 while (high[0] >= getvalue(high, d3) and low[0] > getvalue(low, d3)) == 0
 do k3 + 1)
 else 0;


# find bar3 bn and save to all bars in last x bars range
# yyyy  ??
# ?? this doesnt test if bar3 is still in the range, just if bar2 is
# get value from future and save it in other bars
def upbar3off2 =
#  if (upbar2bn - upbar3off) < (lastbn - xbars_to_lastbn) then 0 else
# if !bar1_rng then 0 else
 if netrng_bar1 then
  highest( upbar3off[-(nbr-1)], nbr )
  else upbar3off2[1];


def upbar3off3 = if (upbar2bn - upbar3off2) < netrng_bn1 then 0 else 1;


input test4 = no;
addchartbubble(test4, high*1.005,
upbar2bn + " 2bn\n" +
upbar3off2 + " off2\n" +
(upbar2bn - upbar3off2) + " 2diff\n" +
lastbn + " last\n" +
netrng_bn1 + " net\n" +
upbar3off3 + "  off3"
, color.cyan, yes);


#def upbar3bn = upbar2bn - upbar3off2;
def upbar3bn = if upbar3off3 then (upbar2bn - upbar3off2) else 0;

# -------------------------------------

# add numbers of the 3 bar net patterns to a var
def upbarz = if bn < netrng_bn1 then 0 else
  if bn == upbar1bn then 1
  else if bn == upbar2bn then 2
  else if bn == upbar3bn then 3
  else 0;

# ------------------------------------
# stop line
# up trend - calc a stop line, from low of bar3
def up3bar_netline =
  if bn == 1 or isnan(close) then 0
  else if bn == upbar3bn then low
  else up3bar_netline[1];

# ------------------------------------
# warn line
# up trend - calc a warn line, from high of bar3
def up3bar_warnline =
  if bn == 1 or isnan(close) then 0
  else if bn == upbar3bn then high
  else up3bar_warnline[1];

# -------------------------------------




# yyyy  can have 2+ red arrows when crosses red line level
#  need to check ..? and only have 1 arrow
# reorganize the code sections



# cancel up trend , sell
# draw red down arrow, when price cosses below the  'up stop line' , net line
def upsell = if bn == 1 then 0 else if close crosses below up3bar_netline then 1 else 0;
plot upcancel = if upsell then high*1.001 else na;
upcancel.setpaintingStrategy(PaintingStrategy.arrow_down);
upcancel.setdefaultcolor(color.red);
upcancel.setlineweight(2);
upcancel.hidebubble();


# -------------------------------------

# draw a stop line.  end it if a red down arrow
def upstopb = if bn == 1 then 0
# look at prev bar, so line cont onto cancel bar
 else if upsell[1] then -1
 else if upstopb[1] == -1 then -1
 else if up3bar_netline > 0 then up3bar_netline
 else upstopb[1];

plot upstop = if upstopb > 0 then upstopb else na;
upstop.setdefaultcolor(color.red);
upstop.setlineweight(2);
#upstop.hidebubble();

#--------------------------------------
# bubble under stop line

input show_up_reversal_bubble = yes;
addchartbubble(show_up_reversal_bubble and (bn == upbar3bn), low*0.9995,
"Up trend" + "\n" +
"Reversal" + "\n" +
"Line"
, color.magenta, no);



# -------------------------------------

# draw a warn line, above stop line.  end it if a red down arrow
def upwarnb = if bn == 1 then 0
# else if upsell then -1
# look at prev bar, so line cont onto cancel bar
 else if upsell[1] then -1
 else if upwarnb[1] == -1 then -1
 else if up3bar_warnline > 0 then up3bar_warnline
 else upwarnb[1];

plot upwarn = if upwarnb > 0 then upwarnb else na;
#upwarn.setdefaultcolor(color.yellow);
upwarn.setdefaultcolor(color.light_gray);
upwarn.setlineweight(1);
upwarn.hidebubble();


# ----------------------------------
# warn of possible end of up trend
# draw yellow down arrow, when low cosses below the  'up stop line'
def upsellwarn = if !upsell and high > upstop and low < upstop then 1 else 0;
plot upwarnarrow = if upsellwarn then high*1.001 else na;
upwarnarrow.setpaintingStrategy(PaintingStrategy.arrow_down);
upwarnarrow.setdefaultcolor(color.yellow);
upwarnarrow.setlineweight(2);

# -------------------------------------

input show_sequence_numbers_above_up_bars = yes;
plot zup = if show_sequence_numbers_above_up_bars and upbarz > 0 then upbarz else na;
zup.setpaintingStrategy(PaintingStrategy.VALUES_ABOVE);
zup.setdefaultcolor(color.white);
zup.hidebubble();


#-----------------
# white dots above net3 up bars
def point_vert = 0.0024;
input show_points_above_up_bars = yes;
plot wup = if show_points_above_up_bars and upbarz > 0 then (high * (1 + point_vert)) else na;
wup.setpaintingStrategy(PaintingStrategy.points);
wup.setdefaultcolor(color.white);
wup.setlineweight(3);
wup.hidebubble();


# -------------------------------------
# -------------------------------------

# =====================================
# alerts , sounds
# alert(condition, text, alert type, sound);
# Sound.Ding,  higher , up sound
# Sound.Bell,  lower , down sound
#def a = no;
#alert(a, "crossed up" ,alert.BAR, sound.DING);
alert(upsell, "crossed down" ,alert.BAR, sound.bell);
# =====================================




#/////////////////////////////////////////
#/////////////////////////////////////////

# down trend - 3 bar net line

#  down trend-------------------







#/////////////////////////////////////////
#/////////////////////////////////////////
#/////////////////////////////////////////
#/////////////////////////////////////////

# common code for cup and cap


input show_cup_data = yes;
input show_cap_data = yes;

# find a peak for bar1 of a cup or cap. highest in +- x bars
input cupcap_bar1_peak_bars = 5;
def coffset = Min(cupcap_bar1_peak_bars - 1, lastBn - bn);
# chg future code, to not  include current, so its x > future...

def big = 999999;

# cup , cap stop line,
#  does price cross below cup line within x bars?  sell
#  does price cross above cap line within x bars?  buy
# orig rules, define 3 bars after cup, to look for a lower low
input c_cross_within_bars = 6;

# cup,  price has to be 0.01 lower than sell line
# cap,  price has to be 0.01 higher than buy line
def cdiff1 = 0.01;


#/////////////////////////////////////////
#/////////////////////////////////////////

# cup reversal pattern , sell


#up trend
#cup, at a peak

#3 bars , middle bar lower

#bar1 high is the peak, this is bar1 of the netline pattern
#bar2 low is lower
#bar3 low is higher

# draw a line from bar2 low
#sell when,  price < (middle bar low - $0.03) , within 3 bars of cup bar3

# ----------------------



# ref  net up peak
#  def netpast = highest(high[1], net_3bar_peak_bars - 1);
#  def netfuture = GetValue(highest(high, net_3bar_peak_bars-1), -netoffset);
#  def up1peak = (high >= netpast and high >= netfuture);

#def cupbar1peak = high >= highest(high[1], cupcap_bar1_peak_bars - 1) and high == GetValue(highest(high, cupcap_bar1_peak_bars), -coffset);
def cupbar1peak = high >= highest(high[1], cupcap_bar1_peak_bars - 1) and high >= GetValue(highest(high, cupcap_bar1_peak_bars-1), -coffset);

def cbar1peakbn = if cupbar1peak then bn else 0;

# ----------------

# cup , sell pattern

#def cupbar1 = if bn <= peak_len then 0 else if up1peak then 1 else 0;
def cupbar1 = if bn <=  cupcap_bar1_peak_bars then 0 else if cupbar1peak then 1 else 0;
def cupbar2 = if cupbar1[1] and low < low[1] then 1 else 0;
def cupbar3 = if cupbar2[1] and low > low[1] then 1 else 0;

def cupbar1_high = if cupbar1 then high else cupbar1_high[1];
def cupbar1_low = if cupbar1 then low else cupbar1_low[1];
def cupbar2_low = if cupbar2 and cupbar3[-1] then low else cupbar2_low[1];

def cupbar3bn = if bn == 1 then big else
if (lastbn - bn) <= 3 then  cupbar3bn[1]
else if cupbar3[-2] then bn+2 else cupbar3bn[1];






def cupline_stop = if bn == 1 then 0
# did price cross below line?

# this is true on yellow arrow ? and stopping line
# else if bn > cupbar3bn and close < (cupbar2_low + cdiff1) then 1
# chg +diff  to  -diff
# yyyy
 else if bn > cupbar3bn and close <= (cupbar2_low - cdiff1) then 1

# -3 offset below. if within 3 bars of last bar, then 0 , keep line going
 else if (lastbn - bn) <= 3 then 0
# if a valid cup, start another line, dont stop old line
 else if cupbar2[0] and cupbar3[-1] then 0
# was the prev bar a crossing?
 else if cupline_stop[1] then 0
# has the line gone x bars with no crossing ?  2 close cups will false trigger
# else if cupbar3[xwithin_bars] then 1
# chg to check recent bar3 bn
 else if bn >= (cupbar3bn + c_cross_within_bars) then 1
# did another cup appear?  check for bar3, not bar1
# else if cupbar1[-1] then 1
# else if isnan(cupbar3[-3]) then 0
#else if (lastbn - bn) <= 3 then 0
 else if cupbar3[-3] then 1
## did price cross below line?
# else if bn > cupbar3bn and close < (cupbar2_low + cdiff1) then 1
 else cupline_stop[1];



def cupsell_price = if bn == 1 then na
 else if cupline_stop[1] or isnan(close) then na
#  -1 offset ,  so check if 1 bar from lastbar
 else if (lastbn - bn) <= 1 then cupsell_price[1]
 else if cupbar3[-1] then cupbar2_low
 else cupsell_price[1];


input test6_cup = no;
addchartbubble(test6_cup, low*0.9960,
bn  + "\n" +
cupbar3bn + " 3bn\n" +
(cupbar3bn + c_cross_within_bars) + " 3+\n" +
cupline_stop + " stp\n" +
cupsell_price + " sell$\n" +
(cupbar2_low + cdiff1) + " 2low+\n" +
close + " cls"
, color.yellow, no);






# cup sell line
plot cupsell2 = cupsell_price;
cupsell2.setdefaultcolor(color.light_red);
#  Strategy.DASHES: 1 dash per candle, no matter the zoom level
cupsell2.SetPaintingStrategy(PaintingStrategy.DASHES);
cupsell2.hidebubble();
cupsell2.setlineweight(2);
#  Curve.._DASH: qty of dashes changes based on zoom level.
#  zoom in = many dashes, narrower than candle. zoom out = fewer, dashes, wider than candle
# cupsell2.SetStyle(Curve.MEDIUM_DASH);


# show a price bubble, when last bar has a cup sell line
def bub_off1 = 1;
addchartbubble( (lastbar[bub_off1] and !isnan(cupsell_price[bub_off1])) , cupsell_price[bub_off1],
 round(cupsell_price[bub_off1],2)
, color.light_red, no);



def cupsell_a = (!isnan(cupsell_price) and cupline_stop and close < (cupbar2_low - cdiff1));
#plot cupsellz = if (!isnan(sellzz) and cupsell and close < (cupbar2_low + diff1)) then high*1.001 else na;
plot cupsellz = if cupsell_a then high*1.001 else na;
cupsellz.setpaintingStrategy(PaintingStrategy.arrow_down);
#cupsellz.setdefaultcolor(color.magenta);
cupsellz.setdefaultcolor(color.white);
cupsellz.setlineweight(4);
cupsellz.hidebubble();





# yyyy   need to stop arrows, only 1 .  change the bar2 price level?  to na ?  after 6 bars?
#  chk if line exists

# warn of possible down trend
# draw yellow down arrow, when low cosses below the  'cup stop line'
def cupsell_warn = if !isnan(cupsell_price) and !cupsell_a and high > cupbar2_low and low < (cupbar2_low - cdiff1) then 1 else 0;
#def cupsell_warn = if !isnan(cupsell_a) and !cupsell_a and high > cupbar2_low and low < (cupbar2_low - cdiff1) then 1 else 0;
plot cupwarn_arrow = if cupsell_warn then high*1.001 else na;
cupwarn_arrow.setpaintingStrategy(PaintingStrategy.arrow_down);
cupwarn_arrow.setdefaultcolor(color.yellow);
cupwarn_arrow.setlineweight(2);
cupwarn_arrow.hidebubble();


# ---------------------

# shade cup pattern in red
# get highest of 3 cup bars, after bar3 exists
# this doesn't work when cup is the last 3 bars on chart
# shades first half of the cup when 1 bar after bar3

# yyyy
# make dup cond, copy these cond and add a chk for lastbar
def cup_hi = if cupbar3[-2] then max(high, max(high[-1], high[-2] ))
 else if cupbar3[-1] then cup_hi[1]
 else if cupbar3[0] then cup_hi[1]
 else na;

# lowest is bar2
def cup_lo = if cupbar3[-2] then low[-1]
 else if cupbar3[-1] then cup_lo[1]
 else if cupbar3[0] then cup_lo[1]
 else na;

# this causes error .  no recs in addcloud
#   addcloud(cup_hi*1.005, cup_lo*0.995, color.light_red, color.light_red);
# assign new vars , and ref them in addcloud.  then it works

# on 1 min, red shading is very tall, scale is down
 def vert3 = if chartmin <= 5 then 0.001 else 0.002;
 def vert2 = vert3;
#def vert2 = 0.002;
def cuphi2 = cup_hi * (1 + vert2);
def cuplo2 = cup_lo * (1 - vert2);
addcloud(cuphi2, cuplo2, color.red, color.red);

#addlabel(1, "vert2 " + vert2, color.pink);


# cup bubble above cup pattern, chk if cup bar3 exists
addchartbubble( cupbar3[-2], cuphi2,  "CUP", color.light_red);
# this will label a cup on last 3 bars.   but it wont be shaded red or have numbers 2 and 3



#----------------
# cup stats

def cupqty = if bn == 1 then 0 else if cupbar3 then cupqty[1] + 1 else cupqty[1];
def cupsellqty = if bn == 1 then 0
 else if isnan(cupsell_a) then cupsellqty[1]
 else if cupsell_a then cupsellqty[1] + 1
 else cupsellqty[1];
def cupsellper = round(100*cupsellqty/cupqty, 1);

addlabel(1, "Cups: " + cupqty + " , Sells: " + cupsellqty, color.light_red);
addlabel(1, "Cup sell: " + cupsellper + "%", color.light_red);

#---------------------------------

# cup , number the bars
# add numbers to the 3 bars. check if bar3 exists
def cupnum = if cupbar1 and cupbar3[-2] then 1
  else if cupbar2 and cupbar3[-1] then 2
  else if cupbar3 then 3
  else 0;

# cup bar1
plot cupnumz = if cupnum > 0 then cupnum else na;
cupnumz.setpaintingStrategy(PaintingStrategy.VALUES_below);
cupnumz.setdefaultcolor(color.white);
cupnumz.hidebubble();


#---------------------------------
# cup test stuff

#addverticalline(cupbar3[-1] , "   cup bar2", color.cyan);

input test5_cup = no;
addchartbubble(test5_cup, low*0.997,
"cup" + "\n" +
 bn + "\n" +
 upbar1bn + "  1\n" +
 upbar3bn + "  3\n" +
cupbar1_high + "  hi\n" +
cupbar1_low + "  lo\n" +
upbar3off3 + "\n" +
cupbar2_low + "\n" +
#sellzz + "\n" +
cupsell_price + "\n" +
cupbar3bn
, (if bn == upbar1bn then color.yellow else if bn == upbar3bn then color.cyan else color.gray), no);



input test6_cupnum = no;
addchartbubble(test6_cupnum, low*0.997,
cupbar1 + "\n" +
cupbar2 + "\n" +
cupbar3 + "\n" +
cupnum + "\n" +
high + "\n" +
low + "\n" +
cupbar2_low
, (if bn == upbar1bn then color.yellow else if bn == upbar3bn then color.cyan else color.gray), no);

#---------------------------------








#/////////////////////////////////////////
#/////////////////////////////////////////

# cap reversal pattern , buy




#/////////////////////////////////////////
#/////////////////////////////////////////





#==========================================
# test stuff


# up bar3 line stats
addchartbubble(0, low*0.994,
bn + "\n" +
up3bar_warnline + " w\n" +
up3bar_netline + " s\n" +
upsell + "\n" +
upstopb + "\n" +
upstop + "\n"
,color.cyan, no);


addchartbubble(0, high*1.003,
(high[0] >= getvalue(high, 1) and low[0] > getvalue(low, 1))
, color.cyan, yes);


addchartbubble(0 and isnetrng, low*0.995,
 bn + "\n" +
high + "\n" +
#jj + " jj2\n" +
#upbar1peakbn + "\n" +
 upbar1bn + " 1bn\n" +
#upbar1bn4 + " 4\n" +
# upbar2bn2 + " 2off\n" +
 upbar2off + " 2off\n" +
 upbar2off2 + " 2off2\n" +
 upbar2bn + " 2bn\n" +
# upbar1bn + " 1c"
 upbar3off + " 3off\n" +
 upbar3off2 + " 3off2\n" +
 upbar3bn + " 3bn\n"
, (if upbar2off > 0 then color.cyan else if upbar3off > 0 then color.magenta else color.gray), no);
#, color.cyan, no);

addchartbubble(0 and isnetrng, low*0.995,
 bn + "\n" +
 upbar1bn + "  1\n" +
 upbar2bn + "  2\n" +
 upbar3off + " 3off\n" +
 upbar3off2 + " 3off2\n" +
 upbar3bn + " 3\n"
, color.cyan, no);


#--------------------------------------


#plot x =
# x.setdefaultcolor(color.light_red);
#  Curve.._DASH: qty of dashes changes based on zoom level.
#  zoom in = many dashes, narrower than candle. zoom out = fewer, dashes, wider than candle
# x.SetStyle(Curve.MEDIUM_DASH);
# x.SetDefaultColor(Color.red);
# x.setlineweight(1);
# x.hidebubble();
# x.SetPaintingStrategy(PaintingStrategy.LINE);
#  Strategy.DASHES: 1 dash per candle, no matter the zoom level
# x.SetPaintingStrategy(PaintingStrategy.DASHES);

# x.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
# x.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
# x.SetPaintingStrategy(PaintingStrategy.POINTS);
# x.SetPaintingStrategy(PaintingStrategy.SQUARES);
# x.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#
look pretty good! i hope @barbaros or other great coder here will help you and help us! happy sunday to all
 

barbaros

Administrator
Staff member
There are so many failing signals. Also, when the 3bar line is breached, what happens when the price reverses? still paint the bars green?
LxMWqDs.png
 
All signals have false signals. This would be more for confirmation and deciding if you even want to take a trade. You might want to get long but price stays below 3ar net line so pass on trade. This is not really a signal or "trigger" type indicator but more of a confirming indicator.

When price CLOSES above 3bar net line you are now in bull mode taking long trades. It is a close, not a penetration of the 3bar net line. Everything else is just "pullback" unless you close below the 3bar net line, then you are in bear mode.
 
I want the bars to color green when they are in bullish mode. These bars can be below the 3bar line that triggered bullish mode, but still above where it would trigger 3bar line to be bearish mode. Vice versa is true for the bearish mode and I would like those bars colored red. Prolly best if the colors are changeable, but the defaults would be green and red. Hopefully that answers your question.
 
Last edited:
I'm guessing this is either not doable, or nobody finds it valuable enough to convert (or I haven't explained the concept well enough). Hopefully someone will have an epiphany or change their mind and see the value. Thanks in advance.
 
Last edited:
Top