Overview
A Pine Script library packages reusable functions that can be imported by indicators and strategies. Use libraries to avoid copy-pasting the same math into every script. Shared logic in a library means a bug fix applies to every consumer with one version bump, rather than requiring a manual edit in every script that copied the code. This mirrors the DRY principle in general-principles. Libraries cannot contain plot(), strategy.*, or input.* calls; they export pure functions only.
Declare with library() and set exportable functions
The library() call at the top declares the script as a library. Every exported function must have a // @function annotation so TradingView can generate hover documentation.
//@version=5
// @description Volatility and position-sizing utilities
library("VolUtils", overlay=false)
// @function Computes ATR-based stop distance
// @param src Series to compute ATR from
// @param atrLen ATR period
// @param multiplier ATR multiplier for stop distance
// @returns Stop distance in price units
export atrStop(series float src, simple int atrLen, simple float multiplier) =>
ta.atr(atrLen) * multiplierThe export keyword makes the function visible to importers. Functions without export are private to the library. Use private functions for shared intermediate calculations that callers do not need directly.
Type function parameters explicitly
Type annotations are required for exported functions. They prevent silent type coercion that can cause incorrect values at runtime.
Pine types for parameters:
series float/series int/series bool: bar-by-bar series (most common)simple float/simple int/simple bool: single value, evaluated once per script execution, not per barinput float/input int/input bool: value comes from aninput.*call in the callerconst float/const int/const bool: compile-time constant
Use simple int for length parameters like ATR period. Using series int on a length argument that changes bar-by-bar causes a runtime error in built-in functions like ta.atr.
Return typed tuples for multi-value functions
Functions can return multiple values as a tuple. Annotate the return type for clarity:
// @function Returns upper and lower Keltner Channel bands
// @param src Price source series
// @param emalen EMA period
// @param atrlen ATR period
// @param mult ATR multiplier
// @returns [upper, mid, lower]
export keltner(series float src, simple int emalen, simple int atrlen, simple float mult) =>
mid = ta.ema(src, emalen)
band = ta.atr(atrlen) * mult
[mid + band, mid, mid - band]Callers destructure the return:
[kUpper, kMid, kLower] = vol.keltner(close, 20, 14, 1.5)Publish and version the library before importing
Libraries must be published (even as private scripts) before they can be imported. The version number in the import statement is the major version. Increment the major version when you change function signatures in a breaking way; patch-level changes do not change the import line.
// To publish: TradingView Editor → Publish → Script library
// The published URL contains the username and script nameImport in a consumer script:
//@version=5
indicator("My Indicator", overlay=true)
import yourUsername/VolUtils/1 as vol
stopDist = vol.atrStop(close, 14, 2.0)The alias (vol) scopes all library calls. Use a short alias that matches the library name. Avoid lib as a generic alias; it becomes ambiguous when importing multiple libraries.
Test the library before publishing
Pine has no unit test framework, but you can write a companion indicator that calls every exported function and plots the results:
//@version=5
indicator("VolUtils Test", overlay=false)
import yourUsername/VolUtils/1 as vol
// Call each function and plot to verify visually
stopDist = vol.atrStop(close, 14, 2.0)
[u, m, l] = vol.keltner(close, 20, 14, 1.5)
plot(stopDist, "Stop dist", color=color.red)
plot(u, "Kelt upper", color=color.blue)
plot(m, "Kelt mid", color=color.gray)
plot(l, "Kelt lower", color=color.blue)Visual inspection catches obvious errors. Cross-check against known values on a stable instrument (SPY daily, for example) where the ATR is predictable over a specific date range.
Document every exported function
TradingView renders // @function, // @param, and // @returns annotations in the hover tooltip and in the script’s description. Users of your library read these without opening the source.
Write the // @description at the top of the file for the library-level summary. Write per-function annotations immediately above each export function. See pine-script-indicators for the user-facing perspective on documentation: the same principle applies here, where the exported API is the contract.