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)
returnValueThe 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)