Skip to main content

Custom Libraries in Pine Script 📚

Creating Libraries

Basic Library Structure

//@version=5
library("TradingTools", overlay=true)

// Export functions using 'export' keyword
export getATR(length) =>
ta.atr(length)

export getRSI(length) =>
ta.rsi(close, length)

// Private helper function (not exported)
_normalizeValue(value, min, max) =>
(value - min) / (max - min)

Advanced Library Components

//@version=5
library("AdvancedIndicators", overlay=true)

// Library settings
maxLookback = 1000
defaultLength = 14

// Exported type definition
export type IndicatorSettings
int length
float multiplier
string method

// Exported function with custom type
export calculateBands(IndicatorSettings settings) =>
basis = ta.sma(close, settings.length)
dev = ta.stdev(close, settings.length) * settings.multiplier
[basis, basis + dev, basis - dev]

Using Libraries

Importing Libraries

//@version=5
strategy("Library Usage", overlay=true)

// Import libraries
import TradingTools/1 as tools
import AdvancedIndicators/1 as indicators

// Use library functions
atr = tools.getATR(14)
rsi = tools.getRSI(14)

// Create settings object
settings = indicators.IndicatorSettings.new()
settings.length = 20
settings.multiplier = 2.0
settings.method = "sma"

// Use advanced function
[middle, upper, lower] = indicators.calculateBands(settings)

Library Best Practices

Versioning and Documentation

//@version=5
// @version=1.0.0
// @author=Your Name
// @description=A collection of technical analysis tools
library("TechnicalTools", overlay=true)

//@function Calculates custom momentum indicator
//@param price Source price series
//@param length Lookback period
//@returns Momentum value between -100 and 100
export calculateMomentum(price, length) =>
change = price - price[length]
maxChange = ta.highest(math.abs(price - price[length]), length)
100 * change / maxChange

Error Handling in Libraries

//@version=5
library("SafeCalculations")

// Custom error type
export type CalcError
bool hasError
string message

// Safe calculation function
export safeDiv(float a, float b) =>
if na(a) or na(b)
[float(na), CalcError.new(true, "Invalid input")]
else if b == 0
[float(na), CalcError.new(true, "Division by zero")]
else
[a/b, CalcError.new(false, "")]

Advanced Library Features

Stateful Libraries

//@version=5
library("StatefulIndicators", overlay=true)

// State management
var float[] history = array.new_float(0)
var int maxSize = 100

// Exported functions that maintain state
export addValue(float value) =>
if array.size(history) >= maxSize
array.shift(history)
array.push(history, value)
array.size(history)

export getStats() =>
size = array.size(history)
avg = array.sum(history) / size
[size, avg]

Composite Libraries

//@version=5
library("CompositeAnalysis")

// Import other libraries
import TradingTools/1 as tools
import SafeCalculations/1 as calc

// Combine functionality
export analyzeMarket() =>
atr = tools.getATR(14)
rsi = tools.getRSI(14)

[value, error] = calc.safeDiv(rsi, atr)
value

Performance Optimization

Efficient Library Design

//@version=5
library("OptimizedCalc")

// Cache frequently used values
var float[] cache = array.new_float(100, 0.0)
var int cacheIndex = 0

// Optimized calculation with caching
export efficientCalc(float value) =>
if array.get(cache, cacheIndex) != value
array.set(cache, cacheIndex, value)
cacheIndex := (cacheIndex + 1) % 100

result = 0.0
for i = 0 to 99
result += array.get(cache, i)
result / 100

Testing Libraries

Library Test Suite

//@version=5
indicator("Library Tests")

// Import library to test
import TradingTools/1 as tools

// Test cases
testRSI() =>
rsi = tools.getRSI(14)
rsi >= 0 and rsi <= 100

testATR() =>
atr = tools.getATR(14)
not na(atr) and atr >= 0

// Run tests
var bool[] testResults = array.new_bool(0)
array.push(testResults, testRSI())
array.push(testResults, testATR())
Library Development Tips
  • Keep functions focused and modular
  • Document all exported functions
  • Handle edge cases and errors
  • Use meaningful naming conventions
  • Test thoroughly before publishing
Common Library Issues

❌ Excessive global state ❌ Poor error handling ❌ Insufficient documentation ❌ Inefficient calculations ❌ Tight coupling between components

Next Steps

Ready to learn about integrating with external systems? Move on to the next chapter! 🚀