Pine Script Visuals

Pine Script plotchar: Signature, Parameters, and Examples

plotchar() plots a single character on selected bars. Its first argument, series, supplies the condition or, with location.absolute, the vertical coordinate. Use char for the glyph, text for a fixed message, and label.new() for text that changes with each bar. Keep plotchar() calls in global scope and put the condition in series. The documented v5 signature has 13 parameters; the current v6 signature adds format and precision before force_overlay.

Add Markers with AI

The v5 and v6 signatures

The v5 documentation lists plotchar(series, title, char, location, color, offset, text, textcolor, editable, size, show_last, display, force_overlay). The current v6 documentation lists plotchar(series, title, char, location, color, offset, text, textcolor, editable, size, show_last, display, format, precision, force_overlay). Both return void. Older examples that stop at display remain useful calls, but do not show every currently documented parameter. Use names for later arguments, especially when migrating a positional force_overlay argument.

ParameterPurpose and constraint
seriesRequired bool or numeric series. Use a boolean for conditional markers and a numeric value for location.absolute.
titleA const string naming the output in settings and value readouts.
charAn input string for the single character, such as "B" or "▲". Use an empty string to hide the glyph.
locationabovebar, belowbar, top, bottom, or absolute from the location namespace.
colorThe glyph color; a series color can change on each bar.
offsetHorizontal shift in bars. In v6 it must be simple or weaker, so it cannot vary by bar.
textA const string for accompanying text. It cannot contain a changing price or input.string() value.
textcolorThe accompanying text color; it may vary by bar.
editableWhether users can edit the output style in the settings.
sizeThe character size, using size.auto, tiny, small, normal, large, or huge.
show_lastAn input integer restricting output to the most recent number of bars.
displayOutput destinations such as display.pane, display.data_window, display.status_line, display.all, or display.none.
format and precisionCurrent v6 parameters controlling numeric value formatting, rather than character content.
force_overlayWhen true, places the visual on the main chart even when the script occupies another pane.
Complete v5 indicator: positional and named arguments on the same conditionpinescript
//@version=5
indicator("plotchar arguments", overlay = true)

average = ta.sma(close, 20)
crossedAbove = ta.crossover(close, average)
confirmedCross = crossedAbove and barstate.isconfirmed

plotchar(confirmedCross, "Positional marker", "B", location.belowbar, color.teal)
plotchar(series = confirmedCross, title = "Named marker", char = "▲", location = location.abovebar, color = color.teal, text = "CROSS", textcolor = color.teal)
plot(average, "SMA", color = color.gray)

One character, fixed text, or a dynamic label

Supply a single character to char. Do not rely on a multi-character string being truncated, or assume every composed emoji will render as a single glyph. For words, use the text parameter. That text must be known at compilation; str.tostring(close) produces a series string and belongs in label.new(). plotshape() also supports fixed text, with a built-in shape in place of a character.

NeedChooseConstraint
A letter, digit, or Unicode markerplotchar()The character cannot change with a series string. Use separate conditional calls for different characters.
An arrow, circle, or triangle from the shape namespaceplotshape()The style is a built-in shape; accompanying text is still constant.
The same word beside every signalThe text argument on either plotting functionUse fixed text such as "CROSS".
A price or calculated value written beside a barlabel.new()Accepts a series string; label objects have their own count limit.
Complete v6 indicator: fixed plot text and a changing price labelpinescript
//@version=6
indicator("Fixed text and dynamic labels", overlay = true, max_labels_count = 50)

average = ta.sma(close, 20)
crossedAbove = ta.crossover(close, average)
trigger = crossedAbove and barstate.isconfirmed

plotchar(trigger, title = "Fixed annotation", char = "B", location = location.belowbar, color = color.teal, text = "CROSS", textcolor = color.teal)
if trigger
    label.new(bar_index, high, "Close: " + str.tostring(close, format.mintick), style = label.style_label_down, textcolor = color.white)
plot(average, "SMA", color = color.gray)

Conditional markers must remain in global scope

A plotchar() call cannot sit inside an if block, loop, or user-defined function. Calculate the condition first, then pass it to a global call. If different bars need different letters or digits, create one call per fixed character. These calls consume plot counts even when their conditions are false. The example classifies the relation between two averages; it does not infer a profitable trading regime.

Complete v6 indicator: two fixed characters selected by series conditionspinescript
//@version=6
indicator("Average relation markers", overlay = true)

showMarkers = input.bool(true, "Show markers")
fast = ta.ema(close, 9)
slow = ta.ema(close, 21)
above = fast > slow
below = fast < slow

plotchar(showMarkers and barstate.isconfirmed and above, title = "Fast above slow", char = "A", location = location.bottom, color = color.teal)
plotchar(showMarkers and barstate.isconfirmed and below, title = "Fast below slow", char = "B", location = location.bottom, color = color.orange)
plot(fast, "Fast EMA", color = color.teal)
plot(slow, "Slow EMA", color = color.orange)

Location, numeric series, and the Data Window

For relative locations, a boolean series controls whether a marker appears; numeric zero or na suppresses it, while other numeric values enable it. With location.absolute, the numeric series is the y-coordinate instead. Use na for bars with no absolute marker. Separately, display.data_window exposes the numeric series in the Data Window without drawing the character in the pane. An offset only moves the drawing horizontally; it does not change when the condition was calculated.

  • The red x is a per-bar example coordinate. It is not a trailing-stop algorithm or an order.
  • The confirmed-bar condition waits for the chart bar to close. Removing it allows the current marker to change while the bar updates.
  • Move the cursor over different bars and inspect ATR value in the Data Window. Chart rendering and UI placement still need checking in TradingView.
SettingEffect
location.abovebar / location.belowbarPositions the character above or below its bar.
location.top / location.bottomPositions the character near the top or bottom of the script pane. This does not create a separate debug pane.
location.absoluteUses the numeric series as the vertical coordinate in the destination pane.
display.data_windowShows the numeric value in the Data Window, with no pane marker.
display.noneHides the output; it does not remove the call from the plot-count budget.
Complete v6 indicator: absolute marker and Data Window diagnosticspinescript
//@version=6
indicator("plotchar numeric diagnostics", overlay = true)

average = ta.sma(close, 20)
atr = ta.atr(14)
showLevel = close > average and barstate.isconfirmed
illustrativeLevel = showLevel ? low - 2.0 * atr : na

plotchar(illustrativeLevel, title = "Illustrative level", char = "x", location = location.absolute, color = color.red)
plotchar(atr, title = "ATR value", char = "", location = location.top, display = display.data_window, format = format.price, precision = 4)
plot(average, "SMA", color = color.gray)

Limits and missing-marker checks

plotchar() and plotshape() do not create label objects, but both consume the shared plot-count budget. A call can use additional counts when colors vary by bar. Labels default to roughly 50 displayed objects and can be configured up to 500; older labels are removed as the limit is reached. Plot-based markers can cover the available dataset, which is not unlimited history.

  • Check the condition on the selected bar. For absolute placement, check that the coordinate is numeric rather than na.
  • Check display, show_last, the Style tab, and whether the script is in the main chart or another pane.
  • Check for an empty char, a transparent color, or an absolute coordinate outside the visible scale.
  • If a v5 script uses a series offset, replace it with a stable value before migrating to v6. v5 used only the last calculated offset for the whole output.
Where Pineify fits

Pine Script AI Coding Agent

Ask Pineify to add fixed signal markers or dynamic labels to your script. Specify the condition, location, text, and bar-close behavior, then request a syntax check and review the output on a chart.

Add Markers with AI

Frequently asked questions

These examples explain chart annotations and diagnostics. They are not trading recommendations or tested strategies. Syntax validation does not establish profitable signals or correct chart placement.

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.