This indicator is an automatic detector of ascending triangles (flat top, rising lows) and descending triangles (flat bottom, falling highs). Every valid figure is drawn directly on the chart as a coloured triangle joining its three vertices, with a dotted projection line marking the level where the breakout is expected.
A triangle is, by definition, a figure with one structural extreme (the major pivot) and several intermediate extremes that converge towards it. The indicator captures this with two independent lookback windows:
On each bar, the script records every new pivot of each type into four parallel arrays — two for the major scale ($level3DN, $level3UP) and two for the minor scale ($level1DN, $level1UP) — together with their bar indices. Four counters (t3, z3, t1, z1) keep track of the last index filled in each array.
The actual triangle search runs only on islastbarupdate, which keeps the chart clean and the indicator fast even on thousands of bars.
For each major pivot the script walks the minor-pivot arrays with two nested for … next loops and a break on the first match. Each loop sets a semafor flag confirming that:
When both flags are set and the geometry is consistent (x3 < x2 and y3 > y2 for ascending; x3 < x2 and y3 < y2 for descending), the figure is drawn.
Each detected triangle is drawn as three connected segments plus three labelled vertices:
| Vertex | Meaning | Colour |
|---|---|---|
| Point 1 (V1) | Major pivot (apex of the converging side) | green (ascending) / blue (descending) |
| Point 2 (V2) | Intermediate pivot on the converging side | black |
| Point 3 (V3) | Intermediate pivot on the flat side | red |
A dotted projection line is drawn from V3, extending the flat side a few bars into the future. This is the level the trader watches for the breakout — a close beyond it is the canonical entry trigger.
The indicator is intentionally non-directional: it detects the figure but does not generate buy or sell signals. The user decides whether to fade the flat side (mean-reversion bias) or trade the breakout (continuation bias) according to context.
| Parameter | Default | Description |
|---|---|---|
| `Period3` | 36 | Major lookback — defines the dominant pivot |
| `Period1` | 13 | Minor lookback — defines the intermediate pivots |
The 36 / 13 ratio (roughly 2.7:1). Increasing both proportionally produces fewer but larger figures; reducing Period1 alone makes the detector more sensitive to minor swings.
A few decisions worth flagging for anyone reading the source:
//------------------------------------------
//PRC_Triangles
//version = 0
//17.06.24
//Iván González @ www.prorealcode.com
//Traducido de MQ4
//Sharing ProRealTime knowledge
//------------------------------------------
Period3=36
Period1=13
//------------------------------------------
lowestlow3=lowest[Period3](low)
highesthigh3=highest[Period3](high)
if low=lowestlow3 then
$level3DN[t3+1]=Low
$level3DNx[t3+1]=barindex
t3=t3+1
endif
if high=highesthigh3 then
$level3UP[z3+1]=high
$level3UPx[z3+1]=barindex
z3=z3+1
endif
lowestlow1=lowest[Period1](low)
highesthigh1=highest[Period1](high)
if low=lowestlow1 then
$level1DN[t1+1]=Low
$level1DNx[t1+1]=barindex
t1=t1+1
endif
if high=highesthigh1 then
$level1UP[z1+1]=high
$level1UPx[z1+1]=barindex
z1=z1+1
endif
//-------------------------------------------------//
if islastbarupdate then
//----triangulo ascendente
for i=t3 downto 0 do
xx1=0
yy1=0
xx2=0
yy2=0
xx3=0
yy3=0
semafor1d=0
semafor1u=0
for j=t1 downto 0 do
if $level3DNx[i]<$level1DNx[j] and $level3DNx[i]>=$level1DNx[max(0,j-1)] and $level3DN[i] < $level1DN[j] then
semafor1d=1
xx2=$level1DNx[j]
yy2=$level1DN[j]
break
else
semafor1d=0
endif
next
for k=t1 downto 0 do
if $level3DNx[i]<$level1UPx[k] and $level3DNx[i]>=$level1UPx[max(0,k-1)] and $level3UP[i]<$level1UP[k] then
semafor1u=1
xx1=$level3DNx[i]
yy1=$level3DN[i]
xx3=$level1UPx[k]
yy3=$level1UP[k]
break
else
semafor1u=0
endif
next
if semafor1d and semafor1u and xx3<xx2 and yy3>yy2 and yy1<>0 then
drawtriangle(xx1,yy1,xx2,yy2,xx3,yy3)coloured("purple")style(line,2)
drawpoint(xx2,yy2,2)coloured("black")
drawpoint(xx3,yy3,2)coloured("red")
drawpoint(xx1,yy1,3)coloured("green")
drawsegment(xx3,yy3,xx3+abs(xx2-xx3)+5,yy3)coloured("red")style(dottedline)
endif
next
//----triangulo descendente
for i=z3 downto 0 do
x1=0
y1=0
x2=0
y2=0
x3=0
y3=0
semafor1d=0
semafor1u=0
for j=z1 downto 0 do
if $level3UPx[i]<$level1UPx[j] and $level3UPx[i]>=$level1UPx[max(0,j-1)] and $level3UP[i]> $level1UP[j] then
semafor1d=1
x2=$level1UPx[j]
y2=$level1UP[j]
break
else
semafor1d=0
endif
next
for k=t1 downto 0 do
if $level3UPx[i]<$level1DNx[k] and $level3UPx[i]>=$level1DNx[max(0,k-1)] and $level3UP[i]>$level1DN[k] then
semafor1u=1
x1=$level3UPx[i]
y1=$level3UP[i]
x3=$level1DNx[k]
y3=$level1DN[k]
break
else
semafor1u=0
endif
next
if semafor1d and semafor1u and x3<x2 and y3 < y2 and y1<>0 then
drawtriangle(x1,y1,x2,y2,x3,y3)coloured("blue")style(line,2)
drawpoint(x2,y2,2)coloured("black")
drawpoint(x3,y3,2)coloured("red")
drawpoint(x1,y1,3)coloured("blue")
drawsegment(x3,y3,x3+abs(x2-x3)+5,y3)coloured("blue")style(dottedline)
endif
next
endif
return