The Ascending Triangle has a flat resistance level and a rising lower trendline. Buyers are willing to pay increasingly higher prices. When resistance finally breaks, the measured move equals the triangle's height at its widest point.
Three swing highs at 110 — a flat ceiling — and rising swing lows at 100, 104 and 107. Day 27 closes at 114, above the ceiling. The widest part is 110 − 100 = 10, so the target is 110 + 10 = 120.
The example data
The turning points the daily closes run through, in straight lines between them; high and low are half a point either side of each bar.
| Day | Close |
|---|---|
| 0 | 95 |
| 4 | 110 |
| 8 | 100 |
| 12 | 110 |
| 16 | 104 |
| 20 | 110 |
| 24 | 107 |
| 27 | 114 |
- The ceiling can hold; rising lows do not guarantee a break, and a close back under the ceiling after a break is a common failure.
- “Flat” needs a tolerance (1% here), and which triangles you find depends on it.
- Bulkowski’s counts show ascending triangles also break downward a meaningful share of the time.
def swings(s, n=3): # a swing high (low) is the extreme of the 2n+1 bars around it
w = s.rolling(2 * n + 1, center=True)
return s[s == w.max()], s[s == w.min()]
c = df['close']
highs, lows = swings(c)
top, rises = highs.iloc[-3:], lows.iloc[-3:]
flat_top = (top.max() - top.min()) / top.mean() < 0.01
rising = rises.is_monotonic_increasing
height = top.mean() - rises.iloc[0]
breakout = c.iloc[-1] > top.max()
target = top.mean() + heightAssumes import numpy as np, import pandas as pd, and a DataFrame df with columns open, high, low and close for the data above.
- Encyclopedia of Chart Patterns (2nd ed.), T. N. Bulkowski, Wiley, 2005 — success and failure rates from large counts of patterns
- Technical Analysis of Stock Trends, R. D. Edwards & J. Magee, 1948 (later editions revised by W. H. C. Bassetti)
Last reviewed October 2026 · How this site checks its content · Report a mistake