Libraries
Introduction
Pine Script™ libraries are publications containing functions that can be reused in indicators, strategies, or in other libraries. They are useful to define frequently-used functions so their source code does not have to be included in every script where they are needed.
A library must be published (privately or publicly) before it can be used in another script. All libraries are published open-source. Public scripts can only use public libraries and they must be open-source. Private scripts or personal scripts saved in the Pine Script™ Editor can use public or private libraries. A library can use other libraries, or even previous versions of itself.
Library programmers should be familiar with Pine Script™‘s typing nomenclature, scopes and user-defined functions. If you need to brush up on qualified types, see the User Manual’s page on the Type system. For more information on user-defined functions and scopes, see the User-defined functions page.
You can browse the library scripts published publicly by members in TradingView’s Community Scripts.
Creating a library
A library is a special kind of script that begins with the library() declaration statement, rather than indicator() or strategy(). A library contains exportable function, method, UDT, and enum definitions, which constitute the only visible part of the library when imported by another script. Like other script types, libraries can also include Pine Script™ code in their global scopes. Programmers typically use a library’s global code to demonstrate how other scripts can use its exported structures.
A library script has a structure like the following, which must include one or more exportable functions or types:
Note that:
- The
//@description
,//@enum
,//@type
,@field
,// @function
,// @param
, and// @returns
compiler annotations are optional but we highly recommend you use them. These annotations document the library’s code and populate the default library description, which authors can use when publishing the library. - The export keyword is mandatory.
- <parameter_type> is mandatory, contrary to user-defined function parameter definitions in indicators or strategies, which are typeless.
- <script_code> can be any code one would normally use in an indicator, including inputs.
This is an example library:
Library functions
Exported functions and methods have slightly different requirements and constraints compared to non-exported functions.
In exported library function signatures (their first line):
- The export is mandatory.
- The function’s signature must include type keywords to specify the required type for each parameter.
- Programmers can include either the simple or series qualifier keywords to specify the qualified type each parameter accepts. See the next section for more information.
Exported library functions have the following constraints:
- They cannot use variables from the library’s global scope except for those with the “const” qualifier, meaning they cannot use global variables initialized from script inputs, for example, or globally declared arrays.
- They cannot include calls to any
input.*()
functions. - They cannot call
request.*()
functions in their local scopes unless the script includesdynamic_requests = true
in the library() declaration statement. See this section of the Other timeframes and data page to learn more about dynamic requests.
Library functions always return “simple” or “series” results. Consequently, scripts cannot use their returned values in locations requiring “const” or “input” values. For example, a library function cannot calculate an argument for the show_last
parameter in a plot() call because the parameter requires an “input int” qualified type.
Qualified type control
The qualified types of arguments supplied in calls to library functions are autodetected based on how each argument is used inside the function. If the argument can be used as a “series”, it is qualified as such. If it cannot, an attempt is made with the “simple” type qualifier. This explains why this code:
will work when called using myCustomLibrary.myEma(20)
, even though
ta.ema()‘s
length
parameter requires a “simple int” argument. When the Pine
Script™ compiler detects that a “series” length cannot be used with
ta.ema(),
it tries the “simple” qualifier, which in this case is allowed.
While library functions cannot return “const” or “input” values,
they can be written to produce “simple” results. This makes them
useful in more contexts than functions returning “series” results, as
some built-in functions do not allow “series” arguments. For example,
request.security()
requires a “simple string” argument for its symbol
parameter when a script does not allow dynamic requests. If we wrote a
library function to assemble the argument to symbol
in the following
way, the function’s result would not work with a non-dynamic request.*()
call because it is of the “series
string” qualified type:
However, by restricting the parameter qualifiers to “simple”, we can force the function to yield a “simple” result. We can achieve this by prefixing the parameters’ type with the simple keyword:
Note that for the function to return a “simple” value, no “series” values can be used in its calculation; otherwise the result will be a “series” value.
One can also use the series keyword to prefix the type of a library function parameter. However, because arguments are qualified as “series” by default, using the series modifier is redundant.
User-defined types and objects
Libraries can export user-defined types (UDTs), and library functions can return objects of these types.
To export a UDT, prefix its definition with the export keyword, similar to exporting a function:
A script importing that library and creating an
object of its point
UDT
would look somewhat like this:
Note that:
- This code won’t compile because no “Point” library is published, and the script doesn’t display anything.
userName
would need to be replaced by the TradingView user name of the library’s publisher.- We use the built-in
new()
method to create an object from thepoint
UDT. - We prefix the reference to the library’s
point
UDT with thept
alias defined in the import statement, just like we would when using a function from an imported library.
A library must export a UDT if any exported functions or methods accept or return an object of that type, or if the fields of another exported UDT accept an instance of the type.
When a library only uses a
UDT
internally, it does not need to export the type. The following library
uses the point
type internally, but it only exports the drawPivots()
function, which does not have a parameter of the point
type or return
a point
object:
If the TradingView user published the above library, it could be used like this:
Enum types
Libraries can also export enum types, allowing other scripts to import sets of predefined, named values that help control the values accepted by variables, conditional expressions, and collections.
For example, this library exports a State
enum with three fields
representing distinct signal states: long
, short
, and neutral
.
These fields represent the possible values a variable, expression, or
collection of the
enum type can take on:
A script that imports this library can use the members (values) of the
State
enum as named states in its logic. Here, we show a simple,
hypothetical script that imports the “Signal” library published by the
userName
user and uses the Signal.State
enum to assign one of three
possible values to a mySignal
variable:
Similar to exporting UDTs, a library must export an enum when its exported functions or methods accept or return the enum’s members, or when the fields of an exported UDT accept values of that enum type.
Publishing a library
Before you or other Pine Script™ programmers can reuse any library, it must be published. If you want to share your library with all TradingViewers, publish it publicly. To use it privately, use a private publication. As with indicators or strategies, the active chart when you publish a library will appear in both its widget (the small placeholder denoting libraries in the TradingView scripts stream) and script page (the page users see when they click on the widget).
Private libraries can be used in public Protected or Invite-only scripts.
After adding our example library to the chart and setting up a clean chart showing our library plots the way we want them, we use the Pine Editor’s “Publish Script” button. The “Publish Library” window comes up:
Note that:
- We leave the library’s title as is (the
title
argument in our library() declaration statement is used as the default). While you can change the publication’s title, it is preferable to keep its default value because thetitle
argument is used to reference imported libraries in the import statement. It makes life easier for library users when your publication’s title matches the actual name of the library. - A default description is built from the compiler annotations we used in our library. We will publish the library wihout retouching it.
- We chose to publish our library publicly, so it will be visible to all TradingViewers.
- We do not have the possibility of selecting a visibility type other than “Open” because libraries are always open-source.
- The list of categories for libraries is different than for indicators and strategies. We have selected the “Statistics and Metrics” category.
- We have added some custom tags: “all-time”, “high” and “low”.
The intended users of public libraries being other Pine programmers; the better you explain and document your library’s functions, the more chances others will use them. Providing examples demonstrating how to use your library’s functions in your publication’s code will also help.
House Rules
Pine libraries are considered “public domain” code in our House Rules on Script Publishing, which entails that permission is not required from their author if you call their functions or reuse their code in your open-source scripts. However, if you intend to reuse code from a Pine Script™ library’s functions in a public protected or invite-only publication, explicit permission for reuse in that form is required from its author.
Whether using a library’s functions or reusing its code, you must credit the author in your publication’s description. It is also good form to credit in open-source comments.
Using a library
Using a library from another script (which can be an indicator, a strategy or another library), is done through the import statement:
where:
- The <username>/<libraryName>/<libraryVersion> path will uniquely identify the library.
- The <libraryVersion> must be specified explicitly. To ensure the reliability of scripts using libraries, there is no way to automatically use the latest version of a library. Every time a library update is published by its author, the library’s version number increases. If you intend to use the latest version of the library, the <libraryVersion> value will require updating in the import statement.
- The
as <alias>
part is optional. When used, it defines the namespace that will refer to the library’s functions. For example, if you import a library using theallTime
alias as we do in the example below, you will refer to that library’s functions asallTime.<function_mame>()
. When no alias is defined, the library’s name becomes its namespace.
To use the library we published in the previous section, our next script will require an import statement:
As you type the user name of the library’s author, you can use the
Editor’s ctrl
+
space
/ cmd
“Auto-complete”
command to display a popup providing selections that match the available
libraries:
This is an indicator that reuses our library:
Note that:
- We have chosen to use the “allTime” alias for the library’s instance in our script. When typing that alias in the Editor, a popup will appear to help you select the particular function you want to use from the library.
- We use the library’s
hi()
andlo()
functions without an argument, so the default high and low built-in variables will be used for their series, respectively. - We use a second call to
allTime.hi()
, but this time using close as its argument, to plot the highest close in the chart’s history.