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
xfield 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. yis a “float” because it will hold the pivot’s price.xlocis 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, itsxlocfield 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
Counterobject assigned to thecountervariable persists throughout the script’s execution. - The
barsfield rolls back on realtime bars, whereas theticksfield 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
references to UDT objects, enabling programmers to add virtual dimensions to their data
structures. To create a collection of a user-defined type, call the collection type’s *.new*() function with the UDT name in the function’s type template.
The following line of code declares a variable that holds the ID of an empty
array
that can store references to 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, prefix the variable declaration with collection’s type keyword followed by its type template. For example:
See the Collections section of the Type system page to learn about type templates.
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 UDT names in existing scripts; as a rule, UDT names shadow the language’s namespaces. For example, a UDT can have the same name as some built-in types, such as line or table.
However, scripts cannot use the following keywords for fundamental types as names for UDTs: int, float, string, bool, and color.