Functions#

When a piece of logic needs to be reused in a script, you can encapsulate it into a function. Functions make code more concise, readable, and easier to maintain.

Defining a Function#

Pine Script function definition syntax:

functionName(param1, param2) =>
    // function body (indented)
    returnValue

The value on the last line is automatically used as the return value (no return keyword needed).

Simple example — calculate the average of two values:

//@version=6
indicator("Function Demo")

// Define the function
average(a, b) =>
    (a + b) / 2

// Call the function
midPrice = average(high, low)
plot(midPrice, "Mid Price", color=color.orange)

Default Parameter Values#

Function parameters can have default values, allowing the caller to omit them:

//@version=6
indicator("Default Parameters")

// length defaults to 14
myRSI(src, length = 14) =>
    ta.rsi(src, length)

// Use default length=14
plot(myRSI(close))

// Specify length=7
plot(myRSI(close, 7), color=color.orange)

Multi-Line Functions#

A function body can contain multiple lines of code, separated by indentation:

//@version=6
indicator("Multi-Line Function", overlay=true)

// Determine bar type and return a color
barTypeColor() =>
    bodySize  = math.abs(close - open)
    rangeSize = high - low
    ratio     = rangeSize > 0 ? bodySize / rangeSize : 0

    if ratio > 0.7
        color.new(close > open ? color.green : color.red, 0)  // Large body: strong bar
    else if ratio > 0.3
        color.new(color.gray, 50)  // Medium body
    else
        color.new(color.gray, 80)  // Long wicks: indecisive bar

barcolor(barTypeColor())

Returning Multiple Values#

A function can return multiple values as a tuple; use [a, b] destructuring to receive them:

//@version=6
indicator("Multiple Return Values", overlay=true)

// Return both highest and lowest close prices
highLowClose(length) =>
    h = ta.highest(close, length)
    l = ta.lowest(close, length)
    [h, l]

// Destructure to receive values
[channelHigh, channelLow] = highLowClose(20)

plot(channelHigh, "Channel High", color=color.green)
plot(channelLow,  "Channel Low",  color=color.red)
fill(plot(channelHigh, display=display.none),
     plot(channelLow,  display=display.none),
     color=color.new(color.blue, 90))

Function Limitations#

Pine Script user-defined functions have several important restrictions:

  • No recursion: Functions cannot call themselves directly or indirectly
  • Cannot modify global variables: Functions can read global variables but cannot assign to them (:=)
  • Cannot call certain built-in functions: indicator(), strategy(), barcolor(), bgcolor(), alertcondition(), etc. can only be called at the global scope, not inside user-defined functions

method — Type Methods#

Pine Script supports methods, allowing user-defined functions to be called with . syntax for a more object-oriented style:

//@version=6
indicator("method Demo")

// Define a method for the array<float> type
method normalize(array<float> arr) =>
    minVal = array.min(arr)
    maxVal = array.max(arr)
    result = array.new<float>()
    for val in arr
        normalized = maxVal != minVal ? (val - minVal) / (maxVal - minVal) : 0.0
        array.push(result, normalized)
    result

// Call using . syntax
prices = array.from(close, close[1], close[2], close[3], close[4])
normalizedPrices = prices.normalize()

plot(array.get(normalizedPrices, 0), "Normalized Close")

Practical Example: Encapsulating MACD Signal#

//@version=6
indicator("Encapsulated MACD Signal", overlay=false)

// Encapsulate MACD calculation and return three values
calcMACD(src, fastLen, slowLen, signalLen) =>
    fastMA   = ta.ema(src, fastLen)
    slowMA   = ta.ema(src, slowLen)
    macdLine = fastMA - slowMA
    sigLine  = ta.ema(macdLine, signalLen)
    hist     = macdLine - sigLine
    [macdLine, sigLine, hist]

// Call the function
[macd, signal, histogram] = calcMACD(close, 12, 26, 9)

plot(macd,      "MACD",      color=color.blue)
plot(signal,    "Signal",    color=color.orange)
plot(histogram, "Histogram", style=plot.style_histogram,
     color=histogram >= 0 ? color.green : color.red)

Reference#