A common feature of TradingView indicators is plotting values in the same chart area as the instrument. How do we programmatically specify where a script displays?

In this article:

Programmatically placing a TradingView indicator on the price chart

In TradingView we set a script’s characteristics, like its name and how it should display on the chart, with the study() function (Pine Script Language Tutorial, n.d.). This function is the only function that always needs to be included in an indicator’s source code, and its title argument (which sets the indicator’s name) is something that always needs to be defined too (TradingView, n.d.).

Another argument of study() is overlay. With this optional argument set to true, the script is overlaid on the chart’s instrument. That makes the indicator show up in the same chart area as where the instrument’s price bars display. When we set overlay to false the indicator plots in a separate chart panel (Pine Script Language Tutorial, n.d.). For example:

study(title="My example script", overlay=false)

The default value of the overlay argument is false (TradingView, n.d.), meaning that indicators are displayed in a separate chart panel whenever the overlay argument isn’t set.

Note: The overlay argument of the study() function only accepts literal Boolean values (like overlay=true). It cannot be set to a built-in or user-defined bool variable nor can the overlay argument work with a Boolean input variable.
Tip: When a script was applied to the chart before the overlay argument was added to the study() function or before this argument had its value changed, then the indicator needs to be removed and re-added to the chart to see the effect of the updated code.

The overlay argument has a few noteworthy features:

  • Each indicator, regardless of the range of its values, can be overlaid on the main data series. When an indicator’s values are different than the scale used by the instrument itself, we can specify the indicator’s price scale programmatically to prevent the instrument’s scale from being distorted.
  • It’s not possible to programmatically define the subchart in which the indicator should display when overlay is set to false. We need to do this manually with the ‘move up’ ( ) and ‘move down’ ( ) icons that are displayed in the top right of the indicator’s chart panel.
  • While most TradingView functions are affected by the overlay argument, not all are. barcolor(), for instance, always colours the instrument’s price bars regardless of whether the overlay argument is true or false.

Let’s look at a programming example to see how overlay works in practice.

Plotting a TradingView volume histogram in a separate chart panel

In the example below we plot a volume histogram with the highest and average volume plotted as lines. First we’ll display this indicator in a separate chart panel while later on we’ll overlay the indicator on the price chart. After discussing the code we’ll look at how the indicator looks on the chart and what its input options are.

study(title="Volume histogram", overlay=false)

// Inputs
highestLen = input(title="Highest Length", type=integer, defval=25)
averageLen = input(title="Average Length", type=integer, defval=10)

// Compute values
highestVol = highest(volume, highestLen)[1]
averageVol = sma(volume, averageLen)

// Determine histogram bar colour
histColour = (volume > highestVol) ? orange :
    (volume > averageVol) ? #7B68EE :
    #4169E1

// Plot the values on the chart
plot(series=volume, style=histogram, 
    color=histColour, linewidth=5)
plot(series=highestVol, color=red)
plot(series=averageVol, color=green)

We begin with the study() function that’s required to be added to every TradingView indicator (TradingView, n.d.). Two of this function’s arguments are set: title to define the indicator’s name and overlay that, when set to false, displays the indicator in a separate chart panel.

Then we add two input options to the script:

highestLen = input(title="Highest Length", type=integer, defval=25)
averageLen = input(title="Average Length", type=integer, defval=10)

Inputs are made with input(), a function that add an option to the script’s settings but that also returns the option’s current value (Pine Script Language Tutorial, n.d.). Here we store those values in the highestLen and averageLen variables with the assignment operator. This way we can refer to the input’s current value later on in the script’s code by using the variable.

Both inputs are numerical integer inputs. These accept whole numbers only and are made by setting the type argument of the input() function to integer (Pine Script Language Tutorial, n.d.).

The first input is named “Highest Length” with the title argument, and this name is what’s displayed before the input option (see image further down below). We set this input to a default value (defval) of 25, and use this input (stored in the highestLen variable) later on when computing the highest volume.

The other input is named “Average Length” and starts off with a value of 10 (defval=10). This input, with its current value stored in the averageLen variable, is used when calculating the average volume.

Then we compute the indicator’s values:

highestVol = highest(volume, highestLen)[1]
averageVol = sma(volume, averageLen)

Here we create two variables: highestVol and averageVol. The first is assigned the value returned by highest(), a function that works with two arguments: a series of values to process and the number of bars to get the highest value of (TradingView, n.d.). Here those arguments are set to the bar’s volume (volume) and highestLen, the input variable that we gave a default value of 25.

We place the history referencing operator ([]) behind the highest() function with a value of 1 between its square brackets. We do that because the volume built-in variable series also includes the current bar’s volume. This means that, should we compute the 25-bar highest volume up to and including the current bar, then the current bar’s volume can never rise above that highest volume value.

And so what we do here with the history referencing operator is to ‘offset’ the value that’s returned by highest() with 1 bar to the past. This way the highestVol variable doesn’t hold the highest volume including the current bar, but the highest volume of the 25 bars leading up to the current bar.

The second variable that we make here (averageVol) is set to the value returned by sma(). That function calculates the Simple Moving Average (SMA) with two arguments: a series of values to process and the number of bars to compute the moving average on (TradingView, n.d.). Here those arguments are set to volume and averageLen, the input variable that we gave a standard value of 10 earlier.

With the indicator’s values calculated, we determine the volume histogram’s colour:

histColour = (volume > highestVol) ? orange :
    (volume > averageVol) ? #7B68EE :
    #4169E1

The histColour variable is assigned a conditional colour with the help of two conditional (ternary) operators (?:). That operator works on three values, with the first being a true/false condition. Whenever that condition evaluates to true, the conditional operator returns its second value; otherwise, its third value is returned (Pine Script Language Tutorial, n.d.).

The first conditional operator evaluates whether the volume of the current bar (volume) is greater than (>) the highest volume of the last 25 bars (a value we stored in the highestVol variable). This also shows why we didn’t want the highestVol variable to include the current bar’s volume – this condition would never satisfy otherwise. When the condition is true, this conditional operator returns the orange basic TradingView colour and we store that colour in the histColour variable for use later on.

However, the second conditional operator is processed whenever the current bar’s volume isn’t greater than the highest volume. That second conditional operator then checks whether the volume is above the 10-bar average (volume > averageVol). If that’s the case, this conditional operator returns the #7B68EE hexadecimal colour of medium slate blue (and that colour is then stored in the histColour variable).

But if the condition of the second conditional operator is false too, then this latter operator returns the #4169E1 hexadecimal colour of royal blue, which we then assign to the histColour variable. So what we’re doing here is setting that variable to an orange, slate blue, or royal blue colour depending on the bar’s volume. We then use that variable when plotting the volume histogram:

plot(series=volume, style=histogram, 
    color=histColour, linewidth=5)
plot(series=highestVol, color=red)
plot(series=averageVol, color=green)

The volume histogram is made with plot(), a function that plots the data of its series argument on the chart (TradingView, n.d.). In the first plot() statement we set that argument to volume. And with the style argument set to histogram that volume displays as histogram bars.

The color argument of the plot() function defines the plot’s colour, and here we set that argument to histColour – the variable that we set to one of three colours earlier. To make these histogram bars more noticeable we set their size to 5 with the linewidth argument.

The two other plot() statements display the highest and average volume on the chart. For this we set their series argument to the highestVol and averageVol variables. Since we don’t specify the style argument here, these values are plotted with a consecutive line by default (TradingView, n.d.). The colour of these lines is set to the red and green basic TradingView colours.

Plotting the volume with in a separate chart panel

When we add the above example indicator to a chart of the German DAX Index CFD, the volume histogram looks like:

Example of the TradingView indicator added to the chart

Here see that the histogram is coloured orange for bars that reached a new volume high. Histogram bars with an above-average volume are coloured slate blue while all the other bars are just coloured blue.

The indicator has these input options:

Example of the TradingView indicator's input settings

When we change these inputs to a highest high of 45 and an average length of 22 bars, then the previous chart changes to:

Settings of the TradingView indicator changed

Now let’s look at how this indicator behaves when we overlay it on top of the chart’s instrument.

Plotting a TradingView indicator on the chart’s instrument

To plot the indicator in the same chart panel as the chart’s instrument, we only need to change the first line of the programming example. That line with the study() function is changed to:

study(title="Volume histogram", overlay=true, precision=0)

We make two adjustments here. First, the overlay argument is set to true to make the indicator plot in the same chart area as the instrument (TradingView, n.d.). The other difference is changing the indicator’s decimal precision by setting the precision argument to 0. That way the indicator’s values aren’t showed with 4 decimals (the default precision, which we see in the previous images) but with zero decimals instead (TradingView, n.d.).

Then we save the script without making other code modifications. The indicator refreshes on the chart and then looks like:

TradingView indicator didn't change after changing its settings programmatically

While the price axis is indeed changed here (no values after the floating point anymore), the indicator is not overlaid on the chart’s instrument. That’s because changing the overlay argument, when the script is already added to the chart, requires that we remove and re-add the indicator to the chart.

When we do that, the updated indicator displays on the DAX 30 Index CFD:

Updated TradingView indicator skews the price chart

This brings us to another issue: the price scale is distorted since the volume values (around 500-1,500) are much lower than the values of the DAX index (around 9,500). To have the indicator overlay properly, it needs to use the left price axis. That way the right price axis can be used for the instrument’s values.

To set the script to the left axis, we right-click one of the indicator plots and select ‘Scale Left’:

Enabling the left price scale in TradingView

That changes the chart and the indicator to:

TradingView indicator successfully placed on the chart's instrument
Tip: The indicator’s scale can be set programmatically with the scale argument of the study() function. That way we don’t need to define this setting manually every time. See specifying an indicator’s scale programmatically for more.

One remaining issue is that the volume values don’t display on the price axis given that the chart’s left price axis is disabled by default. To change that, we right-click on the right price axis and select ‘Left Axis’:

Enabling the left scale on a TradingView chart

Now our chart has two price axes: one with the indicator’s values and another one with the instrument’s prices.

Example of a TradingView chart with both price axes enabled

To learn more about setting indicator settings programmatically, see specifying an indicator’s maximum number of bars back and setting the name of an indicator programmatically.

Summary

study() is the only function that needs to be added to every TradingView indicator. This function sets the indicator’s properties with several arguments, including the required title and the optional overlay. That latter argument affects where the indicator displays: when overlay is set to true, the indicator is overlaid on the chart’s instrument. And when this argument is set to false or simply not present as a study() argument in the script’s code, then the indicator shows in a separate chart panel below the chart’s instrument. When the script is already on the chart when we change or add the overlay argument, then we need to remove and re-add the script in order to see the updated code.


References

Pine Script Language Tutorial (n.d.). Retrieved on February 24, 2016, from https://docs.google.com/document/d/1sCfC873xJEMV7MGzt1L70JTStTE9kcG2q-LDuWWkBeY/

TradingView (n.d.). Script Language Reference Manual. Retrieved on March 1, 2016, from https://www.tradingview.com/study-script-reference/