# Pine Script v6 Documentation Pine Script is TradingView's proprietary programming language designed for creating custom technical analysis indicators, strategies, and alerts on financial charts. It enables traders and developers to build sophisticated trading tools that execute on TradingView's servers, analyzing market data in real-time and on historical data. The language features a specialized type system with qualifiers (const, input, simple, series) that determine when values are available during script execution, making it uniquely suited for time-series financial data processing. The core functionality centers around three main script types: indicators for visualization and analysis, strategies for backtesting trading systems, and libraries for sharing reusable code. Pine Script provides extensive built-in functions for technical analysis (moving averages, oscillators, pattern recognition), data requests from multiple symbols and timeframes, visual drawing tools (lines, labels, boxes, tables), and alert systems for automated notifications. Version 6 is the current latest version, offering the most advanced features including enhanced type system controls, dynamic requests, and comprehensive charting capabilities. ## Script Declaration Declares the script type and sets global properties for indicators, strategies, or libraries. ```pine //@version=6 indicator("My Indicator", shorttitle="MI", overlay=true, format=format.price, precision=2) // Or for a strategy //@version=6 strategy("My Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100) // Or for a library //@version=6 // @description Provides utility functions for technical analysis library("MyLibrary", overlay=true) ``` ## Input Functions Creates user-configurable inputs that appear in the script's Settings/Inputs tab, allowing customization without code changes. ```pine //@version=6 indicator("Input Demo", overlay=true) // Integer input with constraints lengthInput = input.int(14, "RSI Length", minval=1, maxval=100, step=1, tooltip="Period for RSI calculation") // Float input with options dropdown factorInput = input.float(1.5, "BB Factor", options=[1.0, 1.5, 2.0, 2.5, 3.0]) // Boolean toggle showMAInput = input.bool(true, "Show Moving Average", inline="ma_settings", group="Display Options") maColorInput = input.color(color.blue, "MA Color", inline="ma_settings", group="Display Options") // String selection maTypeInput = input.string("SMA", "MA Type", options=["SMA", "EMA", "WMA", "VWMA"]) // Source input (allows selecting price or another indicator's output) sourceInput = input.source(close, "Source") // Symbol and timeframe inputs symbolInput = input.symbol("AAPL", "Symbol") tfInput = input.timeframe("1D", "Timeframe") // Time input with interactive confirmation startTimeInput = input.time(timestamp("2024-01-01"), "Start Date", confirm=true) // Apply inputs rsi = ta.rsi(sourceInput, lengthInput) ma = switch maTypeInput "SMA" => ta.sma(close, lengthInput) "EMA" => ta.ema(close, lengthInput) "WMA" => ta.wma(close, lengthInput) "VWMA" => ta.vwma(close, lengthInput) plot(rsi, "RSI") plot(showMAInput ? ma : na, "MA", maColorInput) ``` ## Plot Functions Displays data series on the chart with various styles including lines, histograms, columns, and shapes. ```pine //@version=6 indicator("Plot Demo", overlay=false) // Basic line plot rsi = ta.rsi(close, 14) plot(rsi, "RSI", color.blue, linewidth=2) // Conditional coloring rsiColor = rsi > 70 ? color.red : rsi < 30 ? color.green : color.gray plot(rsi, "Colored RSI", rsiColor, style=plot.style_line) // Histogram style with base reference volumeChange = ta.change(volume) plot(volumeChange, "Volume Change", volumeChange > 0 ? color.green : color.red, style=plot.style_histogram) // Columns style (like volume bars) plot(volume, "Volume", color.new(color.blue, 70), style=plot.style_columns) // Area plot plot(rsi, "RSI Area", color.new(color.purple, 80), style=plot.style_area, histbase=50) // Step line plot(ta.highest(high, 20), "Highest", color.orange, style=plot.style_stepline) // Circles and crosses for discrete points bullishCross = ta.crossover(rsi, 30) bearishCross = ta.crossunder(rsi, 70) plot(bullishCross ? rsi : na, "Buy Signal", color.lime, style=plot.style_circles, linewidth=4) plot(bearishCross ? rsi : na, "Sell Signal", color.red, style=plot.style_cross, linewidth=4) // Plot with display control plot(rsi, "Hidden Plot", display=display.none) // Calculated but not shown // Horizontal reference lines hline(70, "Overbought", color.red, linestyle=hline.style_dashed) hline(30, "Oversold", color.green, linestyle=hline.style_dashed) hline(50, "Midline", color.gray) ``` ## Technical Analysis Functions Built-in functions for calculating common technical indicators including moving averages, oscillators, and volatility measures. ```pine //@version=6 indicator("TA Functions Demo", overlay=true) length = input.int(14, "Length") src = input.source(close, "Source") // Moving Averages smaValue = ta.sma(src, length) // Simple Moving Average emaValue = ta.ema(src, length) // Exponential Moving Average wmaValue = ta.wma(src, length) // Weighted Moving Average vwmaValue = ta.vwma(src, length) // Volume Weighted MA almaValue = ta.alma(src, length, 0.85, 6) // Arnaud Legoux MA // Oscillators rsiValue = ta.rsi(src, length) // Relative Strength Index [macdLine, signalLine, histLine] = ta.macd(src, 12, 26, 9) // MACD stochK = ta.stoch(close, high, low, length) // Stochastic %K cciValue = ta.cci(src, length) // Commodity Channel Index mfiValue = ta.mfi(hlc3, length) // Money Flow Index // Volatility atrValue = ta.atr(length) // Average True Range trValue = ta.tr // True Range (current bar) [bbMiddle, bbUpper, bbLower] = ta.bb(src, length, 2.0) // Bollinger Bands // Trend Detection risingTrend = ta.rising(src, length) // True if rising over length bars fallingTrend = ta.falling(src, length) // True if falling over length bars crossOver = ta.crossover(emaValue, smaValue) // True when first crosses above second crossUnder = ta.crossunder(emaValue, smaValue) // True when first crosses below second // Highest/Lowest highestHigh = ta.highest(high, length) // Highest high over length bars lowestLow = ta.lowest(low, length) // Lowest low over length bars highestBarOffset = ta.highestbars(high, length) // Bars since highest (negative) // Cumulative and Running cumVolume = ta.cum(volume) // Cumulative sum changeValue = ta.change(src) // Difference from previous bar percentRank = ta.percentrank(src, length) // Percentile rank // Plot selected indicators plot(smaValue, "SMA", color.blue) plot(emaValue, "EMA", color.red) plot(bbUpper, "BB Upper", color.gray) plot(bbLower, "BB Lower", color.gray) ``` ## Strategy Functions Functions for creating backtestable trading strategies with entry, exit, and position management. ```pine //@version=6 strategy("Strategy Demo", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10) // Inputs fastLength = input.int(10, "Fast MA") slowLength = input.int(20, "Slow MA") stopLossPercent = input.float(2.0, "Stop Loss %") takeProfitPercent = input.float(4.0, "Take Profit %") // Calculate indicators fastMA = ta.sma(close, fastLength) slowMA = ta.sma(close, slowLength) // Entry conditions longCondition = ta.crossover(fastMA, slowMA) shortCondition = ta.crossunder(fastMA, slowMA) // Entry orders with custom alert messages if longCondition strategy.entry("Long", strategy.long, alert_message="Long entry at " + str.tostring(close)) if shortCondition strategy.entry("Short", strategy.short, alert_message="Short entry at " + str.tostring(close)) // Exit with stop loss and take profit longStopPrice = strategy.position_avg_price * (1 - stopLossPercent / 100) longTakeProfitPrice = strategy.position_avg_price * (1 + takeProfitPercent / 100) shortStopPrice = strategy.position_avg_price * (1 + stopLossPercent / 100) shortTakeProfitPrice = strategy.position_avg_price * (1 - takeProfitPercent / 100) if strategy.position_size > 0 strategy.exit("Long Exit", "Long", stop=longStopPrice, limit=longTakeProfitPrice) if strategy.position_size < 0 strategy.exit("Short Exit", "Short", stop=shortStopPrice, limit=shortTakeProfitPrice) // Close all positions if ta.crossover(ta.rsi(close, 14), 80) strategy.close_all("RSI Overbought") // Access strategy metrics // strategy.position_size - Current position size // strategy.position_avg_price - Average entry price // strategy.opentrades - Number of open trades // strategy.closedtrades - Number of closed trades // strategy.netprofit - Net profit // Plot plot(fastMA, "Fast MA", color.green) plot(slowMA, "Slow MA", color.red) plotshape(longCondition, "Buy", shape.triangleup, location.belowbar, color.green) plotshape(shortCondition, "Sell", shape.triangledown, location.abovebar, color.red) ``` ## Alert Functions Creates alert conditions and triggers for real-time notifications when specific conditions are met. ```pine //@version=6 indicator("Alert Demo", overlay=true) // Calculate indicators rsi = ta.rsi(close, 14) sma20 = ta.sma(close, 20) sma50 = ta.sma(close, 50) // Detect conditions goldenCross = ta.crossover(sma20, sma50) deathCross = ta.crossunder(sma20, sma50) rsiOverbought = ta.crossover(rsi, 70) rsiOversold = ta.crossunder(rsi, 30) // alert() function - Modern approach, works in indicators and strategies // Supports dynamic messages and multiple frequencies if goldenCross alert("Golden Cross detected! Price: " + str.tostring(close) + ", RSI: " + str.tostring(rsi, "#.##"), alert.freq_once_per_bar) if deathCross alert("Death Cross detected! Price: " + str.tostring(close), alert.freq_once_per_bar_close) // Alert for any significant move if math.abs(ta.change(close) / close[1]) > 0.02 alert("Price moved more than 2%", alert.freq_all) // alertcondition() function - Legacy approach, indicators only // Creates selectable conditions in the alert dialog // Message must be constant string, but can use placeholders alertcondition(goldenCross, "Golden Cross Alert", "SMA20 crossed above SMA50. Close: {{close}}") alertcondition(deathCross, "Death Cross Alert", "SMA20 crossed below SMA50. Close: {{close}}") alertcondition(rsiOverbought, "RSI Overbought", "RSI crossed above 70. RSI value: {{plot_0}}") alertcondition(rsiOversold, "RSI Oversold", "RSI crossed below 30") // Compound condition alert alertcondition(goldenCross and rsi < 50, "Golden Cross + RSI Low", "Bullish signal confirmed") // Plot for reference in alertcondition placeholders plot(rsi, "RSI", display=display.none) plot(sma20, "SMA20", color.green) plot(sma50, "SMA50", color.red) ``` ## Arrays One-dimensional collections for storing multiple values of the same type with dynamic sizing. ```pine //@version=6 indicator("Array Demo", overlay=true) // Array declaration and creation var array prices = array.new(0) // Empty array using var for persistence var pricesLegacy = array.new_float(0) // Legacy syntax (deprecated) var colors = array.from(color.red, color.green, color.blue) // Create with initial values // Add elements if barstate.isconfirmed array.push(prices, close) // Add to end // array.unshift(prices, close) // Add to beginning // array.insert(prices, 0, close) // Insert at index // Limit array size (keep last 100 values) if array.size(prices) > 100 array.shift(prices) // Remove first element // Read elements if array.size(prices) > 0 firstPrice = array.get(prices, 0) // Get first lastPrice = array.get(prices, -1) // Get last (negative index) // Or use methods: // firstPrice = prices.first() // lastPrice = prices.last() // Modify elements if array.size(prices) > 0 array.set(prices, 0, close) // Set value at index // Array statistics if array.size(prices) >= 10 avgPrice = array.avg(prices) // Average maxPrice = array.max(prices) // Maximum minPrice = array.min(prices) // Minimum sumPrice = array.sum(prices) // Sum medianPrice = array.median(prices) // Median stdDev = array.stdev(prices) // Standard deviation plot(avgPrice, "Avg Price", color.purple) plot(maxPrice, "Max Price", color.green) plot(minPrice, "Min Price", color.red) // Search and check if array.size(prices) > 0 hasValue = array.includes(prices, close) // Check if value exists idx = array.indexof(prices, close) // Find index of value (-1 if not found) // Sorting var sortedPrices = array.copy(prices) // Create copy array.sort(sortedPrices, order.ascending) // Sort ascending // array.reverse(sortedPrices) // Reverse order // Loop through array string info = "" for i = 0 to math.min(array.size(prices) - 1, 4) info += str.tostring(array.get(prices, i), "#.##") + "\n" // Alternative: for...in loop // for price in prices // info += str.tostring(price) + "\n" // Display if barstate.islast label.new(bar_index, high, "Last 5 prices:\n" + info) ``` ## Request Functions Retrieves data from different symbols, timeframes, or financial data sources. ```pine //@version=6 indicator("Request Demo", overlay=true) // Request data from higher timeframe dailyClose = request.security(syminfo.tickerid, "1D", close) weeklyHigh = request.security(syminfo.tickerid, "1W", high) // Request from different symbol btcClose = request.security("BINANCE:BTCUSDT", timeframe.period, close) spyClose = request.security("SPY", "1D", close) // Request with custom expression (calculated on the requested timeframe) dailyRSI = request.security(syminfo.tickerid, "1D", ta.rsi(close, 14)) dailyBB = request.security(syminfo.tickerid, "1D", ta.bb(close, 20, 2.0)) // Request multiple values using tuple [dailyOpen, dailyHigh, dailyLow, dailyCloseVal] = request.security(syminfo.tickerid, "1D", [open, high, low, close]) // Non-repainting higher timeframe request indexHighTF = barstate.isrealtime ? 1 : 0 indexCurrTF = barstate.isrealtime ? 0 : 1 nonRepaintingDaily = request.security(syminfo.tickerid, "1D", close[indexHighTF])[indexCurrTF] // Request from lower timeframe (returns array) lowTFCloses = request.security_lower_tf(syminfo.tickerid, "1", close) if array.size(lowTFCloses) > 0 avgLowTF = array.avg(lowTFCloses) // Request with gaps control dailyWithGaps = request.security(syminfo.tickerid, "1D", close, gaps=barmerge.gaps_on) dailyNoGaps = request.security(syminfo.tickerid, "1D", close, gaps=barmerge.gaps_off) // Extended session data extendedTicker = ticker.modify(syminfo.tickerid, session=session.extended) extendedClose = request.security(extendedTicker, timeframe.period, close) // Financial data requests if timeframe.period == "1D" earnings = request.earnings(syminfo.tickerid, earnings.actual) dividends = request.dividends(syminfo.tickerid, dividends.gross) // Plot plot(dailyClose, "Daily Close", color.blue, linewidth=2) plot(nonRepaintingDaily, "Non-Repainting Daily", color.orange) plotcandle(dailyOpen, dailyHigh, dailyLow, dailyCloseVal) ``` ## Drawing Functions Creates visual elements on the chart including lines, labels, boxes, and tables. ```pine //@version=6 indicator("Drawing Demo", overlay=true, max_lines_count=500, max_labels_count=500) // Lines var line trendLine = na if barstate.islast // Delete old line and create new line.delete(trendLine) trendLine := line.new(bar_index - 20, low[20], bar_index, low, color=color.blue, width=2, style=line.style_solid) // Horizontal line extending both directions if ta.crossover(close, ta.sma(close, 50)) line.new(bar_index, close, bar_index + 1, close, extend=extend.both, color=color.green, style=line.style_dashed) // Labels if ta.crossover(ta.rsi(close, 14), 30) label.new(bar_index, low, "Oversold\nRSI: " + str.tostring(ta.rsi(close, 14), "#.#"), style=label.style_label_up, color=color.green, textcolor=color.white, size=size.normal, yloc=yloc.belowbar) if ta.crossunder(ta.rsi(close, 14), 70) label.new(bar_index, high, "Overbought", style=label.style_label_down, color=color.red, textcolor=color.white, yloc=yloc.abovebar) // Boxes (rectangles) var box supportBox = na if barstate.islast box.delete(supportBox) float support = ta.lowest(low, 20) float resistance = ta.highest(high, 20) supportBox := box.new(bar_index - 20, resistance, bar_index, support, border_color=color.purple, bgcolor=color.new(color.purple, 90), border_width=2, border_style=line.style_dashed) // Tables (fixed position on chart) var table infoTable = table.new(position.top_right, 2, 4, bgcolor=color.new(color.gray, 80)) if barstate.islast table.cell(infoTable, 0, 0, "Metric", text_color=color.white, text_halign=text.align_left) table.cell(infoTable, 1, 0, "Value", text_color=color.white, text_halign=text.align_right) table.cell(infoTable, 0, 1, "Price", text_color=color.white) table.cell(infoTable, 1, 1, str.tostring(close, format.mintick), text_color=color.green) table.cell(infoTable, 0, 2, "RSI", text_color=color.white) table.cell(infoTable, 1, 2, str.tostring(ta.rsi(close, 14), "#.##"), text_color=color.yellow) table.cell(infoTable, 0, 3, "Volume", text_color=color.white) table.cell(infoTable, 1, 3, str.tostring(volume, format.volume), text_color=color.blue) // Polylines (connected series of points) var polyline pl = na if barstate.islast polyline.delete(pl) points = array.new() for i = 0 to 9 array.push(points, chart.point.from_index(bar_index - i * 5, high[i * 5])) pl := polyline.new(points, line_color=color.orange, line_width=2) ``` ## User-Defined Functions Creates reusable custom functions to encapsulate calculations and logic. ```pine //@version=6 indicator("User Functions Demo", overlay=true) // Single-line function sma(src, len) => ta.sma(src, len) // Multi-line function with documentation //@function Calculates a custom oscillator based on price momentum //@param source The source series //@param fastLen Fast period length //@param slowLen Slow period length //@returns The oscillator value between -100 and 100 customOsc(float source, int fastLen, int slowLen) => fastMA = ta.ema(source, fastLen) slowMA = ta.ema(source, slowLen) momentum = fastMA - slowMA normalized = 100 * momentum / slowMA math.max(-100, math.min(100, normalized)) // Function returning multiple values (tuple) //@function Calculates Bollinger Bands //@returns Tuple of [middle, upper, lower] calcBB(float src, int length, float mult) => basis = ta.sma(src, length) dev = mult * ta.stdev(src, length) [basis, basis + dev, basis - dev] // Function with default parameters emaWithDefault(float src, int length = 20) => ta.ema(src, length) // Function using method syntax declaration //@function Checks if value is within range method inRange(float val, float lower, float upper) => val >= lower and val <= upper // Recursive-like pattern using var //@function Calculates all-time high allTimeHigh(float source) => var float ath = source ath := math.max(ath, source) ath // Using the functions osc = customOsc(close, 12, 26) [bbMiddle, bbUpper, bbLower] = calcBB(close, 20, 2.0) ema20 = emaWithDefault(close) ema50 = emaWithDefault(close, 50) ath = allTimeHigh(high) // Using method syntax rsi = ta.rsi(close, 14) inNeutralZone = rsi.inRange(40.0, 60.0) // Plot plot(osc, "Custom Osc", color.purple) plot(bbMiddle, "BB Middle", color.gray) plot(bbUpper, "BB Upper", color.blue) plot(bbLower, "BB Lower", color.blue) plot(ath, "All Time High", color.green, style=plot.style_stepline) bgcolor(inNeutralZone ? color.new(color.gray, 90) : na) ``` ## Libraries Creates reusable, shareable functions that can be imported into other Pine scripts. ```pine //@version=6 // @description Provides utility functions for technical analysis and risk management library("TradingUtils", overlay=true) // Exported function - must declare parameter types //@function Calculates position size based on risk percentage //@param accountSize Total account size //@param riskPercent Risk percentage per trade (e.g., 2.0 for 2%) //@param entryPrice Entry price //@param stopPrice Stop loss price //@returns Position size in units export calcPositionSize(float accountSize, float riskPercent, float entryPrice, float stopPrice) => riskAmount = accountSize * (riskPercent / 100) priceRisk = math.abs(entryPrice - stopPrice) priceRisk > 0 ? riskAmount / priceRisk : 0.0 // Exported function returning simple values (for use in non-series contexts) //@function Creates a formatted ticker ID string export makeTickerId(simple string exchange, simple string symbol) => exchange + ":" + symbol // Exported user-defined type //@type Represents a trade signal //@field direction 1 for long, -1 for short, 0 for neutral //@field strength Signal strength from 0 to 100 //@field price Suggested entry price export type TradeSignal int direction = 0 float strength = 0.0 float price = na // Exported function using custom type //@function Generates a trade signal based on RSI export generateRSISignal(float rsiValue, float overbought = 70.0, float oversold = 30.0) => signal = TradeSignal.new() if rsiValue < oversold signal.direction := 1 signal.strength := (oversold - rsiValue) / oversold * 100 else if rsiValue > overbought signal.direction := -1 signal.strength := (rsiValue - overbought) / (100 - overbought) * 100 signal // Demo usage in the library itself posSize = calcPositionSize(10000, 2.0, close, close * 0.95) signal = generateRSISignal(ta.rsi(close, 14)) if barstate.islast label.new(bar_index, high, "Position Size: " + str.tostring(posSize, "#.##") + "\nSignal: " + str.tostring(signal.direction)) ``` ```pine // Example: Importing and using a library in another script //@version=6 indicator("Using Library Demo", overlay=true) // Import the library (username/libraryName/version as alias) import TradingView/TradingUtils/1 as utils // Use exported functions accountSize = input.float(10000, "Account Size") riskPercent = input.float(2.0, "Risk %") stopDistance = input.float(0.02, "Stop Distance %") entryPrice = close stopPrice = close * (1 - stopDistance) positionSize = utils.calcPositionSize(accountSize, riskPercent, entryPrice, stopPrice) // Use exported type and function rsi = ta.rsi(close, 14) signal = utils.generateRSISignal(rsi) // Display if barstate.islast label.new(bar_index, high, "Pos Size: " + str.tostring(positionSize, "#.##") + "\nDirection: " + str.tostring(signal.direction) + "\nStrength: " + str.tostring(signal.strength, "#.#") + "%") ``` ## String Functions Functions for manipulating and formatting text strings. ```pine //@version=6 indicator("String Demo") // String creation and concatenation symbol = syminfo.ticker tf = timeframe.period info = "Symbol: " + symbol + " | TF: " + tf // str.format() - Powerful formatting with placeholders price = close change = ta.change(close) changePercent = change / close[1] * 100 formatted = str.format("Price: {0,number,#.##} | Change: {1,number,percent}", price, changePercent / 100) // Number formatting options priceStr = str.format("{0,number,#.####}", close) // 4 decimals intStr = str.format("{0,number,integer}", 123.456) // Rounds to integer currencyStr = str.format("{0,number,currency}", 1234.56) // $1,234.56 percentStr = str.format("{0,number,percent}", 0.1234) // 12% // str.tostring() - Simple conversion priceString = str.tostring(close) // Default formatting priceFormatted = str.tostring(close, "#.##") // Custom format priceFixed = str.tostring(close, format.mintick) // Symbol's tick precision volumeStr = str.tostring(volume, format.volume) // Abbreviated volume (1.5M) // Time formatting timeStr = str.format_time(time, "yyyy-MM-dd HH:mm", syminfo.timezone) dateOnly = str.format_time(time, "MMM dd, yyyy", "UTC") // String inspection and manipulation length = str.length(symbol) // Character count upper = str.upper(symbol) // UPPERCASE lower = str.lower(symbol) // lowercase hasUSD = str.contains(symbol, "USD") // Check substring startsBTC = str.startswith(symbol, "BTC") // Check prefix endsUSDT = str.endswith(symbol, "USDT") // Check suffix // String search and extraction pos = str.pos(symbol, "BTC") // Find position (-1 if not found) sub = str.substring(symbol, 0, 3) // Extract substring // String splitting and joining parts = str.split("BTC,ETH,SOL", ",") // Split into array joined = array.join(parts, " | ") // Join array to string // Replace replaced = str.replace(symbol, "USDT", "USD", 0) // Replace first occurrence replacedAll = str.replace_all(info, "|", "-") // Replace all occurrences // Display var label infoLabel = label.new(na, na, "") if barstate.islast label.set_xy(infoLabel, bar_index, high) label.set_text(infoLabel, formatted + "\n" + "Time: " + timeStr + "\n" + "Volume: " + volumeStr) ``` ## Maps (Dictionaries) Key-value data structures for associating unique keys with values. ```pine //@version=6 indicator("Map Demo", overlay=true) // Create a map var map priceMap = map.new() var map signalMap = map.new() // Put values if barstate.isfirst map.put(priceMap, "support", ta.lowest(low, 20)) map.put(priceMap, "resistance", ta.highest(high, 20)) map.put(priceMap, "pivot", (high + low + close) / 3) map.put(signalMap, 1, "Strong Buy") map.put(signalMap, 0, "Neutral") map.put(signalMap, -1, "Strong Sell") // Update values each bar map.put(priceMap, "current", close) map.put(priceMap, "sma20", ta.sma(close, 20)) // Get values support = map.get(priceMap, "support") resistance = map.get(priceMap, "resistance") currentSMA = map.get(priceMap, "sma20") // Check if key exists hasSupport = map.contains(priceMap, "support") // Get all keys and values keys = map.keys(priceMap) // Returns array values = map.values(priceMap) // Returns array // Map size numEntries = map.size(priceMap) // Remove entry // removedValue = map.remove(priceMap, "pivot") // Clear all entries // map.clear(priceMap) // Put all from another map var map additionalLevels = map.new() map.put(additionalLevels, "fib382", close * 0.382) map.put(additionalLevels, "fib618", close * 0.618) map.put_all(priceMap, additionalLevels) // Iterate over map using keys if barstate.islast info = "Price Levels:\n" for key in keys value = map.get(priceMap, key) info += key + ": " + str.tostring(value, "#.##") + "\n" label.new(bar_index, high, info) // Plot levels plot(nz(support), "Support", color.green, style=plot.style_stepline) plot(nz(resistance), "Resistance", color.red, style=plot.style_stepline) ``` ## Matrix Functions Two-dimensional data structures for advanced mathematical operations and data organization. ```pine //@version=6 indicator("Matrix Demo") // Create matrices var matrix priceMatrix = matrix.new(3, 4, 0.0) // 3 rows, 4 columns, filled with 0 var matrix signals = matrix.new(2, 2) // 2x2, filled with na // Set individual values if barstate.isfirst matrix.set(priceMatrix, 0, 0, open) // row 0, col 0 matrix.set(priceMatrix, 0, 1, high) // row 0, col 1 matrix.set(priceMatrix, 0, 2, low) // row 0, col 2 matrix.set(priceMatrix, 0, 3, close) // row 0, col 3 // Get values val = matrix.get(priceMatrix, 0, 0) // Matrix dimensions rows = matrix.rows(priceMatrix) // 3 cols = matrix.columns(priceMatrix) // 4 elements = matrix.elements_count(priceMatrix) // 12 // Fill entire matrix or region matrix.fill(signals, 0) // Fill all with 0 matrix.fill(signals, 1, 0, 1, 0, 1) // Fill region [0:1, 0:1] with 1 // Row and column operations row0 = matrix.row(priceMatrix, 0) // Get row as array col0 = matrix.col(priceMatrix, 0) // Get column as array matrix.add_row(priceMatrix, 0, array.from(1.0, 2.0, 3.0, 4.0)) // Insert row at index matrix.add_col(priceMatrix, 0, array.from(1.0, 2.0, 3.0)) // Insert column at index // Statistical functions (for numeric matrices) var m = matrix.new(2, 2) if barstate.isfirst matrix.set(m, 0, 0, 1) matrix.set(m, 0, 1, 2) matrix.set(m, 1, 0, 3) matrix.set(m, 1, 1, 4) maxVal = matrix.max(m) // Maximum value minVal = matrix.min(m) // Minimum value avgVal = matrix.avg(m) // Average sumVal = matrix.sum(m) // Sum medVal = matrix.median(m) // Median // Matrix operations var m2 = matrix.copy(m) // Create copy transposed = matrix.transpose(m) // Transpose // product = matrix.mult(m, m2) // Matrix multiplication // inverse = matrix.inv(m) // Inverse (if exists) // det = matrix.det(m) // Determinant // Reshape and resize // matrix.reshape(m, 1, 4) // Reshape to 1x4 // matrix.resize(m, 3, 3, 0.0) // Resize to 3x3, fill new with 0 // Sort matrix.sort(m, 0, order.ascending) // Sort by column 0 // Display matrix if barstate.islast label.new(bar_index, high, "Matrix:\n" + str.tostring(m) + "\nMax: " + str.tostring(maxVal) + "\nAvg: " + str.tostring(avgVal)) ``` ## Type System and Qualifiers Pine Script uses type qualifiers (const, input, simple, series) to control when values are available and whether they can change. ```pine //@version=6 indicator("Type System Demo", overlay=true) // CONST - Known at compile time, never changes const string INDICATOR_TITLE = "My Indicator" const int DEFAULT_LENGTH = 14 const float PI = 3.14159 // INPUT - Set before script runs, doesn't change during execution // Returned by input.*() functions lengthInput = input.int(DEFAULT_LENGTH, "Length") sourceInput = input.source(close, "Source") // SIMPLE - Determined on first bar, constant thereafter // Most syminfo.* and timeframe.* variables simple string symbol = syminfo.ticker simple string exchange = syminfo.prefix simple int barCount = syminfo.type == "crypto" ? 100 : 50 // SERIES - Can change on every bar (most flexible) // All price data, calculations, etc. series float price = close series float sma = ta.sma(close, lengthInput) series bool crossUp = ta.crossover(close, sma) // Type hierarchy (weaker → stronger): const < input < simple < series // A parameter accepting "simple" also accepts "const" and "input" // A parameter accepting "series" accepts all qualifiers // Explicit type declarations float myFloat = 1.5 int myInt = 10 bool myBool = true string myString = "text" color myColor = color.red // Array type declaration array myArray = array.new(0) // User-defined type type PriceLevel float price string label color lineColor = color.gray // Create instance var PriceLevel support = PriceLevel.new(price=ta.lowest(low, 20), label="Support", lineColor=color.green) // na (Not Available) - represents missing/undefined value float maybePrice = close > open ? close : na plot(maybePrice) // Plots nothing when na // Check for na if not na(maybePrice) label.new(bar_index, maybePrice, "Valid") // nz() - Replace na with default float safePrice = nz(maybePrice, 0.0) // Use 0 if na // Type casting int rounded = int(close) // float to int (truncates) float asFloat = float(bar_index) // int to float string priceStr = str.tostring(close) // to string bool isUp = bool(close > open ? 1 : 0) // int to bool ``` Pine Script v6 provides a comprehensive platform for creating sophisticated trading tools on TradingView. The main use cases include developing custom technical indicators that combine multiple analysis techniques, building and backtesting automated trading strategies with detailed performance metrics, creating alert systems for real-time trade notifications, and publishing reusable libraries for the trading community. The language's time-series-native design makes it particularly effective for financial analysis where historical patterns inform current decisions. Integration patterns typically involve combining multiple data sources using request.security() for multi-timeframe analysis, creating modular code with user-defined functions and libraries, and building interactive dashboards using tables and dynamic drawings. Scripts can be designed to work together through the library import system, allowing teams to share standardized calculations while individual traders customize the presentation and alert logic. The strong typing system with qualifiers ensures reliable execution, while the extensive built-in function library covers most technical analysis needs without external dependencies.