Pine Script swing highs and lows: find the turning points with code
The last places price turned around are the backbone of a chart. Pine Script can find them for you. But there's one delay built into every turning point, and it changes how you should read the chart.
What a swing high and a swing low are
A swing high is a candle whose high is higher than the candles on both sides of it. It's a place price turned down.
A swing low is the opposite: a low that's lower than its neighbours. A place price turned up.
We call them turning points. They're how we read a Trend: higher highs and higher lows mean up, lower highs and lower lows mean down. More in higher highs and higher lows and the glossary entry for Swing high and swing low.
New to Pine Script? Start with Pine Script for beginners.
The 2 tools: ta.pivothigh() and ta.pivotlow()
Pine Script calls turning points pivots:
- ta.pivothigh(high, 5, 5) looks for a high with 5 lower highs to its left and 5 to its right.
- ta.pivotlow(low, 5, 5) looks for a low with 5 higher lows on each side.
When it finds one, it gives you the price. On every other candle, it gives na (nothing).
The 2 numbers set how big a turn must be. Small numbers find many small turns. Bigger numbers find fewer, bigger ones.
Example 1: mark them
//@version=6
indicator("Swing highs and lows", overlay=true)
left = input.int(5, "Candles to the left", minval=1)
right = input.int(5, "Candles to the right", minval=1)
ph = ta.pivothigh(high, left, right)
pl = ta.pivotlow(low, left, right)
plotshape(not na(ph), "Swing high", style=shape.triangledown, location=location.abovebar, color=color.red, offset=-right)
plotshape(not na(pl), "Swing low", style=shape.triangleup, location=location.belowbar, color=color.green, offset=-right)
Line by line:
- Line 1 says this is Pine Script version 6.
- Line 2 names the script and puts it on the price chart.
- Lines 3 and 4 make the 2 sizes settings. See Pine Script inputs.
- Line 5 looks for a swing high. It's a price when one is found, na otherwise.
- Line 6 does the same for swing lows.
- Line 7 draws a red triangle above each swing high. not na(ph) means "a swing high was found here".
- Line 8 draws a green triangle below each swing low.
The key part is offset=-right. Read on.
The delay you must understand
Think about what "5 lower highs to the right" means. Pine Script can't know them until those 5 candles have closed.
So a swing high is only confirmed 5 candles after it happened. ta.pivothigh() gives its answer on that later candle.
offset=-right then draws the mark 5 candles back, on the real turning point. That looks right. But it hides the delay.
Scroll back on the chart, and every turn seems marked the moment it happened. Live, you'd have seen nothing until 5 candles later. That gap is why turning-point charts look smarter in hindsight than they felt in real time.
Rule for reading pivot marks: the turn is real, but you only knew about it right candles later. When you judge a setup on a past chart, count from the confirmation candle, not the triangle.
Try it: remove offset=-right from both lines and save. Each triangle jumps forward to the candle where it was actually confirmed. That's where you'd have seen it.
Example 2: label higher highs and lower highs
Now let's compare each swing high with the one before it:
//@version=6
indicator("Higher or lower highs", overlay=true, max_labels_count=200)
right = input.int(5, "Candles each side", minval=1)
ph = ta.pivothigh(high, right, right)
var float lastHigh = na
if not na(ph)
tag = na(lastHigh) ? "H" : ph > lastHigh ? "HH" : "LH"
label.new(bar_index - right, ph, tag, style=label.style_label_down, color=color.new(color.red, 70), textcolor=color.white, size=size.small)
lastHigh := ph
breakUp = ta.crossover(close, lastHigh)
plotshape(breakUp and barstate.isconfirmed, "Closed above last high", style=shape.circle, location=location.belowbar, color=color.green, size=size.tiny)
Every line, in plain words
- Line 3 uses one setting for both sides, to keep it simple.
- Line 4 finds swing highs.
- Line 5 makes a box that remembers the last swing high. var keeps it from candle to candle.
- Line 6 says "when a new swing high is confirmed…"
- Line 7 picks a tag. Read it as: if there's no earlier high, say "H". Otherwise, if this one is higher, "HH" (higher high). If not, "LH" (lower high).
- Line 8 puts the tag on the real turning point: bar_index - right is the candle that many steps back. Labels are covered in Pine Script labels and lines.
- Line 9 saves this high for next time.
- Line 10 is true when a candle closes above the last swing high.
- Line 11 draws a small green dot under that candle, on closed candles only.
Line 10 uses close, not high. That's our body-close rule: a Wick poking above the last high doesn't count. Only a candle closing past it does. See breakout vs fakeout.
Copy lines 4 to 9 with pivotlow, low and "HL" / "LL" to label the lows too.
Picking the size
| Setting | What you'll see | Good for |
|---|---|---|
| 2–3 | Many small turns, lots of noise | Studying fast intraday charts |
| 5 | A balanced middle | A first try on most charts |
| 10+ | Few, big turns, long delay | The bigger picture |
Bigger settings mean a longer delay. With 10, a turn is confirmed 10 candles later. There's always a trade-off between seeing a turn early and being sure it was one.
If you'd rather not code this, the free StructureX chart tool marks the turning points for you, and it works in the TradingView phone app.
Try it today
- Paste Example 2 into the Pine Editor on a computer. Save and add it to a daily chart.
- Read the tags left to right. Where did "HH" turn into "LH"? That's often where an uptrend paused.
- Open bar replay and step forward one candle at a time. Note how many candles pass before each tag appears.
- Log 10 of them: the turn, the confirmation candle, and what price did next.
Use a few charts. A setting that looks perfect on one chart may look messy on the next. Check 3 before you settle.
Learning from a real script
Turning points are the core of our chart tool. Our course includes the full source code of the StructureX chart tool, so you can see how it finds and labels them, and change it. It's source code, not a ready-made trading bot.
Common mistakes
- Forgetting the delay. The mark sits on the turn, but it was only known later.
- Judging setups from the triangle. Count from the confirmation candle.
- Treating a high wick as a break. Use the close.
- Settings so small that every wiggle is a turn. Start at 5.
- Comparing to na. Check na(lastHigh) first, as line 7 does.
Questions
How do I find swing highs and lows in Pine Script?
Use ta.pivothigh(high, left, right) and ta.pivotlow(low, left, right). They give a price on a turning point and na everywhere else.
Does ta.pivothigh repaint?
It doesn't change once confirmed, but it's confirmed late: right candles after the turn. Drawing it with offset=-right puts the mark on the turn, which makes past charts look earlier than they were.
What do leftbars and rightbars mean in ta.pivothigh?
How many candles on each side must have lower highs. Bigger numbers find bigger turns, with a longer confirmation delay.
How do I label higher highs in Pine Script?
Save the last swing high with var, compare each new one to it, and use label.new() to write "HH" or "LH" on the turning point.
Want the next step? We'll walk you through it.
Four free lessons by email, one every few days — each with a 10-minute exercise on a real chart.
Send Me the Free Lessons 4 short emails · No spam · Unsubscribe anytimeOr see the whole method, step by step:
See What’s Inside the Course Try everything free first. Decide when you're ready. · Open the free chart tool (works in the TradingView phone app)One chart idea a day, in plain English. Follow along: