Skip to content
Back to App

Supported Pine Features

TestMax supports Pine Script v5 and v6 across common indicator and strategy workflows, and converts v4 and v3 scripts when they are applied. This page describes the implemented features and the limits to check when bringing a script from TradingView. Identical source can produce different results with different data, sessions, history, or simulation assumptions.

Language and inputs

FeatureSupport
indicator() and strategy()Indicators and strategies can be applied to replay charts
library() and importAvailable library source can be saved in your account and imported by exact path
InputsInteger, float, boolean, string, text area, color, source, timeframe, session, time, price, symbol, and enum inputs; options, group, inline, tooltip, active, and confirm
Control flowif / else, for, for ... in (array elements, map pairs, and matrix rows), while, switch, and once; if, switch, and loops can return values, and a function returns the value of its last statement
Functions and typesUser-defined functions, methods, user-defined types, enum types, and the const, input, simple, and series qualifiers
StringsSingle-line strings and triple-quoted strings ("""...""") that span lines and keep their leading spaces
CollectionsArrays, matrices, and maps in function form (array.sort(a)) and method form (a.sort()), with size limits; array.slice() returns a view that shares its elements with the original array
Series historyx[n] and history-dependent calculations
Version rulesv5 evaluates both sides of and / or and divides integer constants as integers (5 / 2 is 2); v6 stops early and divides as decimals (2.5). v5 also divides int(5) / int(2) as 2. v3 to v5 compare a bool with a number as two bools (0 and na are false); v6 refuses that comparison, a number used as a condition, and na(), nz(), or fixnan() on a bool. In v6 a bool is never na: its history before the first bar is false. timeframe.period is "D", "W", or "M" in v5 and "1D", "1W", or "1M" in v6. A plot or level linewidth below 1 is drawn as 1 in v5 and is an error in v6
Persistent statevar state rolls back between open-candle updates, including referenced objects; varip persists between executions
Logs and errorslog.info, log.warning, log.error, and runtime.error

The compiler refuses the common mistakes that TradingView refuses, with their line: a wrong value type in a typed declaration, argument, or array, missing or extra function arguments, a variable declared twice in one scope, x = na without a type (version 4 and later), a field name that the type does not have in Type.new(), a name that does not exist in syminfo, barstate, timeframe, session, strategy, math, or ta (for example syminfo.tickr), plotshape() or plotchar() text that is not a constant string, and a continuation line that is not indented or is indented by a multiple of four spaces. It does not implement every Pine type rule or collection method. A successful compilation is not a promise of full language equivalence.

Older versions. A //@version=4 or //@version=3 script is converted to current Pine before it compiles: study(), names without a namespace (sma, security, tostring, …), iff(), input(type = ...), transp, version 3 color, style, and weekday names, and the long argument of strategy orders. A name the converter does not know stops the script with an error that names it. A script without a //@version line is version 1 on TradingView and is not supported; add a version line and migrate it. Version 2 is not supported. A ta.* or math.sum call inside a branch keeps its own history, as on TradingView: it sees only the bars on which the branch ran.

Common TA calculations

CategoryFunctions and built-ins
Moving averagessma, ema, rma, wma, vwma, swma, alma
Oscillatorsrsi, macd, stoch, cci, mfi, tsi, cog, rci
Bands and dispersionbb, stdev, variance, dev, atr, tr
Trendsupertrend, sar, dmi — dmi returns +DI, −DI, and ADX
Extremes and statisticshighest, lowest, highestbars, lowestbars, all-time max and min, median, mode, range, percentrank, percentile_linear_interpolation, percentile_nearest_rank, linreg, correlation
Changes and totalschange, mom, roc, cum
Crosses and conditionscross, crossover, crossunder, rising, falling
Pivots and eventspivothigh, pivotlow, pivot_point_levels, barssince, valuewhen
Volumeobv, accdist, iii, nvi, pvi, pvt, wad, wvad, and vwap with an optional anchor condition and standard-deviation bands

Common math.* helpers and constants (math.pi, math.e, math.phi, math.rphi), math.sum, na, nz, and fixnan are available. Numeric str.tostring() formatting supports common decimal/grouping patterns with literal text around the number ("$#.##"), format.mintick, format.percent, and format.volume; it also prints arrays and matrices. str.format() supports plain, number, date, and time placeholders. str.match() accepts simple patterns; patterns that could stall the calculation are refused.

Bar-state values update with replay execution, including barstate.isconfirmed.

Time, sessions, and timeframes

Each instrument reports its exchange clock: CME futures use Chicago time with a 17:00 to 16:00 session, forex and spot metals use New York time with a 17:00 to 17:00 session, and crypto uses UTC around the clock. hour, minute, dayofweek, session strings without a timezone, and str.format_time() use that clock.

FeatureSupport
time() and time_close()Chart timeframe, another timeframe (time("D")), a session string, and a timezone
Session stringsOne or several ranges ("0930-1200,1300-1600"), day lists, overnight and full-day sessions
session.*ismarket, isfirstbar, islastbar, their _regular forms, session.regular, session.extended
timeframe.*period, multiplier, isseconds to ismonthly, change(), in_seconds(), from_seconds(), main_period
timestamp()Numeric parts with an optional timezone, and date strings
dayofweek.*dayofweek.sunday to dayofweek.saturday

Higher-timeframe periods follow TestMax’s own candles, which are cut on the UTC clock. A Pine "D" period therefore matches the TestMax daily chart, and can start at a different hour than the exchange day on TradingView. ta.vwap(source) resets by calendar day in the exchange timezone. ta.vwap(source, anchor) resets on each bar where anchor is true.

Plots and drawing objects

VisualSupport
Numeric plotsLines, step lines, circles, crosses, histograms, columns, and areas, including the linebr, areabr, steplinebr, and stepline_diamond styles; per-bar colors and transparency; offset, show_last, join, trackprice, linewidth, linestyle, histbase, format, and precision
hline()Constant or input-controlled levels with solid, dashed, or dotted lines; levels are part of the pane’s scale
plotshape() / plotchar()Shape and character glyphs, including absolute, above/below-bar, and pane-edge locations; offset, show_last, and force_overlay
plotarrow()Signed arrows with configurable minimum and maximum heights
plotbar() / plotcandle()OHLC drawings with colors, na visibility, show_last, and force_overlay
bgcolor()Colored background bands for individual bars; offset, show_last, and display
barcolor()Colors the candle body, wick, and border; offset, show_last, and display
fill()Fills between compatible pairs of plot IDs or horizontal-line IDs, including dynamic colors, gradient fills (top_value, bottom_value, top_color, bottom_color), and fillgaps
Lines, boxes, and labelsCreation from coordinates or chart.point values, setters, copies, deletion, line extensions/arrowheads, multiline text, box text with wrapping, label tooltips, and force_overlay
linefillFills that follow the referenced lines
PolylinesStraight or curved paths, closed shapes, and fill colors
TablesAll nine positions, merged cells, regional clearing, text/alignment/size/color setters, tooltips, and supported font formatting

Open-candle redraws replace temporary output and restore prior drawing state. Script visuals are drawn behind the candles unless the script sets behind_chart = false. Lines, boxes, labels, linefills, and polylines stay above the script’s own plots, fills, and levels. The grid stays below all script visuals, and the crosshair stays on top. Box text with the default size.auto shrinks to fit inside the box.

The scale argument of indicator() and strategy() puts a separate-pane script on the right or left axis. With overlay = true, scale.none gives the script no axis of its own (without overlay = true it is a compile error, as on TradingView), and scale.left gives it its own axis on the left side of the price pane. With explicit_plot_zorder = true, plots, levels, and fills stack in the order the script calls them; lines, boxes, labels, and tables always stay on top of them. Exact font metrics, curve interpolation, and marker sizing can differ slightly from TradingView.

The following options remain limited:

  • A plot offset must keep the same value during a run. A positive offset draws at most 500 bars beyond the last candle.
  • Supported display settings control pane visibility. TradingView’s status line values, Data Window, and price-scale labels are not reproduced.
  • indicator(timeframe = ...) with a timeframe other than the chart’s is not supported. The script stops with an error.
  • alert() and alertcondition() are accepted and do nothing.
  • chart.left_visible_bar_time and chart.right_visible_bar_time are not supported, because TestMax does not re-run a script when you scroll or zoom. The script stops with an error.

Libraries

Save each library’s source as a Library with the exact name used by the import, such as local/MathTools/1. Then use import local/MathTools/1 as tools in an indicator or strategy.

Imports resolve from your saved sources. TestMax does not download a TradingView library automatically. Missing versions, duplicate saved names, circular imports, and ambiguous overloads report errors. Libraries are not applied directly to a chart. See the library walkthrough.

Other symbols and timeframes

request.security() and request.security_lower_tf() evaluate supported expressions using chart datasets available in your replay. Add a chart pane for a required symbol or timeframe before applying a script that needs it.

  • The same symbol/timeframe can reuse its existing bars.
  • Higher-timeframe calculations need an available matching dataset or a supported exact aggregation of finer bars. Automatic aggregation currently requires a UTC, continuous-session bar grid; exchange-session rebucketing is not available.
  • Lower-timeframe requests require an available finer dataset whose interval divides the chart interval. request.security_lower_tf() returns the revealed intrabars as arrays.
  • A lookahead_on request needs a history offset of at least 1 that the compiler can prove from a literal, an input, a default value, or a call argument, such as close[1] or f(1). Otherwise the script stops with an error at the request’s line.
  • Gaps and lookahead settings operate within the replay’s revealed-data boundary. A request cannot provide future replay candles, so scripts relying on future historical values can differ from a complete TradingView history run.
  • A request can sit inside your own function, such as the common noRepaintSecurity(sym, tf, src) wrapper. When an earlier line of that function changes an array, map, matrix, or object through a path the compiler cannot follow (for example a conditional or tuple alias, a value returned by a call, or a for ... in element), the script stops with an error at that line. Pass the value as a parameter, or call the request outside the function.
  • Requested results can be primitive values or flat tuples. Nested requests, chart drawing/order calls inside requested expressions, currency conversion, and calc_bars_count are not supported.
  • request.financial(), request.economic(), request.dividends(), request.splits(), request.earnings(), request.seed(), request.currency_rate(), request.footprint(), and Heikin Ashi, Renko, or other non-standard ticker.* data are not available. The script stops with an error.

If an error says data is unavailable, add the matching pane and apply again. If a requested expression captures a mutable outer value, move its calculation into a function evaluated by the request.

Strategy support

Entries, raw orders, stop/limit brackets, trailing stops, partial exits, exit reservations, FIFO/ANY allocation, entry/order OCA groups, immediate closes, commissions, margin checks, and margin liquidation are implemented. The Strategies guide explains their defaults and fill rules.

The strategy.risk.* rules are implemented. Bar Magnifier, alternate calculation modes, custom OCA groups on strategy.exit(), and automatic currency conversion remain unsupported. Alerts do not send notifications or webhooks; use chart markers, tables, or log.* output for feedback during replay.

Limits

LimitValue
Editor, paste, import, save, and export50 MiB of valid UTF-8 per script
Script plus imported libraries50 MiB combined; up to 16 libraries
Saved scripts1,000 per account
Account script storage100 MiB by default; administrator configurable
Applied scripts10 per symbol
Compile and history calculation30 seconds each
Loops500 ms for one loop on one bar, as on TradingView. Time spent loading request.security() data for another symbol or timeframe does not count
Executable source complexity100,000 code tokens; deeply nested expressions may also be rejected
TA lookback10,000 bars
Collections100,000 elements per collection; maps up to 50,000 key/value pairs
Data requests40 request contexts, using available replay data
Drawing counts50 by default; declared line/box/label limits up to 500 and polyline limits up to 100; 500 linefills. A new linefill between the same two lines replaces the old one
Drawing positionsWith xloc.bar_index, at most 500 bars after and 10,000 bars before the current bar
Table cells10,000 per script
Chart output history8 MiB of drawing changes and 32 MiB of per-bar visuals (fills, backgrounds, bar colors, shapes, and candle plots); deleted drawings stop counting once their bar is confirmed; a run of identical fill bars is stored once; 500,000 fill values in total (one per fill() call per bar)
Strategy orders1,000 calls per execution and 1,000 pending orders
Strategy history10,000 trade records
Plot colors65,535 distinct colors per plot

A 30 MiB comment-heavy script can compile and run when its executable body fits the workload limits. Large document size alone does not determine calculation cost. Dense generated code, extensive loops, large collections, and excessive chart output can exceed separate execution limits.

Large documents automatically use plain-text editor mode. Wait for a large paste or import to finish checking before saving or applying. If you hit a limit, reduce the calculation’s lookback, collection size, drawing count, or loaded history as appropriate. Additional memory and output limits can stop a run with a specific error.

Errors and recovery

Compile errors appear in the editor’s error console; use the reported location to find the relevant code. Runtime errors include the bar where execution stopped. Collection errors use TradingView’s text, such as Index 5 is out of bounds. Array size is 3., and array.pop() or array.shift() on an empty array is an error; runtime.error("text") stops the script with your own text. log.info(), log.warning(), and log.error() write to the Logs list in the editor console, which keeps the newest 1,000 lines. Re-apply after correcting the script or providing its missing data. Other applied scripts can keep running.