Limitations
Introduction
As is mentioned in our Welcome page:
Because each script uses computational resources in the cloud, we must impose limits in order to share these resources fairly among our users. We strive to set as few limits as possible, but will of course have to implement as many as needed for the platform to run smoothly. Limitations apply to the amount of data requested from additional symbols, execution time, memory usage and script size.
If you develop complex scripts using Pine Script™, sooner or later you will run into some of the limitations we impose. This section provides you with an overview of the limitations that you may encounter. There are currently no means for Pine Script™ programmers to get data on the resources consumed by their scripts. We hope this will change in the future.
In the meantime, when you are considering large projects, it is safest to make a proof of concept in order to assess the probability of your script running into limitations later in your project.
Below, we describe the limits imposed in the Pine Script™ environment.
Time
Script compilation
Scripts must compile before they are executed on charts. Compilation occurs when you save a script from the Pine Editor or when you add a script to the chart. A two-minute limit is imposed on compilation time, which will depend on the size and complexity of your script, and whether or not a cached version of a previous compilation is available. When a compile exceeds the two-minute limit, a warning is issued. Heed that warning by shortening your script because after three consecutives warnings a one-hour ban on compilation attempts is enforced. The first thing to consider when optimizing code is to avoid repetitions by using functions to encapsulate oft-used segments, and call functions instead of repeating code.
Script execution
Once a script is compiled it can be executed. See the Events triggering the execution of a script for a list of the events triggering the execution of a script. The time allotted for the script to execute on all bars of a dataset varies with account types. The limit is 20 seconds for basic accounts, 40 for others.
Loop execution
The execution time for any loop on any single bar is limited to 500 milliseconds. The outer loop of embedded loops counts as one loop, so it will time out first. Keep in mind that even though a loop may execute under the 500 ms time limit on a given bar, the time it takes to execute on all the dataset’s bars may nonetheless cause your script to exceed the total execution time limit. For example, the limit on total execution time will make it impossible for you script to execute a 400 ms loop on each bar of a 20,000-bar dataset because your script would then need 8000 seconds to execute.
Chart visuals
Plot limits
A maximum of 64 plot counts are allowed per script. The functions that generate plot counts are:
- plot()
- plotarrow()
- plotbar()
- plotcandle()
- plotchar()
- plotshape()
- alertcondition()
- bgcolor()
- fill(),
but only if its
color
is of the series form.
The following functions do not generate plot counts:
One function call can generate up to seven plot counts, depending on the function and how it is called. When your script exceeds the maximum of 64 plot counts, the runtime error message will display the plot count generated by your script. Once you reach that point, you can determine how many plot counts a function call generates by commenting it out in a script. As long as your script still throws an error, you will be able to see how the actual plot count decreases after you have commented out a line.
The following example shows different function calls and the number of plot counts each one will generate:
This example generates a plot count of 56. If we were to add two more instances of the last call to plotcandle(), the script would throw an error stating that the script now uses 70 plot counts, as each additional call to plotcandle() generates seven plot counts, and 56 + (7 * 2) is 70.
Line, box, polyline, and label limits
Contrary to plots, which can
cover the chart’s entire dataset, scripts will only show the last 50
lines,
boxes,
polylines,
and labels on
the chart by default. One can increase the maximum number for each of
these
drawing types via the max_lines_count
, max_boxes_count
,
max_polylines_count
, and max_labels_count
parameters of the
script’s
indicator()
or
strategy()
declaration statement. The maximum number of
line,
box,
and
label
IDs is 500, and the maximum number of
polyline
IDs is 100.
In this example, we set the maximum number of recent labels shown on the chart to 100:
It’s important to note when setting any of a drawing object’s
properties to
na that
its ID still exists and thus contributes to a script’s drawing totals.
To demonstrate this behavior, the following script draws a “Buy” and
“Sell”
label
on each bar, with x
values determined by the longCondition
and
shortCondition
variables.
The “Buy” label’s x
value is
na when
the bar index is even, and the “Sell” label’s x
value is
na when
the bar index is odd. Although the max_labels_count
is 10 in this
example, we can see that the script displays fewer than 10
labels on the
chart since the ones with
na
values also count toward the total:
To display the desired number of labels, we must eliminate label drawings we don’t want to show rather than setting their properties to na. The example below uses an if structure to conditionally draw the “Buy” and “Sell” labels, preventing the script from creating new label IDs when it isn’t necessary:
Table limits
Scripts can display a maximum of nine tables on the chart, one for each of the possible locations: position.bottom_center, position.bottom_left, position.bottom_right, position.middle_center, position.middle_left, position.middle_right, position.top_center, position.top_left, and position.top_right. When attempting to place two tables in the same location, only the newest instance will show on the chart.
`request.*()` calls
Number of calls
A script can use up to 40 unique calls to the functions in the request.*()
namespace. A subsequent call to the same request.*()
function with the same arguments is not unique. This limitation applies when using any request.*()
functions, including:
- request.security()
- request.security_lower_tf()
- request.currency_rate()
- request.dividends()
- request.splits()
- request.earnings()
- request.quandl()
- request.financial()
- request.economic()
- request.seed()
When a script executes two or more identical request.*()
function calls, only the first call counts toward this limit. The repeated calls do not count because they reuse the data from the first call rather than executing a redundant request. Note that when a script imports library functions containing request.*()
calls within their scopes, those calls do count toward this limit, even if the script already calls the same request.*()
function with the same arguments in its main scope.
The script below calls request.security() with the same arguments 50 times within a for loop. Although the script contains more than 40 request.*()
calls, it does not raise an error because each call is identical. In this case, it reuses the data from the first iteration’s request.security() call for the repeated calls on all subsequent iterations:
Here, we modified the above script to call request.security() with a different timeframe
argument on each iteration, meaning all 50 calls are now unique. This time, the script will reach the request.*()
call limit while executing the loop and raise a runtime error because it requests a distinct dataset on each iteration:
Note that:
- These example scripts can call request.security() within a loop and allow “series string”
timeframe
arguments because we includeddynamic_requests = true
in the indicator() declaration statement. See this section of the Other timeframes and data page for more information.
Intrabars
Scripts can retrieve up to the most recent 200,000 intrabars (lower-timeframe bars) via the request.security() or request.security_lower_tf() functions, depending on the user’s plan:
- All non-professional plans — Basic, Essential, Plus, and Premium — can request up to 100K bars of data.
- Expert plans have access to 125K bars of data.
- Elite plans get 150K bars of data.
- Ultimate plans can request 200K lower timeframe bars.
The request.*()
functions limit requested data via the calc_bars_count
parameter. If this parameter is not specified, the default is used, which is 100,000 bars. If the plan permits more, this limit can be increased by passing a greater value.
The number of bars on the chart’s timeframe covered by 100,000 intrabars varies with the number of intrabars each chart bar contains. For example, requesting data from the 1-minute timeframe while running the script on a 60-minute chart means each chart bar can contain up to 60 intrabars. In this case, the minimum number of chart bars covered by the intrabar request is 1,666, as 100,000 / 60 = 1,666.67. It’s important to note, however, that a provider may not report data for every minute within an hour. Therefore, such a request may cover more chart bars, depending on the available data.
Tuple element limit
All the request.*()
function calls in a script taken together cannot
return more than 127 tuple elements. When the combined tuple size of all
request.*()
calls will exceed 127 elements, one can instead utilize
user-defined types (UDTs) to request a greater number of values.
The example below outlines this limitation and the way to work around
it. The first
request.security()
call represents using a tuple with 128 elements as the expression
argument. Since the number of elements is greater than 127, it would
result in an error.
To avoid the error, we can use those same values as fields within an
object of a
UDT
and pass its ID to the expression
instead:
Note that:
- This example outlines a scenario where the script tries to evaluate 128 tuple elements in a single request.security() call. The same limitation applies if we were to split the tuple request across multiple calls. For example, two request.security() calls that each retrieve a tuple with 64 elements will also cause an error.
Script size and memory
Compiled tokens
Before the execution of a script, the compiler translates it into a tokenized Intermediate Language (IL). Using an IL allows Pine Script™ to accommodate larger scripts by applying various memory and performance optimizations. The compiler determines the size of a script based on the number of tokens in its IL form, not the number of characters or lines in the code viewable in the Pine Editor.
The compiled form of each indicator, strategy, and library script is limited to 80,000 tokens. When a script imports libraries, the total number of tokens from all imported libraries cannot exceed 1 million. There is no way to inspect a script’s compiled form, nor its IL token count. As such, you will only know your script exceeds the size limit when the compiler reaches it.
In most cases, a script’s compiled size will likely not reach the limit. However, if a compiled script does reach the token limit, the most effective ways to decrease compiled tokens are to reduce repetitive code, encapsulate redundant calls within functions, and utilize libraries when possible.
It’s important to note that the compilation process omits any unused variables, functions, types, etc. from the final IL form, where “unused” refers to anything that does not affect the script’s outputs. This optimization prevents superfluous elements in the code from contributing to the script’s IL token count.
For example, the script below declares a user-defined type and a user-defined method and defines a sequence of calls using them:
Despite the inclusion of array.new<myType>(),
myType.new()
, and arr.m()
calls in the script, the only thing
actually output by the script is plot(close)
. The rest of the code
does not affect the output. Therefore, the compiled form of this script
will have the same number of tokens as:
Variables per scope
Scripts can contain up to 1,000 variables in each of its scopes. Pine scripts always contain one global scope, represented by non-indented code, and they may contain zero or more local scopes. Local scopes are sections of indented code representing procedures executed within functions and methods, as well as if, switch, for, for…in, and while structures, which allow for one or more local blocks. Each local block counts as one local scope.
The branches of a conditional expression using the ?: ternary operator do not count as local blocks.
Scope count
The total number of scopes in a script, including its global scope and each local scope from the user-defined functions, methods, conditional structures it uses, cannot exceed 550.
It’s important to note that the
request.security(),
request.security_lower_tf(),
and
request.seed()
functions duplicate the scopes required to evaluate the values of
their expression
argument in another context. The scopes produced by
each call to these request.*()
functions also count toward the
script’s scope limit.
For example, suppose we created a script with a global variable that depends on the local scopes of 300 if structures. The total scope count for this script is 301 (1 global scope + 300 local scopes):
Since the total number of scopes is within the limit, it will compile
successfully. Now, suppose we call
request.security()
to evaluate the value of x
from another context and
plot its value as well. In
this case, it will effectively double the script’s scope count since
the value of x
depends on all the script’s scopes:
We can resolve this issue by encapsulating the if blocks within a user-defined function, as the scope of a function counts as one embedded scope:
Compilation request size
The size of the compilation request for a script cannot exceed 5MB. The compilation request is all of the information that is sent to the compiler. This information comprises the script itself and any libraries the script imports.
Unlike the limit for compiled tokens, the request size limit includes unused parts of code. This is because the script is not compiled yet, so any unused code has not yet been optimized out.
To reduce the compilation request size, you can:
- Reduce the size of the script by optimizing the code.
- Reduce the number of script inputs (script inputs are counted separately).
- Remove any imported libraries that are not needed.
- Use smaller libraries. The entire library is sent for compilation, regardless of which functions are called.
Collections
Pine Script™ collections (arrays, matrices, and maps) can have a maximum of 100,000 elements. Each key-value pair in a map contains two elements, meaning maps can contain a maximum of 50,000 key-value pairs.
Other limitations
Maximum bars back
References to past values using the
[]
history-referencing operator are dependent on the size of the historical
buffer maintained by the Pine Script™ runtime, which is limited to a
maximum of 5000 bars. This Help Center
page
discusses the historical buffer and how to change its size using either
the max_bars_back
parameter or the
max_bars_back()
function.
Maximum bars forward
When positioning drawings using xloc.bar_index
, it is possible to use
bar index values greater than that of the current bar as x
coordinates. A maximum of 500 bars in the future can be referenced.
This example shows how we use the [maxval] parameter in our input.int() function call to cap the user-defined number of bars forward we draw a projection line so that it never exceeds the limit:
Chart bars
The number of bars appearing on charts is dependent on the amount of historical data available for the chart’s symbol and timeframe, and on the type of account you hold. When the required historical date is available, the minimum number of chart bars is:
- 40000 historical bars for the Ultimate plan.
- 30000 historical bars for the Elite plan.
- 25000 historical bars for the Expert plan.
- 20000 historical bars for the Premium plan.
- 10000 historical bars for Essential and Plus plans.
- 5000 historical bars for other plans.
Trade orders in backtesting
A script can place a maximum of 9000 orders when backtesting strategies. Once it reaches that limit, the earlier orders are trimmed to store the information of new orders. Programmers can use the strategy.closedtrades.first_index variable to reference the index of the earliest untrimmed trade.
When using Deep Backtesting, the order limit is 1,000,000.