Understanding Pine Script's plotshape() Function: A Comprehensive Guide
So you're working with Pine Script and want to add some visual flair to your charts? The plotshape()
function is probably going to become your best friend. It's basically a way to slap shapes onto your chart whenever something interesting happens - like when your moving averages cross over or when price hits a certain level.
What exactly is plotshape()
?
Think of plotshape()
as your chart's highlighter pen. It drops little shapes (arrows, triangles, circles, whatever) onto specific bars when your conditions are met. So instead of squinting at lines trying to figure out when something happened, you get clear visual markers that jump out at you.

The main things you can control
Here's what you can tweak when using plotshape()
:
- series: This is your "when" - the condition that decides if a shape shows up or not
- title: Just a name for your shape series (shows up in settings)
- location: Where the shape sits - above the bar, below it, wherever
- color: Pretty self-explanatory - what color you want it
- style: The actual shape - triangle, cross, diamond, you name it
- size: How big or small you want it
- offset: If you want to nudge it left or right a bit
- text and textcolor: Add some text next to your shape if you want
Why bother with shapes at all?
Honestly? Because staring at a bunch of lines gets old fast. When you've got clear visual signals popping up on your chart, you can spot patterns and setups way quicker. Plus, it just makes your indicators look more polished.
Let's see it in action
Here's a simple example that'll put a green triangle above bars when a fast moving average crosses above a slow one:
//@version=5
indicator("MA Crossover Signals", overlay=true)
fastMA = ta.sma(close, 9)
slowMA = ta.sma(close, 21)
bullishSignal = ta.crossover(fastMA, slowMA)
plotshape(bullishSignal, title="Buy Signal", location=location.abovebar, color=color.green, style=shape.triangleup, size=size.small)
Pretty straightforward, right? We calculate two moving averages, check when the fast one crosses above the slow one, then drop a green triangle there.
Some tricks I've picked up
- You can combine conditions with
and
andor
to get more specific about when shapes appear - The color doesn't have to be static - you can change it based on other conditions
- Play around with the offset if your shapes are getting crowded
- The text parameter is kind of limited (it needs to be a constant string), so if you want dynamic text, you'll need to use labels instead
Shape options you can use
Here are the shapes you can pick from:
Shape | What it looks like |
---|---|
shape.xcross | An X mark |
shape.arrowup | Arrow pointing up |
shape.arrowdown | Arrow pointing down |
shape.circle | A circle |
shape.square | A square |
shape.triangleup | Triangle pointing up |
shape.triangledown | Triangle pointing down |
shape.diamond | Diamond shape |
shape.flag | A little flag |
shape.labelup | Label that sits above |
shape.labeldown | Label that sits below |
Pick whatever makes sense for your strategy. I usually use triangles for entries and X marks for exits, but do whatever clicks for you.