Skip to main content
Version: v27

Constructor

Overview

constructor is a required field in the CustomIndicator object that you should specify to create a custom indicator.

custom_indicators_getter: function(PineJS) {
return Promise.resolve([
{
// Indicator object
// ...
constructor: {
// ...
},
}
]);
},

The field should contain an ES5 constructor function. The library applies the new operator to the constructor to create an instance of the custom indicator.

The constructor contains the main and init methods that accept the following arguments:

  • ctx — context that stores an indicator state. It includes information about the current symbol, resolution, OHLC values of the current bar, and more.
  • inputs — an array of input values. Elements in the array are arranged in the same order as inputs in the metainfo.

You should implement either both methods or only main to calculate indicator data. In your implementation, use mathematical, logical, and technical analysis functions provided in the PineJSStd interface.

init

The init method is optional. It is designed to get additional information for an indicator and allows you to initialize variables needed for your data calculations. For example, you can reset a counter with this method. The library calls init once during the indicator lifetime when the indicator should be calculated from scratch. This can occur when:

  • The indicator is added to the chart.
  • The indicator is added to a new pane.
  • The symbol is changed.
  • The resolution is changed.

Consider the following example. You want to display an indicator that compares values between the current symbol and a different one. In this case, the indicator requires data for another symbol. The code sample below shows how to request data for a symbol using the new_sym method. Requesting symbol data should be done once, therefore, it is implemented within init.

this.init = function(context, inputCallback) {
var symbol = "AAPL";
var period = PineJS.Std.period(this._context);
context.new_sym(symbol, period);
};

main

The main method is required and should contain the main data calculations. The library calls this method for each bar of the main series.

info

If there is more than one series, the library calls main for each bar of an additional series first, and then for each bar of the main series.

Data calculations

As mentioned above, the library calls main for each bar of the main series. On each iteration, you can get information about previous bars only. Therefore, when you calculate the tenth bar, you can access values of the bars in the [1..9] range. The library does not provide future bars, and you should not use them in your calculations to avoid unexpected results.

To store data for intermediate calculations, you should create variables using API methods such as new_var and new_unlimited_var. Consider the Requesting Data for Another Ticker example where the timestamp of the current bar is stored using new_var.

Output values

As a result, the method should return an indicator value that corresponds to the current bar. An indicator is represented with plots specified in metainfo. Therefore, you should provide a value for each plot. If there is only one plot, main should return a number, for example 10, or an array with one element — [10]. Otherwise, the result is an array where elements are arranged in the same order as plots in metainfo. Consider the OHLC Plots example where four plots get the corresponding open, high, low, and close values.

Values in the array can be one of the following types:

  • Numbers, for example, [10, 20].
  • Objects with the { offset: number, value: number, } structure that allow you to display a value several bars forward or backward from the current bar. For example, [{ value: 10, offset: 5, }, { value: 20, offset: 10, }].

Example

The code sample below demonstrates the constructor implementation for a simple indicator that plots the close value.

constructor: function () {
this.main = function (context, inputCallback) {
this._context = context;
this._input = inputCallback;
var symbolClose = PineJS.Std.close(this._context);
return [symbolClose];
};
},