We often use the built-in functions in TradingView Pine when coding. But we can also create our own functions. How to do that?

In this article:

Creating functions with the function declaration operator

Operators are an important part of what makes our scripts work. These code elements perform an operation on one or several values (Stephens, 2014). And the values that an operator ‘works on’ are what we call operands (Sharp, 2013). Common operators include the assignment operator, arithmetic operators, and the history referencing operator.

There’s also an advanced operator that lets us create functions: the function declaration operator (=>). A TradingView function is a segment of reusable code that performs a specific action each time we use it, like calculating a value. Built-in TradingView functions include ema(), which calculates the Exponential Moving Average (EMA), and highest() for returning the highest price for a certain number of bars (TradingView, n.d.).

You may know functions as subroutines or methods, as they have this name in other programming languages.

Functions make programming easier. That’s because we only need to code a function once, and then can use it as many times as we want in our script. This means we need less code, and that makes our script ‘cleaner’ and reduces the potential for programming errors. And if we change the function, its behaviour changes everywhere in the script where we used the function.

The function declaration operator (=>) can create single-line and multi-line functions (Pine Script Language Tutorial, n.d.). Let’s take a look at the theory and a practical example of each.

Creating a single-line function in TradingView Pine

The default pattern of creating a single-line function with => looks as follows (Pine Script Language Tutorial, n.d.):

FunctionName(comma-separated list of arguments) => expression

We first define the function’s name without any spaces in it (like FunctionName or MyCustomFunction). After the name we have an optional list of arguments, each separated with a comma.

An argument is a value that’s passed into a function (Pine Script Language Tutorial, n.d.). Inside the function, it then acts as a variable that we can calculate with. When we use the function (or ‘call’ it), then we need to provide the arguments.

For example, the built-in ema() function requires two arguments: the price data to calculate on and the moving average length in number of bars (TradingView, n.d.). And so whenever we use this function we need to type in the two values between its parentheses. So ema(close, 10), for instance, calculates the EMA based on closing prices of the last 10 bars.

After the argument list we type => followed by an expression, which is any statement that returns a value (Liberty & MacDonald, 2009). For example, 10 + 2 is an expression (it returns 12) but rsi(close, 20) also (it returns the 20-period RSI based on closing prices). The value of this expression is what’s returned by the function (Pine Script Language Tutorial, n.d.).

Tip: Don’t confuse the function declaration operator (=>) with the greater than or equal to comparison operator (>=). We create a custom function with the first operator, while the second checks if the value on its left is greater than or equal to the value on its right.

Calculating the EMA momentum with a single-line function

A practical example of a single-line function is the following:

study(title="Function declaration operator - 1")

momEMA(length, barsBack) => ema(close, length) - ema(close, length)[barsBack]

plot(series=momEMA(20, 10), color=blue, style=histogram, linewidth=3)
plot(series=momEMA(40, 10), color=red, style=histogram, linewidth=3)

hline(price=0, color=gray, linestyle=solid)

We first set the script’s title with the study() function. Then we create a single-line function that’s named momEMA():

momEMA(length, barsBack) => ema(close, length) - ema(close, length)[barsBack]

This function takes in two arguments: length and barsBack. The expression that’s immediately after the function declaration operator (=>) subtracts two Exponential Moving Averages (EMAs) from each other, and that result is what’s returned by the function.

The first of these EMAs calculates on closing prices (close) with a number of bars that’s set by the length argument. The second ema() function call uses the same values, but this time we shift the EMA value a certain number of bars to the past.

To do that ‘offsetting’ to the past, we place the barsBack argument between the square brackets ([ ]) of the history referencing operator. This way the ema(close, length) function doesn’t return the EMA value of the current bar, but this moving average value from the barsBack number of bars ago.

And so inside our custom function we subtract the EMA from barsBack ago from the current bar’s EMA. This way we end up with an EMA momentum that’s positive when the moving averages rises, and is negative when the current bar value of the EMA is less than the EMA of barsBack ago.

Then we plot the moving average’s momentum and the neutral line on the chart:

plot(series=momEMA(20, 10), color=blue, style=histogram, linewidth=3)
plot(series=momEMA(40, 10), color=red, style=histogram, linewidth=3)

hline(price=0, color=gray, linestyle=solid)

The plot() function plots the values of its series argument on the chart (TradingView, n.d.). Here we set that argument to our single-line function with 20 and 10 passed in as arguments (momEMA(20, 10)). This plots the 20-period EMA with a 10-bar momentum length. With the other arguments we set the plot’s colour to the blue basic TradingView colour, and give this histogram (style=histogram) a size of 3 (linewidth=3).

The second plot() statement is nearly the same, except that here we plot the 10-bar momentum of a 40-period EMA (momEMA(40, 10)) in the red standard colour on the chart.

We end with the hline() function to plot a horizontal line at the level specified by its price argument (TradingView, n.d.). We set that argument to 0, and that neutral line displays as a solid (linestyle=solid), grey (color=gray) line.

When we add this example to the chart, it looks like:

Example script that creates a custom, single-line function

Creating a multi-line function in TradingView Pine

With the function declaration operator (=>) we can also create multi-line functions that allow for coding more complex ideas. The default pattern of a multi-line function is (Pine Script Language Tutorial, n.d.):

FunctionName(comma-separated list of arguments) =>
    statement
    statement
    ... etc
    expression, variable, or variable declaration

We create a multi-line function just like we create a single-line function. So we specify the function’s name without spaces, and place two parentheses (( and )) behind the function name. Inside those parentheses we can optionally list the arguments that our function should use.

The difference with a single-line function is that, in a multi-line function, each line that’s placed after => needs to be indented with either 4 spaces or 1 tab (Pine Script Language Tutorial, n.d.). Due to that indentation TradingView knows which lines below to the function and which ones don’t.

The value that’s returned by a multi-line function is the function’s last line (Pine Script Language Tutorial, n.d.). That line can either be an expression (like x + 10), a variable (x), or a variable declaration (x = 10).

A multi-line function that checks if prices cross above an EMA

An example script that creates and uses a multi-line function is:

study(title="Function declaration operator - 2", overlay=true)

CrossAbove(price, length) =>
     emaValue = ema(price, length)
     above = (price > emaValue and price[1] < emaValue[1])
     above
    
plotshape(series=CrossAbove(close, 10), 
     style=shape.flag, location=location.abovebar, color=red)
plotshape(series=CrossAbove(high, 30),
     style=shape.flag, location=location.belowbar, color=blue)

plot(series=ema(close, 10), color=red)
plot(series=ema(high, 30), color=blue)

Here we first specify the indicator name with help of the study() function. We also set this function’s overlay argument to true to overlay the indicator on the chart’s instrument.

Then we create a multi-line function with the function declaration operator (=>):

CrossAbove(price, length) =>
     emaValue = ema(price, length)
     above = (price > emaValue and price[1] < emaValue[1])
     above

We name this function CrossAbove() and give it two arguments: price and length. The first holds price data (like a bar’s high, low, or close) while the length argument sets the EMA length.

In the function we create the emaValue variable. That variable is set with the assignment operator (=) to the value returned by ema() function, which uses the price and length values here. This way we calculate an EMA based on the arguments provided to the CrossAbove() function. This also shows that we can call a function (ema()) inside our user-made function (CrossAbove()).

The next line in our CrossAbove() function assigns the above variable a true/false value based on two expressions. The first checks whether the current value of the price variable is greater than (>) the EMA we’ve just calculated (emaValue). The second expression uses the history referencing operator ([]) to evaluate whether on the previous bar price was less than (<) that bar’s EMA value (price[1] < emaValue[1]).

Because we combine these expressions into one condition with the logical and operator, they both need to be true before the above variable is given a true value also (Pine Script Language Tutorial, n.d.). And when one or both of them are false, then the result that’s combined with and is false too.

We end the function with a line that simply contains the above variable. Given that’s the last statement of the function, the value of the above true/false variable is what’s returned by the function (Pine Script Language Tutorial, n.d.).

Next we use our custom function when plotting some shapes on the chart:

plotshape(series=CrossAbove(close, 10), 
     style=shape.flag, location=location.abovebar, color=red)
plotshape(series=CrossAbove(high, 30),
     style=shape.flag, location=location.belowbar, color=blue)

The plotshape() function draws a visual shape on the chart when its series argument is true on that bar (Pine Script Language Tutorial, n.d.; TradingView, n.d.).

The first plotshape() statement has its series argument set to our custom CrossAbove() function, which computes here with the close and 10 values. Given how we’ve coded that function, this returns true whenever the close crosses above the 10-period EMA. When that happens, the series argument of the plotshape() function is true and this function then draws a red flag (shape.flag) above that price bar (location.abovebar).

The second plotshape() function call plots a blue flag below the price bar (location.belowbar) on which the high crossed above the 30-period EMA of high prices. We check this latter condition with CrossAbove(high, 30).

We end the example by plotting the two EMAs:

plot(series=ema(close, 10), color=red)
plot(series=ema(high, 30), color=blue)

The plot() function displays a series of data on the chart, and that data shows as a continuous line by default (TradingView, n.d.).

Here we use plot() to plot a 10-period EMA based on closing prices and a 30-bar EMA of high prices on the chart. For this we set the series arguments of these different plot() function calls to ema(close, 10) and ema(high, 30). These plots display in the red and blue standard TradingView colours.

When we add the example to the chart, it looks like:

Creating a multi-line function in TradingView Pine

Here we see small flags whenever the bar’s close and/or high price reach the value of their exponential moving average.

Summary

With the function declaration operator (=>) we create single-line and multi-line functions. For both user-made functions we first type the function’s name and then a list of comma-separated arguments in parentheses before the => operator. After the function declaration operator we include one expression (for single-line functions) or several lines of code all indented with 5 spaces or 1 tab plus a space (for multi-line functions). The last expression in a single-line or multi-line function is the value that’s returned by the function.

Learn more:


References

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

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

Sharp, J. (2013). Microsoft Visual C# 2013 Step by Step. Microsoft Press.

Stephens, R. (2014). C# 5.0 Programmer Reference. Indianapolis, IN: John Wiley & Sons.

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