Pine Script plotshape(): mark signals on your chart
A rule is easier to judge when you can see it. plotshape() puts a small mark on every candle where your condition happens, so you can scroll back and check it.
What plotshape() does
plotshape() draws a small shape on the chart. An arrow, a triangle, a circle or a label.
You give it a condition. On every candle where the condition is true, a shape appears. Where it's false, nothing.
That's the fastest way to see a rule. Scroll back through a year of candles and you'll know in a minute if it marks what you meant. New to Pine Script? Start with Pine Script for beginners.
A first example
This indicator marks every candle that closes above or below a 20-candle average:
//@version=6
indicator("Closes past the average", overlay=true)
length = input.int(20, "Length", minval=1)
avg = ta.sma(close, length)
plot(avg, "Average", color=color.gray)
crossUp = ta.crossover(close, avg)
crossDown = ta.crossunder(close, avg)
plotshape(crossUp, "Closed above", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small)
plotshape(crossDown, "Closed below", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.small)
Line by line:
- Line 1 says this is Pine Script version 6.
- Line 2 names the indicator and draws it on the price chart.
- Line 3 makes the length a setting. See Pine Script inputs.
- Line 4 works out the average of the last 20 closes.
- Line 5 draws it in gray.
- Line 6 is true when the close crosses from below the average to above it.
- Line 7 is true when the close crosses from above to below.
- Line 8 draws a small green triangle under the candle when line 6 is true.
- Line 9 draws a small red triangle above the candle when line 7 is true.
Notice these use close. A candle only counts once its body closes past the line. That's the same rule we use for any level: a Wick poking through doesn't count. More on that in breakout vs fakeout.
The parts of plotshape()
| Part | What it does | Example |
|---|---|---|
| series (first) | The condition. Shape shows when true | crossUp |
| title | The name in the settings | "Closed above" |
| style | Which shape | shape.triangleup |
| location | Where it sits | location.belowbar |
| color | The shape's color | color.green |
| size | How big | size.small |
| text | Words next to the shape | "Up" |
| textcolor | The color of those words | color.white |
Shapes you can pick
- shape.triangleup and shape.triangledown
- shape.arrowup and shape.arrowdown
- shape.labelup and shape.labeldown (a small tag that can hold text)
- shape.circle, shape.square, shape.diamond
- shape.cross, shape.xcross, shape.flag
Where it sits
- location.abovebar sits just above the candle.
- location.belowbar sits just below it.
- location.top and location.bottom sit at the top or bottom edge of the chart.
- location.absolute sits at a price you choose. Here the first value must be a price, not true or false.
Sizes run size.tiny, size.small, size.normal, size.large, size.huge, plus size.auto.
Adding text
A label shape can carry a short word:
plotshape(crossUp, "Up label", style=shape.labelup, location=location.belowbar, color=color.green, text="Up", textcolor=color.white)
- shape.labelup is a tag that points up at the candle.
- text="Up" is the word inside it.
- textcolor sets the word's color.
One limit: the text must be fixed. It can't show a changing number like the price. For that, Pine Script has label.new(), which is a step up.
Marking a simple candle pattern
plotshape() works for any true-or-false rule. This marks a candle that closes above the high of the candle before it:
closeAboveLastHigh = close > high[1]
plotshape(closeAboveLastHigh, "Close above last high", style=shape.circle, location=location.belowbar, color=color.blue, size=size.tiny)
- high[1] means "the high of the candle one step back". The number in square brackets counts candles back in time.
- The circle shows under every candle that closed above the last candle's high.
The live-candle catch
On a candle that's still forming, the close keeps changing. A mark can appear, then vanish before the candle ends. When the candle closes, only the final answer stays.
This is one kind of repainting: the live chart showed something history won't. To only mark finished candles, add one check:
plotshape(crossUp and barstate.isconfirmed, "Closed above", style=shape.triangleup, location=location.belowbar, color=color.green)
barstate.isconfirmed is true only when a candle has closed. On past candles it's always true, so history looks the same.
A mark is not a signal to act. A triangle shows that your condition happened. It can't tell you if the bigger chart agrees, where your stop goes or how big to trade.
Use it to judge your rule honestly
Marks make it easy to see what you hoped for. Try to see what's really there:
- Add your script to a chart and scroll back a few months.
- Count the marks. Then count how many came right before a clean move, and how many came before nothing.
- Repeat on 2 or 3 other charts. A rule that only looks good on one chart is a warning sign.
- Then step through it candle by candle with bar replay, so you can't see what came next.
If you'd rather not code your levels, the free StructureX chart tool marks the last places price turned around for you.
plotshape() and alerts pair well. Use the same condition for both. If the marks look right, the alerts will fire in the right places. See Pine Script alerts.
Learning from a real script
A finished indicator shows how marks, lines and settings work together without cluttering the chart.
Our course includes the full source code of the StructureX chart tool, to learn from and customize. It's source code, not a ready-made trading bot.
Common mistakes
- Using location.absolute with a true-or-false value. It needs a price.
- Changing text on every candle. plotshape() text must be fixed. Use label.new() instead.
- Marking the live candle. Add barstate.isconfirmed if you only want closed candles.
- Too many marks. If half the candles are marked, the rule isn't saying much.
- Judging only the good examples. Count every mark, not just the ones you like.
Questions
What is the difference between plotshape and plotchar?
plotshape() draws built-in shapes like triangles and labels. plotchar() draws any single character, like a letter or symbol. Both work the same way.
How do I add text to plotshape in Pine Script?
Add text="Your word" and, if you like, textcolor. The text must be fixed. For changing text, use label.new().
Why does my plotshape disappear?
On a live candle, the condition can be true for a moment, then false by the close. Add barstate.isconfirmed to only mark closed candles.
Can plotshape put a shape at an exact price?
Yes. Use location.absolute and give a price as the first value, instead of a true-or-false condition.
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: