Enums
Introduction
Pine Script™ Enums, otherwise known as enumerations, enumerated types, or enum types, are unique data types with all possible values (members) explicitly defined by the programmer. They provide a human-readable, expressive way to declare distinct sets of predefined values that variables, conditional expressions, and collections can accept, allowing more strict control over the values used in a script’s logic.
Declaring an enum
To declare an enum, use the enum keyword with the following syntax:
Each field in the enum represents a unique, named member (value) of the enum type. Users can specify optional “const string” titles for enum fields to add extra information about what their values represent. If the programmer does not specify a field’s title, its title is the “string” representation of its name. Enum inputs display enum field titles within their dropdown menus in a script’s “Settings/Inputs” tab. Scripts can also retrieve enum field titles using the str.tostring() function, allowing their use in additional calculations. See this section below for more information.
While the above syntax may look similar to the syntax for declaring user-defined types (UDTs), it’s crucial to understand that enum types and UDTs serve different purposes. Scripts use UDTs to create objects with “series” fields that can hold values of any specified type. In contrast, enums are distinct groups of “simple” fields representing the specific, predefined values of the same unique type that variables, expressions, and collections can accept.
For example, this code block declares a Signal
enum with three fields:
buy
, sell
, and neutral
. Each field represents a distinct member
(possible value) of the Signal
enum type:
Note that:
- The
Signal
identifier represents the enum’s name, which signifies the unique type the fields belong to. - We used the
//@enum
and//@field
annotations to document the meaning of the enum and its fields. - Unlike the
buy
andsell
fields, theneutral
field does not include a specified title. As such, its title is the “string” representation of its name (“neutral”).
To retrieve a member of an enum, reference its field name using dot notation syntax, i.e.:
As with other types, scripts can assign enum members to variables, function parameters, and UDT fields, allowing strict control over their allowed values.
For instance, this line of code declares a mySignal
variable whose
value is the neutral
member of the Signal
enum. Any value assigned
to this variable later must also be of the same
enum type:
Note that the above line does not require declaring the variable’s
type as Signal
because the compiler can automatically infer that
information from the assigned value. If we use
na as
the initial value instead, we must use Signal
as the type keyword to
specify that mySignal
will accept a Signal
member:
Using enums
Scripts can compare enum members with the == and != operators and use them in conditional structures, allowing the convenient creation of logical patterns with a reduced risk of unintended values or operations.
The following example declares an OscType
enum with three fields
representing different oscillator choices: rsi
, mfi
, and cci
. The
calcOscillator()
function uses OscType
members within a
switch
structure to determine which oscillator it calculates. The script calls
this function using the value from an
enum input as the selection
argument and plots the
resulting oscillator:
Note that:
- The
selection
parameter of thecalcOscillator()
function can only take on one of four values:OscType.rsi
,OscType.mfi
,OscType.cci
, or na. - The “Oscillator type” input in the script’s
“Settings/Inputs” tab displays all
OscType
field titles in its dropdown. See this section to learn more about enum inputs.
It’s crucial to note that each declared enum represents a unique type. Scripts cannot compare members of different enums or use such members in expressions requiring a specific enum type, even if the fields have identical names and titles.
In this example, we added an OscType2
enum to the above script and
changed the oscInput
variable to use a member of that enum. The script
now raises a compilation error because it can’t use a member of the
OscType2
enum as the selection
argument in the calcOscillator()
call:
Utilizing field titles
The “string” titles of an enum’s fields allow programmers to add extra information to each member. These field titles appear within a dropdown in the script’s “Settings/Inputs” tab when calling the input.enum() function.
Scripts can also utilize enum field titles in their calculations and logic. Use the string conversion function (str.tostring()) on an enum field to access its title.
The following example combines different enum field titles to construct
a ticker ID for requesting data from
another context. The script declares two enums, Exchange
and Pair
, whose
respective fields represent exchange and currency pair names. It
uses
input.enum()
to assign user-specified enum members to the exchangeInput
and
pairInput
variables, then retrieves the “string” titles from those
variables with
str.tostring()
and concatenates them to form an “Exchange:Symbol” pair for use in a
request.security()
call:
Note that:
- None of the members of the
Exchange
orPair
enums have specified titles. Therefore, each field’s title is the “string” representation of its name, as shown by the script’s enum inputs. - Calling the
str.tostring()
function on an enum field is the only way to retrieve its
title for additional calculations. The
str.format()
and
log.*()
functions cannot accept enum members. To use a field’s title in a string formatting function, call str.tostring() on the field first, then pass the resulting “string” to the function.
Collecting enum members
Pine Script™ collections (arrays, matrices, and maps) can store enum members, allowing strict control over the values they can contain. To declare a collection of enum members, include the enum’s name in the collection’s type template.
For example, this code block creates an empty
array
to hold members of the FooBar
enum. The only values this array can
allow as elements are FooBar.foo
, FooBar.bar
, FooBar.baz
, and
na:
Enums are particularly helpful when working with maps, as unlike other non-fundamental types, scripts can declare maps with keys of an enum type, enabling strict control over all possible keys allowed in their key-value pairs.
The following example uses a
map
with enum keys and “int” values to track and count signal states
across chart bars. The script’s Signal
enum contains five fields
representing specific named states. The signalCounters
map
uses the Signal
name as the first keyword in its
type template to specify that it can only accept Signal
members as keys.
The script uses a
switch
structure to calculate a signalState
variable whose value is a member
of the Signal
enum, which it uses to determine the counter value to
update in the signalCounters
map. It constructs a “string” to
represent the key-value pairs of the
map
and displays the result in a single-cell
table
on the last chart bar:
Note that:
- The
signalCounters
map can contain up to six key-value pairs, as theSignal
enum has five predefined values, plus a possible value of na, and maps cannot contain repetitive keys. - The script declares the
signalCounters
variable using the var keyword, signifying that the assigned map instance persists across executions. - On the first chart bar, the script uses five
map.put()
calls to establish the insertion order of keys in the
signalCounters
map. See this section of the Maps page for more information. - To minimize resource usage, the script declares the
infoTable
and initializes its cell on the first bar, then updates the cell’s text on the latest bar. See this section of the Profiling and optimization page to learn more.
Shadowing
To avoid potential conflicts where namespaces added to Pine Script™ in the future would conflict with the names of enums in existing scripts, enum names can shadow some of Pine’s namespaces.
For example, one can declare an enum like the following, whose name
shadows the syminfo.*
namespace:
However, using such a name for an enum is only allowed if the enum’s fields do not have names matching any of the namespace’s built-ins. Otherwise, Pine will not be able to determine which value the script is supposed to use, resulting in a compilation error:
Additionally, one cannot use any of Pine’s built-in type names as the name of an enum.