Objects
Introduction
Pine Script™ objects are instances of user-defined types (UDTs). They are the equivalent of variables containing parts called fields, each able to hold independent values that can be of various types.
Experienced programmers can think of UDTs as methodless classes. They allow users to create custom types that organize different values under one logical entity.
Creating objects
Before an object can be created, its type must be defined. The User-defined types section of the Type system page explains how to do so.
Let’s define a pivotPoint
type to hold pivot information:
Note that:
- We use the type keyword to declare the creation of a UDT.
- We name our new UDT
pivotPoint
. - After the first line, we create a local block containing the type and name of each field.
- The
x
field will hold the x-coordinate of the pivot. It is declared as an “int” because it will hold either a timestamp or a bar index of “int” type. y
is a “float” because it will hold the pivot’s price.xloc
is a field that will specify the units ofx
: xloc.bar_index or xloc.bar_time. We set its default value to xloc.bar_time by using the=
operator. When an object is created from that UDT, itsxloc
field will thus be set to that value.
Now that our pivotPoint
UDT is defined, we can proceed to create
objects from it. We create objects using the UDT’s new()
built-in
method. To create a new foundPoint
object from our pivotPoint
UDT,
we use:
We can also specify field values for the created object using the following:
Or the equivalent:
At this point, the foundPoint
object’s x
field will contain the
value of the
time
built-in when it is created, y
will contain the value of
high
and the xloc
field will contain its default value of
xloc.bar_time
because no value was defined for it when creating the object.
Object placeholders can also be created by declaring na object names using the following:
This example displays a label where high pivots are detected. The pivots
are detected legsInput
bars after they occur, so we must plot the
label in the past for it to appear on the pivot:
Take note of this line from the above example:
This could also be written using the following:
When using the var keyword while declaring a variable assigned to an object of a user-defined type, the keyword automatically applies to all the object’s fields:
It’s important to note that assigning an object to a variable that uses the varip keyword does not automatically allow the object’s fields to persist without rolling back on each intrabar update. One must apply the keyword to each desired field in the type declaration to achieve this behavior. For example:
Note that:
- We used the
var
keyword to specify that the
Counter
object assigned to thecounter
variable persists throughout the script’s execution. - The
bars
field rolls back on realtime bars, whereas theticks
field does not since we included varip in its declaration.
Changing field values
The value of an object’s fields can be changed using the := reassignment operator.
This line of our previous example:
Could be written using the following:
Collecting objects
Pine Script™ collections (arrays, matrices, and maps) can contain objects, allowing users to add virtual dimensions to their data structures. To declare a collection of objects, pass a UDT name into its type template.
This example declares an empty
array
that will hold objects of a pivotPoint
user-defined type:
To explicitly declare the type of a variable as an array, matrix, or map of a user-defined type, use the collection’s type keyword followed by its type template. For example:
Let’s use what we have learned to create a script that detects high pivot points. The script first collects historical pivot information in an array. It then loops through the array on the last historical bar, creating a label for each pivot and connecting the pivots with lines:
Copying objects
In Pine, objects are assigned by reference. When an existing object is assigned to a new variable, both point to the same object.
In the example below, we create a pivot1
object and set its x
field
to 1000. Then, we declare a pivot2
variable containing the reference
to the pivot1
object, so both point to the same instance. Changing
pivot2.x
will thus also change pivot1.x
, as both refer to the x
field of the same object:
To create a copy of an object that is independent of the original, we
can use the built-in copy()
method in this case.
In this example, we declare the pivot2
variable referring to a copied
instance of the pivot1
object. Now, changing pivot2.x
will not
change pivot1.x
, as it refers to the x
field of a separate object:
It’s important to note that the built-in copy()
method produces a
shallow copy of an object. If an object has fields with special
types
(array,
matrix,
map,
line,
linefill,
box,
polyline,
label,
table,
or
chart.point),
those fields in a shallow copy of the object will point to the same
instances as the original.
In the following example, we have defined an InfoLabel
type with a
label as one of its fields. The script instantiates a shallow
copy of
the parent
object, then calls a user-defined set()
method to update the
info
and lbl
fields of each object. Since the lbl
field of both
objects points to the same label instance, changes to this field in
either object affect the other:
To produce a deep copy of an object with all of its special type fields pointing to independent instances, we must explicitly copy those fields as well.
In this example, we have defined a deepCopy()
method that instantiates
a new InfoLabel
object with its lbl
field pointing to a copy of the
original’s field. Changes to the deep
copy’s lbl
field will not
affect the parent
object, as it points to a separate instance:
Shadowing
To avoid potential conflicts in the eventuality where namespaces added to Pine Script™ in the future would collide with UDTs or object names in existing scripts; as a rule, UDTs and object names shadow the language’s namespaces. For example, a UDT or object can use the name of built-in types, such as line or table.
Only the language’s five primitive types cannot be used to name UDTs or objects: int, float, string, bool, and color.