traderspost/pinescript-agents1 file

Pine Optimizer

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.

Specification
Skill ID
traderspost/pinescript-agents/pine-optimizer
Publisher
traderspost
Repository
pinescript-agents
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

traderspost/pinescript-agents/pine-optimizerInstalls these files
  • SKILL.md

What this skill tells the agent

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:

// ✅ 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 pattern
showAdvanced = 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:

// Use built-in line styles for cleaner visuals
plot(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 display
showProjections = 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:

// Now possible: deeply nested logic without scope errors
type 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:

// ✅ 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 needed
for [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:

// ❌ SLOW/DANGEROUS: Re-evaluates array.size() every iteration
for i = 0 to array.size(arr) - 1
    // Can cause infinite loop if array modified

// ✅ FALLBACK: Cache boundary if you need traditional for
arrSize = array.size(arr)
for i = 0 to arrSize - 1
    // process

August 2025: Longer Strings (40,960 chars)

Build more comprehensive info panels:

// Now possible: detailed multi-section reports
report = "═══════════════════════════════\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

// ❌ 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 item
array.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 together
newReg = Regression.new(slope=newSlope, intercept=newIntercept, ...)
array.push(regressions, newReg)

Performance Gain: xloc.bar_time Eliminates Clamping

// ❌ BEFORE: Clamping code everywhere (slow, complex)
leftBar = math.max(0, bar_index - startOffset)  // Clamp to valid range
if 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

// ❌ BEFORE: Repeated drawing blocks (~50+ lines each)
// Block for original regression drawing
if 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

// ALWAYS capture BOTH time and bar_index when events occur
var int eventStartTime = na
var 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 both
newItem = MyType.new(
    startTime = eventStartTime,      // Drawing coordinate
    startBarIndex = eventStartBar,   // Calculation coordinate
    ...
)

Core Optimization Areas

1. Calculation Caching

// ❌ BEFORE: Repeated calculations
plot(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 times
sma20 = ta.sma(close, 20)
sma50 = ta.sma(close, 50)
bullish = sma20 > sma50
plot(bullish ? high : low)

Use this skill in a project

Open any RiverX project, search the Skills panel for traderspost/pinescript-agents/pine-optimizer, and install it in one click.

Use this skill