Skip to content

Functions and methods ​

When the same calculation appears more than once in a script, how do you write it once? Declare a function: a name, its parameters in parentheses, =>, and a body. Then call it by name as you call a built-in, passing what changes as arguments. A function can hand back several values at once.

pine
//@version=6
indicator("Bands from one function", overlay = true)
// A channel around a moving average, written once.
bands(float src, int len = 20, float mult = 2.0) =>
    float mid = ta.sma(src, len)
    float dev = mult * ta.stdev(src, len)
    [mid + dev, mid, mid - dev]       // the last line is the result
[upper, mid, lower] = bands(close, mult = 1.5) // len keeps its default
plot(upper, "Upper")
plot(mid, "Middle")
plot(lower, "Lower")

Declaring a function ​

A declaration sits at the top level of the script, on its own lines. A body of one expression can follow => on the same line, as in double(float x) => x * 2. A longer body goes on the lines below, each indented one level, and it ends where the indentation does. The last line's value is what a call gives back. There is no return.

Inside the body you can declare variables, branch, loop and call other functions. The names a body declares belong to it, so two functions can each have their own mid. A body can also read the script's variables.

Declare a function, and the variables its body reads, above the lines that use them, since TradingView reads a script from the top down. Here a later declaration runs too, so the slip only shows when the script moves to TradingView.

Parameters and arguments ​

A parameter can have a type, as in float src, and a qualifier before it, as in simple int len, which says the value can't change from bar to bar. A parameter with no type takes whatever the call passes: add(a, b) => a + b adds two numbers or joins two strings. Type a parameter unless the function is meant for several types, so a wrong argument shows at the call.

A default makes a parameter optional, as len = 20 does above. In Pine the default has to be known before the script runs: a literal, na, or a built-in name such as close or color.red. TradingView refuses a default worked out from other values, such as close * 2. Strict Pine refuses it with "has non-literal default", and AmenoScript accepts it.

A call passes its arguments in order, and it can name any of them: bands(close, mult = 1.5) sets mult and leaves len at its default. Named arguments can come in any order, as in bands(mult = 1.0, src = close).

WARNING

Once a call names an argument, name every argument after it. A plain value after a named one is dropped here without an error, so f(1.0, b = 3.0, 4.0) leaves the third parameter at its default.

Giving back several values ​

End the body with a tuple, as [mid + dev, mid, mid - dev] does, and the call gives back all of its values. Read them with a tuple of names on the left, one name for each value: [upper, mid, lower] = bands(close). Each name is then an ordinary variable.

What a function can't do ​

A function can't change a variable declared outside it with :=. Return the new value instead and assign it where you call the function. A function can still change what an outer array, matrix, map or object holds, because that changes the thing the variable refers to and not the variable: array.push(seen, close) in a function works.

A function can't call plot() or the other calls that draw a series: plotshape, plotchar, hline, fill, bgcolor and barcolor. Those belong at the top level. Labels, lines, boxes and tables can be made anywhere, a function included.

A function can't hold the declaration of another function. Declare each one at the top level.

TradingView refuses all three when it compiles the script, so write them its way, as above. Pine compatibility lists them with the other scope rules.

Methods ​

A method is a function you call with a dot on its first argument. Write method before the declaration and give the first parameter a type. That parameter is the receiver, and its type is what the method attaches to: a built-in type such as float or array<float>, or a type of your own.

pine
//@version=6
indicator("Distance from the last pivot high")
// Each method attaches to the type of its first parameter.
method pctFrom(float self, float base) => (self - base) / base * 100
method lastOr(array<float> self, float otherwise) =>
    self.size() > 0 ? self.last() : otherwise
var array<float> highs = array.new<float>()
if not na(ta.pivothigh(high, 3, 3))
    highs.push(high[3])                // a built-in function as a method
float ref = highs.lastOr(close)
plot(close.pctFrom(ref), "% from last pivot high")

close.pctFrom(ref) and pctFrom(close, ref) are the same call, so a method can be called either way. In Pine a method needs at least one parameter, its receiver. A method with none is AmenoScript only, and strict Pine refuses it.

The built-in functions of arrays, matrices, maps, strings and drawings are methods too, picked by the receiver's type. highs.push(x) is array.push(highs, x), s.upper() is str.upper(s), and lbl.set_text("x") is label.set_text(lbl, "x").

Types and enums shows methods on a type of your own, which is how a library gives its types behaviour.

Two functions with one name ​

Two functions can share a name when their parameters differ in type, as twice(int x) => x * 2 and twice(string s) => s + s do. Each call runs the one whose parameter types fit its arguments.

Each call keeps its own state ​

Every place a script calls a function keeps its own copy of what the function remembers: its ta.* values, its var variables and the past that x[1] reads. So bands(close) and bands(high) keep two averages, not one, and a function called inside an if counts only the bars the if ran. State in functions and branches has the rules and the traps.

What AmenoScript adds ​

Traps ​

  • A call in a branch. A function called in an if, a ternary, or on the right of and or or runs only on the bars that reach it, and its ta.* calls see only those bars. See branches.
  • An untyped parameter. It takes the call's type, so a function meant for prices also runs, without complaint, on whatever else you pass it.
  • A plain value after a named one is dropped, as the warning above says.

See also ​

AmenoScript is compatible with Pine Script v6. Pine Script is a trademark of TradingView, Inc., which has no part in AmenoScript.