Pine Optimizer

TradersPost/pinescript-agents/.claude/skills/pine-optimizer

作者 TradersPostebc382f88b6103fcda2569fe666a38b00fe714c5無授權條款收錄於 2026年10月9日更新於 2026年10月9日

Optimizes Pine Script for performance, user experience, and visual appeal on TradingView. Use when improving script speed, reducing load time, enhancing UI, organizing inputs, improving colors and visuals, or making scripts more user-friendly. Triggers on "optimize", "improve", "faster", "better UX", "clean up", or enhancement requests.

AI 產生的概覽

指導優化 TradingView Pine Script 的速度、使用者體驗與視覺呈現。

功能
提供 Pine Script v6 優化指引,涵蓋計算快取、以元組進行的 request.security 呼叫、迴圈與條件調校,以及記憶體處理。也涉及使用者體驗與視覺改善,例如輸入項目的條件顯示、輸入分組、配色方案、線型,以及適合行動裝置的版面。內容包含前後對照的程式碼範例、檢查清單與快速優化對照表。
適用情境
適用於提升 Pine Script 指標或策略的效能、載入速度或回應速度。也適合在整理輸入項目、顏色、繪圖、表格或警示時,讓 TradingView 使用體驗更完善。
執行需求
不隨附指令碼或工具,僅為說明性指引。使用方需了解 Pine Script v6 與 TradingView 平台。

Pine Script Optimizer

Specialized in enhancing script performance, user experience, and visual presentation on TradingView.

Pine Script v6 2025 Optimization Features

July 2025: Input active Parameter - UX Game Changer

Create conditional input visibility for cleaner UI:

pinescript
// ✅ BEFORE: All inputs always visible (cluttered)maType = input.string("EMA", "MA Type", options=["SMA", "EMA", "Custom"])customLength = input.int(20, "Custom Length")  // Always visible
// ✅ AFTER: Conditional visibility (clean UX)maType = input.string("EMA", "MA Type", options=["SMA", "EMA", "Custom"])customLength = input.int(20, "Custom Length",    active=(maType == "Custom"),  // Only shown when Custom selected    tooltip="Only available when MA Type is 'Custom'")
// Advanced mode patternshowAdvanced = input.bool(false, "Show Advanced Settings", group="Settings")advSetting1 = input.int(10, "Advanced 1", group="Advanced", active=showAdvanced)advSetting2 = input.float(1.5, "Advanced 2", group="Advanced", active=showAdvanced)advSetting3 = input.bool(true, "Advanced 3", group="Advanced", active=showAdvanced)

September 2025: Plot Line Styles

More visual options without custom drawing:

pinescript
// Use built-in line styles for cleaner visualsplot(sma20, "SMA 20", color.blue, linestyle=plot.linestyle_solid)plot(sma50, "SMA 50", color.red, linestyle=plot.linestyle_dashed)plot(support, "Support", color.green, linestyle=plot.linestyle_dotted)
// Combine with conditional displayshowProjections = input.bool(true, "Show Projections")plot(showProjections ? projection : na, "Projection",    color.new(color.yellow, 50),    linestyle=plot.linestyle_dotted)

February 2025: Unlimited Scopes

No longer limited to 550 scopes - enables more complex, modular code:

pinescript
// Now possible: deeply nested logic without scope errorstype ComplexType    float value1    float value2    array<float> history
method process(ComplexType this) =>    if this.value1 > 0        if this.value2 > 0            for i = 0 to array.size(this.history) - 1                if array.get(this.history, i) > 0                    // Deep nesting now allowed                    // Previously would hit 550 scope limit

March 2025: Use for...in for Collections

The preferred and safest way to iterate over collections:

pinescript
// ✅ BEST: Use for...in for arrays (safest, cleanest)for element in myArray    // Process element directly - no boundary issues
// ✅ BEST: Use for...in with index when neededfor [index, element] in myArray    // Have both index and value
// ✅ Works with matrices (iterates rows as arrays)for row in myMatrix    for value in row        // Process each value
// ✅ Works with maps (key-value pairs in insertion order)for [key, value] in myMap    // Process key-value pair

FALLBACK: Cache boundary if traditional for is required:

pinescript
// ❌ SLOW/DANGEROUS: Re-evaluates array.size() every iterationfor i = 0 to array.size(arr) - 1    // Can cause infinite loop if array modified
// ✅ FALLBACK: Cache boundary if you need traditional forarrSize = array.size(arr)for i = 0 to arrSize - 1    // process

August 2025: Longer Strings (40,960 chars)

Build more comprehensive info panels:

pinescript
// Now possible: detailed multi-section reportsreport = "═══════════════════════════════\n"report += "      STRATEGY REPORT         \n"report += "═══════════════════════════════\n\n"report += "PERFORMANCE METRICS\n"report += "───────────────────\n"report += "Win Rate: " + str.tostring(winRate, "#.##") + "%\n"report += "Profit Factor: " + str.tostring(pf, "#.##") + "\n"// ... can now include much more detail

⚠️ CRITICAL: UDT-First Code Organization

The single biggest optimization you can make is using UDT-first architecture. This eliminates parallel arrays, simplifies drawing management, and removes bar_index clamping code.

Before vs After: Parallel Arrays vs UDT

pinescript
// ❌ BEFORE: 6+ parallel arrays (hard to maintain, error-prone)var array<float> slopes = array.new<float>()var array<float> intercepts = array.new<float>()var array<float> stdDevs = array.new<float>()var array<int> startBars = array.new<int>()var array<int> endBars = array.new<int>()var array<line> centerLines = array.new<line>()// Must keep ALL arrays in sync - easy to have bugs!
// Push to ALL arrays when adding itemarray.push(slopes, newSlope)array.push(intercepts, newIntercept)array.push(stdDevs, newStdDev)array.push(startBars, newStartBar)array.push(endBars, newEndBar)// Forgot to push to centerLines? Bug!
// ✅ AFTER: Single UDT array (clean, self-documenting)type Regression    float slope    float intercept    float stdDev    int startTime      // Use TIME, not bar_index!    int endTime    int startBarIndex  // Keep for Y calculations    int endBarIndex    line centerLine = na
var array<Regression> regressions = array.new<Regression>()
// One push, all data togethernewReg = Regression.new(slope=newSlope, intercept=newIntercept, ...)array.push(regressions, newReg)

Performance Gain: xloc.bar_time Eliminates Clamping

pinescript
// ❌ BEFORE: Clamping code everywhere (slow, complex)leftBar = math.max(0, bar_index - startOffset)  // Clamp to valid rangeif bar_index - startBar > 5000    leftBar := bar_index - 5000  // Historical buffer limit!line.set_x1(myLine, leftBar)
// ✅ AFTER: xloc.bar_time has NO limit - just draw!line.new(startTime, y1, endTime, y2, xloc=xloc.bar_time)// No clamping needed! Works for ANY historical bar!

UDT Methods for DRY Drawing Code

pinescript
// ❌ BEFORE: Repeated drawing blocks (~50+ lines each)// Block for original regression drawingif showOriginal    if not na(origCenterLine)        line.delete(origCenterLine)    origCenterLine := line.new(...)    // ... 20 more lines
// Block for live regression drawing (duplicate code!)if showLive    if not na(liveCenterLine)        line.delete(liveCenterLine)    liveCenterLine := line.new(...)    // ... 20 more duplicate lines
// ✅ AFTER: Single method, reuse everywhere (~30 lines total)method draw(Regression this, color baseColor, int width) =>    this.delete()  // Clean up old    startY = this.calculateY(this.startBarIndex)    endY = this.calculateY(this.endBarIndex)    this.centerLine := line.new(this.startTime, startY, this.endTime, endY,         xloc=xloc.bar_time, color=baseColor, width=width)
// Use anywhere - no duplication!originalRegression.draw(origColor, 2)liveRegression.draw(liveColor, 2)for reg in chainedRegressions    reg.draw(chainedColor, 1)

UDT Optimization Metrics

MetricParallel ArraysUDT Architecture
Array declarations6-101
Drawing code blocks5+ (duplicated)1 method
Clamping code4+ locations0
Lines of code400+~150
Bug riskHigh (sync issues)Low
Historical lookback5000 bars maxUnlimited

UDT Time Capture Pattern

pinescript
// ALWAYS capture BOTH time and bar_index when events occurvar int eventStartTime = navar int eventStartBar = na
if eventDetected    eventStartTime := time        // For xloc.bar_time drawing    eventStartBar := bar_index    // For Y calculation (slope * bar + intercept)
// Later, create UDT with bothnewItem = MyType.new(    startTime = eventStartTime,      // Drawing coordinate    startBarIndex = eventStartBar,   // Calculation coordinate    ...)

Core Optimization Areas

1. Calculation Caching

pinescript
// ❌ BEFORE: Repeated calculationsplot(ta.sma(close, 20) > ta.sma(close, 50) ? high : low)bgcolor(ta.sma(close, 20) > ta.sma(close, 50) ? color.green : color.red)
// ✅ AFTER: Cache once, use many timessma20 = ta.sma(close, 20)sma50 = ta.sma(close, 50)bullish = sma20 > sma50plot(bullish ? high : low)bgcolor(bullish ? color.new(color.green, 90) : color.new(color.red, 90))

2. Security Call Optimization

pinescript
// ❌ BEFORE: Multiple security() calls (expensive)htfClose = request.security(syminfo.tickerid, "D", close)htfHigh = request.security(syminfo.tickerid, "D", high)htfLow = request.security(syminfo.tickerid, "D", low)htfVolume = request.security(syminfo.tickerid, "D", volume)
// ✅ AFTER: Single tuple call[htfClose, htfHigh, htfLow, htfVolume] = request.security(    syminfo.tickerid, "D",    [close, high, low, volume])

3. Loop Optimization (Use for...in)

pinescript
// ❌ SLOW/DANGEROUS: Boundary re-evaluated each iterationfor i = 0 to array.size(arr) - 1    val = array.get(arr, i)    // process
// ✅ BEST: Use for...in (safe, clean, preferred)for element in arr    // Process element directly - no boundary issues
// ✅ BEST: With index when neededfor [i, element] in arr    // Have both index and value
// ✅ FASTEST: Use built-in array methods when possibletotal = array.sum(arr)maxVal = array.max(arr)avgVal = array.avg(arr)

4. Conditional Logic Optimization

pinescript
// ❌ SLOW: All conditions evaluatedsignal = cond1 and cond2 and cond3 and expensiveCalc()
// ✅ FAST: Short-circuit with cheap checks firstsignal = cond1  // Cheapest firstsignal := signal and cond2signal := signal and cond3signal := signal and expensiveCalc()  // Only if others pass

User Experience Optimization

1. Input Organization with Active Parameter

pinescript
// Professional input structure with conditional visibility
// === Main Settings ===strategyMode = input.string("Trend Following", "Strategy Mode",    options=["Trend Following", "Mean Reversion", "Custom"],    group="Strategy")
// === Trend Following Settings (conditional) ===tfLength = input.int(20, "Trend Length",    group="Trend Following",    active=(strategyMode == "Trend Following"),    tooltip="Period for trend detection")
tfMultiplier = input.float(2.0, "Trend Multiplier",    group="Trend Following",    active=(strategyMode == "Trend Following"))
// === Mean Reversion Settings (conditional) ===mrLength = input.int(14, "Reversion Length",    group="Mean Reversion",    active=(strategyMode == "Mean Reversion"))
mrThreshold = input.float(2.0, "Reversion Threshold",    group="Mean Reversion",    active=(strategyMode == "Mean Reversion"))
// === Visual Settings ===showPlots = input.bool(true, "Show Plots", group="Visual")plotColor = input.color(color.blue, "Plot Color",    group="Visual",    active=showPlots)  // Only show when plots enabled

2. Professional Color Schemes

pinescript
// Modern, accessible color palettevar color BULL = color.new(#26a69a, 0)      // Teal greenvar color BEAR = color.new(#ef5350, 0)      // Coral redvar color BULL_BG = color.new(#26a69a, 85)  // Transparentvar color BEAR_BG = color.new(#ef5350, 85)var color NEUTRAL = color.new(#787b86, 0)   // Gray
// Gradient based on strengthstrength = ta.rsi(close, 14)gradientColor = color.from_gradient(strength, 30, 70, BEAR, BULL)
// Dark mode friendly tablevar table infoTable = table.new(position.top_right, 2, 5,    bgcolor=color.new(#131722, 10),  // TradingView dark bg    border_color=color.new(#363a45, 0),    border_width=1)

3. Responsive Plot Styling with Line Styles

pinescript
// Use new linestyle parameter for visual hierarchyma = ta.ema(close, maLength)maPlot = plot(ma, "MA", color.blue, linewidth=2,    linestyle=plot.linestyle_solid)  // Primary: solid
// Secondary indicators: dashedplot(upperBand, "Upper", color.gray,    linestyle=plot.linestyle_dashed)plot(lowerBand, "Lower", color.gray,    linestyle=plot.linestyle_dashed)
// Projections/targets: dottedplot(showTargets ? target : na, "Target", color.green,    linestyle=plot.linestyle_dotted)

4. Smart Alert Messages

pinescript
// Comprehensive alert with all relevant infobuildAlert(direction, price, strength) =>    msg = "🔔 " + syminfo.ticker + " ALERT\n"    msg += "═══════════════════\n"    msg += "Direction: " + direction + "\n"    msg += "Price: $" + str.tostring(price, "#,###.##") + "\n"    msg += "Strength: " + str.tostring(strength, "#.#") + "/10\n"    msg += "Time: " + str.format_time(time, "yyyy-MM-dd HH:mm") + "\n"    msg += "═══════════════════"    msg
alertcondition(buySignal,    "Buy Signal",    buildAlert("LONG", close, signalStrength))

Performance Checklist

Architecture (Check First!)

  • Use UDT-first for complex data structures
  • Replace parallel arrays with single UDT array
  • Use xloc.bar_time for drawings (eliminates clamping)
  • Store time + bar_index for each coordinate
  • Add methods to UDT for encapsulated logic

Must-Do Optimizations

  • Cache all repeated calculations
  • Combine security() calls into tuples
  • Cache loop boundaries (March 2025 critical)
  • Put cheap conditions before expensive ones
  • Use var for values that don't change per bar

UX Optimizations (2025 Features)

  • Use active parameter for conditional inputs
  • Group related inputs logically
  • Add tooltips to complex inputs
  • Use new linestyle parameter for visual hierarchy
  • Implement mobile-friendly compact mode option

Visual Optimizations

  • Use consistent color scheme
  • Implement gradient colors for strength
  • Use appropriate plot line widths
  • Add transparency to background colors
  • Make tables dark-mode friendly

Mobile-Friendly Optimization

pinescript
// Compact mode for mobile viewingcompactMode = input.bool(false, "📱 Compact Mode",    group="Display",    tooltip="Enable for better mobile viewing")
// Adjust based on modeplotWidth = compactMode ? 1 : 2labelSize = compactMode ? size.tiny : size.small
// Conditional table displayif not compactMode    // Full table with details    table.cell(infoTable, 0, 0, "Full Statistics", text_color=color.white)    // ... more cellselse    // Minimal display    table.cell(infoTable, 0, 0, bullish ? "↑" : "↓",        text_color=bullish ? BULL : BEAR,        text_size=size.large)

Memory Optimization

pinescript
// Use var for persistent valuesvar float highestHigh = navar int barsSinceSignal = 0
// Limit array sizesvar array<float> recentPrices = array.new<float>(100)if barstate.isconfirmed    array.push(recentPrices, close)    if array.size(recentPrices) > 100        array.shift(recentPrices)
// Clear unused dataif newDay    array.clear(intradayData)

Optimization Quick Wins

IssueBeforeAfterImpact
Parallel arrays6+ arrays to sync1 UDT array80% less code
bar_index drawingClamping + 5000 limitxloc.bar_timeUnlimited lookback
Drawing codeDuplicate blocksUDT methodsDRY, maintainable
Repeated SMAta.sma(close,20) x5Cache in variable5x faster
Multiple security()4 separate calls1 tuple call4x faster
Loop boundaryarray.size(arr) in loopCache before loopPrevents hang
All inputs visibleCluttered UIUse active paramClean UX
One line styleAll solidsolid/dashed/dottedBetter hierarchy

The top 3 optimizations (UDT-related) provide the biggest gains. Balance optimization with readability. Don't over-optimize at the expense of maintainability.

來源與署名

來源:TradersPost/pinescript-agents位於.claude/skills/pine-optimizer提交ebc382f

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架