Skip to content

Pine compatibility ​

Will a script you wrote for TradingView run here, and give the same numbers? A Pine Script v6 text runs unchanged, and where TradingView's output has been captured the engine is held to it value for value. The tables below list every place we know of where it still reads differently, which ones are on purpose, and what TradingView refuses that runs here.

pine
//@version=6
indicator("Runs the same on both", overlay = true)
int len = input.int(20, "Length", minval = 1)
float basis = ta.sma(close, len)
float dev = 2 * ta.stdev(close, len)
plot(basis, "Basis", color.gray)
// fills, colours and bands read the same values on both platforms
p1 = plot(basis + dev, "Upper", color.teal)
p2 = plot(basis - dev, "Lower", color.teal)
fill(p1, p2, color.new(color.teal, 90))

Which version runs ​

Every script runs on Pine Script v6's rules. No //@version line is read: a Pine text keeps //@version=6 because TradingView compiles by it, and an older version's script runs as if it were v6, so a v5 script that relies on v5 behaviour reads v6's. Earlier versions won't be supported.

A text that uses nothing this terminal adds is Pine Script, and runs as TradingView runs it. A text that uses any addition is AmenoScript, which runs leak-safe and refuses what could read past a bar: Pine or AmenoScript says how the engine tells the two apart and what changes. Strict Pine refuses every addition with Pine v6 strict (line N), and the list of additions includes syntax TradingView rejects, such as x == na and a literal / 0, which run here as AmenoScript.

Where it matches, and how that's held ​

TradingView is the ground truth here, not our own tests. Where the two differ, the engine is fixed and the test with it, unless a row below says the difference is meant. These parts are held to output captured from TradingView, on all of the terminal's engines:

AreaHeld to
barstate.* on history, the forming bar and live updatesA live probe on a one-minute chart
ta.* called in a branch, and over na gapsPer-family probes, every value
math.exp, log, log10, pow and the trig functionsPorts of the routines TradingView itself runs. Every exp, log and log10 value read off TradingView matches to the bit
Constant folding: 0.1 + 0.2 reads 0.3, 2.0 / 15 reads 0.1333333333333333The compiler's own folded values
Compares within 1e-10, x / 0, infinities in each na test and in str.tostringProbes of each gate
color.from_gradient, table cells and their defaultsProbes and captured tables
Session schedules, holidays and early closes for captured symbolsCaptured time_close rows
The strategy emulator: fills, exits, margin, the reportCaptured trade lists and reports
The built-in indicatorsWhat TradingView draws for each on INDEX:BTCUSD daily, or its manual where nothing was captured

Different on purpose ​

These read differently by design, and stay that way:

WhatTradingViewHereWhy
A request for a symbol that can't be loadedStops the script, unless ignore_invalid_symbol = trueReads na, with a warningA feed that failed isn't an error in your script
Another symbol's bar in bar replayHands over the whole bar while the chart's bar formsShows only what was known at the replay's momentThe whole bar would leak the future
varip in bar replayKeeps its value across stepsActs as var, so a step draws what a jump to the same time drawsA replay reads the same however you reach a moment
A company's quarter and a CPI print in request.financial and request.economicDated at the quarter's end or the month after, in today's revisionsDated at the filing and at the releaseThe earlier date would read a value before it was public
alert() and alertcondition()Fire from an alert set on the chartFire only from a rule in the Alerts pane, never from a chart's run (Alerts)A rule runs on closed bars on the terminal's server, whether or not a page is open
An AmenoScript textNo such dialectRuns leak-safe: lookahead_on, varip, calc_on_every_tick and the rest are refused, even with [1]Leak-safe AmenoScript

A Pine text hears each leak-safe finding as a warning and runs as TradingView runs it. See what a run sees.

Different, and open ​

These differ from TradingView and aren't meant to. Each is a bug in our engine until it's fixed, and the guide page that covers it says how to work around it.

WhatTradingViewHere
str.replace(source, target, replacement, occurrence)Replaces the nth matchIgnores occurrence and replaces the first (Strings)
str.format_time with EEE, or SSSA day name; millisecondsEEE comes back as typed; SSS writes nine digits
session.ismarket, .ispremarket, .ispostmarket, .isfirstbar, .islastbarFollow the sessionismarket is always true and the rest always false
chart.left_visible_bar_time, .right_visible_bar_timeThe visible rangeAlways 0
chart.bg_color, chart.fg_colorThe chart's coloursFixed at #0F1623 and #E2E8F0 in every theme
request.security(..., currency = ...), request.currency_rate()ConvertsConverts nothing, with a warning; currency_rate reads na unless both currencies are one
request.seed, request.quandl, request.footprint, footprint.*, volume_row.*DataRead na
== and != beside < or >Bind more loosely, so a > b == c > d compares two boolsBind as tightly, so it misparses: add parentheses (Operators)
x = for ..., x = while ...A loop's last valueA syntax error
An enum value compared with a string or another enumRefusedCompares by its title: E.a == "Up" can be true
for i = 0 to n by 0, or a negative stepStops with an errorA negative step runs by its size; 0 runs no pass
A table cell with no text_sizesize.autosize.normal
calc_on_every_tick with process_orders_on_close on a live barKeeps a fill through the bar's later updatesThe next update drops it
array.sliceA view: a change to the slice shows in the originalA copy, one level deep (array.slice)
Placeholders in an alert's messageThe full set, plot_0 and the strategy's among them, in alertcondition()A shorter list, in alert() too; any other stays as typed (Placeholders)
display.pine_screenerShows the plot in TradingView's screenerDoes nothing: the Screener lists every plot by its title (Plots)
export const in a libraryExports the constantDoesn't parse: the library stops with Expected '(' here (Libraries)

A value that should match and doesn't

If a TradingView script reads differently here and the difference isn't on this page, it's a bug. The strategy emulator keeps its own list in Strategy emulator: differences.

What runs here that TradingView refuses ​

The engine accepts some text that TradingView refuses, when it compiles or when it runs. A script that runs here can therefore fail there, so check one you mean to publish on TradingView before you share it.

  • Qualifiers. Where TradingView refuses a series value in a place that needs simple, such as a series length, the run gives a qualifier: warning and goes on. A declared qualifier isn't checked: const float x = close runs. See qualifiers.
  • Layout. A script with no declaration, or two, runs. So do a block indented 2 spaces, a stray indented line after a full statement, a return statement and a triple-quoted string. See script structure.
  • History. close[-1] reads na here, where TradingView stops the script when it runs. 5[1] reads 5, where TradingView refuses it when it compiles. p.price[1] reads na, where TradingView refuses it when it compiles and asks for (p[1]).price. See history.
  • Types. A reassignment can change a variable's type, and int n = 1.5 keeps 1.5. See types.
  • Strings. "a" + 1 joins as a1. See strings.
  • Arguments. A plain argument after a named one is dropped without a word, so f(a = 1, 2) passes only a. See parameters and arguments.
  • Libraries. An importer can call a library function that has no export. See libraries.
  • na on a bool. na() and nz() take a bool, which v6 refuses, and na() can read true for a bool that every condition reads as false. See the bool.
  • Plot calls. hline() takes a series price, and alertcondition() runs in a local scope with only a warning.

A field of an object that is na reads na here, with no error. Test na(obj) before you read one, so a missing object can't pass unnoticed on either platform. See Types and enums.

Write scope TradingView's way ​

TradingView refuses each of these when it compiles a script. Write them its way:

Don't writeWrite instead
:= on a top-level variable inside a functionReturn the new value and assign it where you call the function. See functions and outer variables.
plot(), hline(), fill(), bgcolor() or another plot-family call inside a functionPlot at the top level, cond ? value : na for some bars only. See what a function can't do.
A function declared inside anotherDeclare each function at the top level.
A name read after the block or function that declared itDeclare the variable before the block and change it inside with :=. See scope.

Limits that differ ​

LimitTradingViewHere
Run timeA script past 40 seconds stops (RE10110)No limit
A loop's passesBounded by time100,000, then the loop ends early with no error
HistoryA read past the buffer stops unless max_bars_back makes roomAny depth the chart has; max_bars_back() does nothing
Plots64No cap
max_labels_count and its kinAt most 500Any number
A matrix index past the edgeStops the scriptReads na
Keys in a map50,000No limit
Call depthNo recursion64, for AmenoScript's recursion

A heavy script that runs here can stop on TradingView for time. Performance shows how to keep one fast.

What does nothing here ​

These calls and arguments are accepted, so a script that uses them runs, and they have no effect:

AcceptedWhat happens
log.info(), log.warning(), log.error()Nothing: there is no Pine Logs pane. See debugging
max_bars_back()Nothing: history has no limit
dynamic_requests = falseNot enforced
An input's active argumentThe input stays active

See also ​

AmenoScript is compatible with Pine Script v6. Pine Script is a trademark of TradingView, Inc., which has no part in AmenoScript.