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! 🚀