this study is in response to this request
https://usethinkscript.com/threads/indicator-for-triangles.14372/
find 4 bar wedge pattern,
. peak, lower peak , valley, higher valley
. peaks and valleys defined by x bars on either side of a bar
. may have 2 in a row of same signal , doesn't force alternating signals
. may have 3 or more of 1 signal, during the period of the 2 other signals
. peaks and valleys don't have to be next to each other
. alert when 4th bar appears. different sounds, if a peak or valley
options
..choose a number to define peaks and valleys. default is 2 (does not include the current bar)
..draw cyan wedge (small arrows) on all peaks and valleys
..show a wedge bubble on bar 1 of the pattern
..show a gray shaded rectangle that covers the bars of the pattern
..show diagonal lines that connect, 2 peaks and 2 valleys
..show a gray shaded area, between the 2 diagonal lines
..can show an arrow on the last bar of pattern
notes,
..when a first peak and first valley exist, and the bars after them are within those price levels, it will start to define the pattern
....if the last pattern is near the last bars on the chart, it is possible for future bars to move outside the high , low limits, canceling the pattern.
..the last x bars on the chart won't be included in the pattern
....if length is 4, then the last (length-1), or 3, bars won't be included in the pattern
..valley diagonal line starts at a valley. it doesn't extend backwards to peak bar. same with cloud, so cloud will not cover first few bars
i left my debugging test codes in. not needed to use this study
rectangular cloud
diagonal lines, cloud
https://usethinkscript.com/threads/indicator-for-triangles.14372/
find 4 bar wedge pattern,
. peak, lower peak , valley, higher valley
. peaks and valleys defined by x bars on either side of a bar
. may have 2 in a row of same signal , doesn't force alternating signals
. may have 3 or more of 1 signal, during the period of the 2 other signals
. peaks and valleys don't have to be next to each other
. alert when 4th bar appears. different sounds, if a peak or valley
options
..choose a number to define peaks and valleys. default is 2 (does not include the current bar)
..draw cyan wedge (small arrows) on all peaks and valleys
..show a wedge bubble on bar 1 of the pattern
..show a gray shaded rectangle that covers the bars of the pattern
..show diagonal lines that connect, 2 peaks and 2 valleys
..show a gray shaded area, between the 2 diagonal lines
..can show an arrow on the last bar of pattern
notes,
..when a first peak and first valley exist, and the bars after them are within those price levels, it will start to define the pattern
....if the last pattern is near the last bars on the chart, it is possible for future bars to move outside the high , low limits, canceling the pattern.
..the last x bars on the chart won't be included in the pattern
....if length is 4, then the last (length-1), or 3, bars won't be included in the pattern
..valley diagonal line starts at a valley. it doesn't extend backwards to peak bar. same with cloud, so cloud will not cover first few bars
i left my debugging test codes in. not needed to use this study
Code:
# peaks_valleys_triangle_wedge_01
#------------------
# 23-02-09
# halcyonguy
#
# find 4 bar wedge pattern, starts with a peak
# peak, lower peak , valley, higher valley
# peaks and valleys defined by x bars on either side of a bar
# may have 2 in a row of same signal , doesn't force alternating signals
# may have 3 or more of 1 signal, during the period of the 2 other signals
#------------------
# https://usethinkscript.com/threads/indicator-for-triangles.14372/
# Indicator for Triangles
#------------------------
# template_peaks_valleys_off_robert_03_chg
#------------------------
# https://usethinkscript.com/threads/zigzag-high-low-with-supply-demand-zones-for-thinkorswim.172/#post-7048
# original code, bar qty includes current bar
# define swing low points , robert payne
#
# modifified by halcyonguy to ignore last bar , and bar qty does not include current bar
#------------------------
def bn = BarNumber();
def na = double.nan;
input peak_valley_bars = 2;
def length = peak_valley_bars;
def lastbn = HighestAll(if IsNaN(close) then 0 else bn);
def offset = Min(length - 1, lastbn - bn);
input ignore_last_bar = yes;
def ignorelast = if (ignore_last_bar and bn == lastbn) then 0 else 1;
#
# original robert code, bar qty includes current bar
#def peak = ignorelast and high > highest(high[1], length - 1) and high == GetValue(highest(high, length), -offset);
#def valley = ignorelast and low < Lowest(low[1], length - 1) and low == GetValue(Lowest(low, length), -offset);
#
# mod code , bar qty does not include current bar
#def peak = ignorelast and high > highest(high[1], length) and high > GetValue(highest(high, length), -(offset+1));
#def valley = ignorelast and low < Lowest(low[1], length) and low < GetValue(Lowest(low, length), -(offset+1));
#
# chg so 2+ price levels in a row won't be skipped. trigger on the last bar in set, >= prev bars
def peak = ignorelast and high >= highest(high[1], length) and high > GetValue(highest(high, length), -(offset+1));
def valley = ignorelast and low <= Lowest(low[1], length) and low < GetValue(Lowest(low, length), -(offset+1));
#addlabel(1, "peak/valley bars " + peak_valley_bars, color.yellow);
#-----------------------------
#-----------------------------
# find a peak
# look at future bars for next 3 signals
# valley, lower peak , higher valley
# does not force alternating signals
def peakbn = if peak then bn else 0;
def valleybn = if valley then bn else 0;
# loop length, qty bars to look for next peak/valley
def t = 100;
def temp1;
def temp2;
def bars1;
def bars2;
def bars3;
def peak1bn;
def peak2bn;
def valley1bn;
def valley2bn;
def wedge;
def lastpvbn;
def hislope;
def loslope;
if bn == 1 then {
temp1 = 0;
temp2 = 0;
bars1 = 0;
bars2 = 0;
bars3 = 0;
peak1bn = 0;
peak2bn = 0;
valley1bn = 0;
valley2bn = 0;
wedge = 0;
lastpvbn = 0;
hislope = 0;
loslope = 0;
} else if bn > lastpvbn[1] and !peak then {
# after a wedge reset values
temp1 = 0;
temp2 = 0;
bars1 = 0;
bars2 = 0;
bars3 = 0;
peak1bn = 0;
peak2bn = 0;
valley1bn = 0;
valley2bn = 0;
wedge = 0;
lastpvbn = 0;
hislope = 0;
loslope = 0;
} else if peak and getvalue(wedge, 1) == 0 then {
# check if already in a wedge before recalculating new values
# start with a peak
# look for next peak, get offset to it
bars1 = fold i1 = 1 to t
with p1 = 1
while getvalue(peak, -i1) == 0 and !isnan(getvalue(close, -i1))
do p1 + 1;
# is next peak lower than current peak?
temp1 = if isnan(getvalue(high, -bars1)) then 0
else if (bars1 > 0 and bars1 < t and getvalue(high, -bars1) < high) then 1
else 0;
peak1bn = if temp1 then bn else 0;
peak2bn = if temp1 then (bn + bars1) else 0;
#--------------------------
# find valley1
bars2 = fold i2 = 1 to t
with p2 = 1
while (!isnan(getvalue(close, -i2)) and getvalue(valley, -i2) == 0)
do p2 + 1;
# find valley2
bars3 = fold i3 = 1 to t
# with p3 = bars2 + 1
with p3 = 1
while (!isnan(getvalue(close, -(bars2 + i3))) and getvalue(valley, -(bars2 + i3)) == 0)
do p3 + 1;
# is 1st valley lower than 2nd valley?
temp2 = if (isnan(getvalue(low, -bars2)) or isnan(getvalue(low, -(bars2 + bars3)))) then 0
else if (bars2 > 0 and bars2 < t) and (getvalue(low, -bars2) < getvalue(low, -(bars2 + bars3))) then 1
else 0;
valley1bn = if temp2 then (bn + bars2) else 0;
valley2bn = if temp2 then (bn + bars2 + bars3) else 0;
#----------------------------
# do 2 peaks and 2 valleys form a wedge?
wedge = (temp1 and temp2);
# find last bn , pk or val. may have 2 in a row of same signal , not alternating. 1 side may have more than 2 signals
lastpvbn = max(peak2bn, valley2bn);
# calc slopes of diag lines, connecting peaks, and valleys
hislope = (getvalue(high, -bars1) - high)/bars1;
loslope = (getvalue(low, -(bars2 + bars3)) - getvalue(low, -bars2)) / bars3;
} else {
# during a wedge, keep values
temp1 = 0;
temp2 = 0;
bars1 = 0;
bars2 = 0;
bars3 = 0;
peak1bn = peak1bn[1];
peak2bn = peak2bn[1];
valley1bn = valley1bn[1];
valley2bn = valley2bn[1];
wedge = wedge[1];
lastpvbn = lastpvbn[1];
hislope = hislope[1];
loslope = loslope[1];
}
#--------------------------
def pv = (peak1bn == bn or peak2bn == bn or valley1bn == bn or valley2bn == bn);
input show_all_small_arrows_on_peaks_valleys = no;
def arr = if show_all_small_arrows_on_peaks_valleys then 1
else if (wedge and pv) then 1
else 0;
def vert = 0.002;
#plot zv = if show_peak_valley_arrows and valley then low*(1-vert) else na;
#zv.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
plot zv = if arr and valley then 1 else 0;
zv.SetPaintingStrategy(PaintingStrategy.BOOLEAN_WEDGE_down);
zv.SetDefaultColor(Color.cyan);
#zv.setlineweight(2);
zv.hidebubble();
#plot zp = if show_peak_valley_arrows and peak then high*(1+vert) else na;
#zp.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
plot zp = if arr and peak then 1 else 0;
zp.SetPaintingStrategy(PaintingStrategy.boolean_wedge_up);
zp.SetDefaultColor(Color.cyan);
#zp.setlineweight(2);
zp.hidebubble();
#-------------------------
input show_wedge_bubble = yes;
#addchartbubble(bubble1 and peak and wedge, high*1.001,
# adding , and wedge[1] == 0 , removes 2nd bubble
addchartbubble(show_wedge_bubble and peak and wedge and wedge[1] == 0, high*1.0004,
"wedge"
, color.yellow, yes);
#-------------------------
# draw a rectangular cloud over the wedge
def hi1 = if wedge and peak1bn == bn then high
# else if wedge then hi1[1]
else if bn <= lastpvbn then hi1[1]
else na;
def lo1 = if wedge and peak1bn == bn then getvalue(low, -bars2)
# else if wedge then lo1[1]
else if bn <= lastpvbn then lo1[1]
else na;
input show_rectangular_wedge_cloud = yes;
plot zh1 = if show_rectangular_wedge_cloud then hi1 else na;
zh1.SetDefaultColor(Color.white);
zh1.setlineweight(1);
zh1.hidebubble();
plot zl1 = if show_rectangular_wedge_cloud then lo1 else na;
zl1.SetDefaultColor(Color.white);
zl1.setlineweight(1);
zl1.hidebubble();
addcloud(zh1, zl1, color.gray);
#-------------------------
# diag lines , 2 peaks, 2 valleys
input show_diagonal_lines = no;
def hiline = if wedge and peak1bn == bn then high
# else if wedge then hiline[1] + hislope
else if bn <= lastpvbn then hiline[1] + hislope
else na;
def loline = if wedge and valley1bn == bn then low
# else if wedge then loline[1] + loslope
else if bn <= lastpvbn then loline[1] + loslope
else na;
plot zhiline = if show_diagonal_lines and wedge then hiline else na;
zhiline.SetDefaultColor(Color.white);
zhiline.setlineweight(1);
zhiline.hidebubble();
plot zloline = if show_diagonal_lines and wedge then loline else na;
zloline.SetDefaultColor(Color.white);
zloline.setlineweight(1);
zloline.hidebubble();
input show_wedge_cloud = no;
def zhi2 = if show_wedge_cloud then zhiline else na;
addcloud(zhi2, zloline, color.gray, color.red);
input show_arrow_on_last_bar = no;
plot pattern_end = if show_arrow_on_last_bar and valley2bn == bn then low else na;
pattern_end.SetPaintingStrategy(PaintingStrategy.arrow_up);
pattern_end.SetDefaultColor(Color.cyan);
pattern_end.setlineweight(2);
pattern_end.hidebubble();
#-------------------
# alerts
# Sound.Ding , higher pitch , up sound
# Sound.Bell , lower pitch , down sound
def upalert = (bn == valley2bn);
def dwnalert = (bn == peak2bn);
alert(upalert, "valley" ,alert.BAR, sound.DING);
alert(dwnalert, "peak" ,alert.BAR, sound.bell);
#-------------------
#------------------------------------------
# test stuff
input ooooooooooo = 0;
input test1_bubbles_all_bars = no;
input test2_bubbles_just_peak_valley = no;
def t1 = if test1_bubbles_all_bars then 1
else if test2_bubbles_just_peak_valley then (peak or valley)
else 0;
addchartbubble(t1, low*0.995,
bn + "\n" +
#low + "\n" +
#peak + " P\n" +
bars1 + " b1\n" +
peak1bn + " p1\n" +
peak2bn + " p2\n\n" +
bars2 + " b2\n" +
bars3 + " b3\n" +
valley1bn + " v1\n" +
valley2bn + " v2\n" +
# temp1 + " t1\n" +
# temp2 + " t2\n" +
wedge + " w\n" +
lastpvbn + " last\n" +
hislope + " hi\n" +
loslope + " lo"
, (if wedge then color.yellow else color.gray), no);
#, color.yellow, no);
input test2_prices = no;
addchartbubble(test2_prices, low*0.999,
bn + "\n" +
high + " hi\n" +
low + " lo"
, (if wedge then color.yellow else color.gray), no);
#
rectangular cloud
diagonal lines, cloud