Pine Script visuals

Pine Script plotshape: Signals, Locations and Text Limits

plotshape() draws a built-in shape on bars selected by its series argument. For relative locations, pass a condition; for location.absolute, pass a numeric y-coordinate or na. Keep the call in global scope, use constant text, and treat offset as a visual shift. A marker does not create an alert: define an alert condition separately and create the running alert in TradingView.

Build a Pine Script marker

The arguments that control a signal marker

Only series is required. Named arguments make optional settings easier to read. A call returns void; it does not return a shape object that you can later move or delete. These are the main v6 controls:

  • Other parameters include editable for style settings and format/precision for numeric readouts. They do not change the event rule.
  • The v6 reference lists the complete signature. Prefer names when adapting examples with optional positional arguments.
ArgumentMeaningConstraint
seriesCondition, or y-coordinate with absolute placementUse a bool for relative placement and a number or na for absolute placement
style / locationBuilt-in shape and vertical positioning modeFor example, shape.triangleup and location.belowbar
offsetHorizontal displacement in barssimple int in v6; cannot change from bar to bar
text / titleVisible caption / output nameconst string; cannot contain a changing price
color / textcolorShape and caption colorsMay vary by bar
sizeShape sizeDoes not resize the accompanying text
show_last / displayRecent-bar window / output destinationsCan hide a valid signal without changing its condition
force_overlayDraw on the main chart from a separate script paneDoes not change the signal calculation

Complete v6 example: one event, two positions

This indicator marks a close crossing above an input level. The previous close must be at or below the level, and the current close must be strictly above it. It waits for the chart bar to close. A teal triangle uses relative placement; an orange circle uses a price coordinate two minimum ticks below the signal bar low. The level of 100 is an illustrative default: set it near the prices on your chart.

  • All plotshape() and alertcondition() calls are outside conditional blocks. The series arguments decide which bars qualify.
  • The Data Window outputs remain on the source bar even when the marker offset changes.
  • This is a plotting diagnostic. It submits no orders and does not test whether the event is profitable.
Paste the whole indicator into Pine Editor. Begin with Marker offset set to 0.pinescript
//@version=6
indicator("plotshape signal positions", overlay=true)

level = input.float(100.0, "Crossing level")
enabled = input.bool(true, "Enable signal")
markerOffset = input.int(0, "Marker offset", minval=-10, maxval=10)

hasPreviousClose = not na(close[1])
crossedUp = hasPreviousClose and close[1] <= level and close > level
signal = enabled and crossedUp and barstate.isconfirmed
markerPrice = signal ? low - 2 * syminfo.mintick : na

plot(level, title="Crossing level", color=color.gray)
plotshape(signal, title="Relative marker", style=shape.triangleup, location=location.belowbar, color=color.teal, offset=markerOffset, text="CROSS", textcolor=color.teal, size=size.small)
plotshape(markerPrice, title="Absolute marker", style=shape.circle, location=location.absolute, color=color.orange, offset=markerOffset, size=size.tiny)
plot(signal ? 1 : 0, title="Signal on source bar", display=display.data_window)
plot(markerPrice, title="Marker price on source bar", display=display.data_window)
alertcondition(signal, title="Confirmed cross above level", message="Confirmed cross above level on {{ticker}} at {{close}}")

Check the condition at its boundaries

These are hypothetical input cases for the example, not market observations. Assume level 100, Enable signal on, offset 0, and a closed bar unless a row says otherwise. An event needs both comparisons, so a bar remaining above 100 is not another crossing.

  • For historical bars, barstate.isconfirmed is true. On a live bar it becomes true on the closing update; intrabar threshold touches therefore do not qualify by themselves.
  • Removing barstate.isconfirmed allows shapes to appear and disappear during the open bar. Historical output does not preserve that sequence.
  • This confirmation applies to the chart timeframe. Adding request.security() data requires a separate review of that data; placing barstate.isconfirmed inside the request is not a confirmation method.
Previous closeCurrent close / stateExpected output
99101 / closedBoth shapes; signal readout 1
100101 / closedBoth shapes; equality is allowed on the previous bar
99100 / closedNo shapes; current equality does not qualify
101102 / closedNo shapes; price was already above the level
99101 / openNo shapes until the closing update
99101 intrabar, 99 at closeNo confirmed event and no final marker
Unavailable101 / first dataset barNo shapes; the previous-close guard fails
99101 / closed, signal disabledNo shapes and false alert condition

Separate vertical coordinates from horizontal offsets

With location.abovebar or location.belowbar, a true condition enables a marker near the bar. location.top and location.bottom place it near the pane boundary. With location.absolute, the first argument supplies the y-coordinate instead: use na to omit a point. A numeric zero is a coordinate in absolute mode, so do not use zero as its missing-value fallback.

  • An offset does not forecast a future event or make a signal available earlier. A negative offset can make a historical marker look earlier than the decision that produced it.
  • After shifting an absolute marker, its y-coordinate still comes from the source bar. It need not sit below the destination bar low.
  • When a point is missing, inspect its source-bar condition, coordinate, offset, Style visibility, display setting, show_last window and pane scale before changing the event rule.
Hypothetical setupCalculationExpected placement
Signal bar index 20; low 98; minimum tick 0.2598 - 2 × 0.25 = 97.50Orange circle at price 97.50
Same event; offset 020 + 0 = 20Shapes on the source bar
Same event; offset +320 + 3 = 23Shapes three bars right; circle still at 97.50
Same event; offset -220 - 2 = 18Shapes two bars left; event still known on bar 20
No eventmarkerPrice = naNo absolute circle

Fixed text, dynamic labels and local scope errors

The CROSS caption is the same on every qualifying bar because text requires a const string. A literal message can include line breaks. A changing close converted with str.tostring() is a series string, and an input.string() value is also too strong for this parameter. Use label.new() when a caption must include a changing price.

  • For two fixed messages, use two global plotshape calls with separate conditions and constant captions. Each call contributes to the plot-count budget.
  • For a scope error, calculate the condition or numeric coordinate in the conditional block, then pass the result to a global plotshape call. Do not wrap the plotting call itself in if, a loop or a user-defined function.
  • plotshape does not consume label IDs, but scripts have a limit of 64 plot counts. A call can consume more than one count when series colors are used; alertcondition also consumes a count.

Create the alert separately from the shapes

After adding the example to a chart, create a TradingView alert, select this indicator and Confirmed cross above level, then choose Once Per Bar Close. The alertcondition declaration supplies a selectable condition; it does not start a running alert. Historical shapes do not send retrospective notifications.

  • The alert uses signal on the source bar. Setting Marker offset to +3 does not delay that alert by three bars.
  • Changing plot style, location or display settings does not change the alert condition. Changing Enable signal does affect it because that input is part of signal.
  • TradingView stores a copy of the script, inputs and chart context when an alert is created. Recreate an existing alert after changes that it must use.

Give the coding agent a reproducible marker requirement

Send the existing script, Pine version, condition, expected source bar, y-position, caption and alert timing to Pineify. For this example, specify that 99 to 100 must not trigger, 100 to 101 must trigger only at close, and a visual offset must not move the alert event. Ask for the smallest correction, run syntax validation, then compare the output with the cases above in TradingView.

Where Pineify fits

Pine Script AI Coding Agent

Use Pineify to generate or revise Pine Script from your marker requirements. Supply the minimal reproduction and expected output, request a syntax check, and verify chart placement and alert behavior in TradingView.

Build a Pine Script marker

Frequently asked questions

Educational plotting example, not investment advice or a tested trading strategy. Syntax validation does not establish chart behavior, alert delivery or profitability.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.