# 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);
#