mcpField
P
pine-optimizer

pine-optimizer

github.com/traderspost開発223463 回インストール14 週間前に更新
リポジトリ

pine-optimizer について

pine-optimizerは、TradingViewのスクリプトを改善するPine Script向けスキルです。コード構成や計算・ループの効率化に加え、入力項目やプロットの見せ方も扱います。

主な機能

  1. 01UDTによるデータ構成
  2. 02反復計算のキャッシュ
  3. 03security() 呼び出しの最適化
  4. 04コレクションの安全な反復
  5. 05条件付き入力とプロットスタイル

活用シーン

  1. 01並列配列をUDTに置き換える
  2. 02指標計算の重複を減らす
  3. 03ループ境界とsecurity()の使い方を確認する
  4. 04スクリプトの入力項目とプロットを読みやすくする

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/traderspost/pinescript-agents --skill pine-optimizer

インストール後、Claude Code で/pine-optimizerを入力して読み込まれたか確認します。

詳細

Pine Script オプティマイザー

TradingView でのスクリプトのパフォーマンス、ユーザーエクスペリエンス、視覚的な表現の向上に特化しています。

Pine Script v6 2025 年最適化機能

2025 年 7 月:入力の active パラメーター — UX を一変させる機能

条件に応じて入力項目の表示を切り替え、すっきりした 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)
2025 年 9 月:プロットのラインスタイル

カスタム描画なしで、より多くの視覚的な表現が可能になります。

// 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)
2025 年 2 月:スコープ数の上限撤廃

スコープ数が 550 に制限されなくなり、より複雑でモジュール化されたコードを記述できます。

// 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
2025 年 3 月:コレクションには for...in を使用

コレクションを反復処理する、推奨される最も安全な方法です。

// ✅ 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

代替手段:従来の for が必要な場合は、境界値をキャッシュします。

// ❌ 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
2025 年 8 月:文字列の長さが延長(40,960 文字)

より詳細な情報パネルを作成できます。

// 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

⚠️ 重要:UDT を中心としたコード構成

実行できる最大の最適化は、UDT を中心としたアーキテクチャを採用することです。 並列配列をなくし、描画管理を簡素化し、bar_index のクランプ処理を不要にします。

改善前と改善後:並列配列と 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)
パフォーマンス向上:xloc.bar_time によりクランプ処理を排除
// ❌ 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!
DRY な描画コードを実現する UDT メソッド
// ❌ 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 最適化の指標
指標並列配列UDT アーキテクチャ
配列の宣言6~101
描画コードブロック5 以上(重複)1 メソッド
クランプ処理のコード4 か所以上0
コード行数400 以上約 150
バグのリスク高(同期の問題)低
過去データの参照範囲最大 5000 バー無制限
UDT での時刻取得パターン
// 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
    ...
)

主な最適化分野

1. 計算のキャッシュ
// ❌ 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)
bgcolor(bullish ? color.new(color.green, 90) : color.new(color.red, 90))
2. セキュリティ呼び出しの最適化
// ❌ 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. ループの最適化(for...in を使用)
// ❌ SLOW/DANGEROUS: Boundary re-evaluated each iteration
for 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 needed
for [i, element] in arr
    // Have both index and value

// ✅ FASTEST: Use built-in array methods when possible
total = array.sum(arr)
maxVal = array.max(arr)
avgVal = array.avg(arr)
4. 条件ロジックの最適化
// ❌ SLOW: All conditions evaluated
signal = cond1 and cond2 and cond3 and expensiveCalc()

// ✅ FAST: Short-circuit with cheap checks first
signal = cond1  // Cheapest first
signal := signal and cond2
signal := signal and cond3
signal := signal and expensiveCalc()  // Only if others pass

ユーザーエクスペリエンスの最適化

1. Active パラメーターによる入力項目の整理
// 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. プロフェッショナルな配色
// Modern, accessible color palette
var color BULL = color.new(#26a69a, 0)      // Teal green
var color BEAR = color.new(#ef5350, 0)      // Coral red
var color BULL_BG = color.new(#26a69a, 85)  // Transparent
var color BEAR_BG = color.new(#ef5350, 85)
var color NEUTRAL = color.new(#787b86, 0)   // Gray

// Gradient based on strength
strength = ta.rsi(close, 14)
gradientColor = color.from_gradient(strength, 30, 70, BEAR, BULL)

// Dark mode friendly table
var 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. ラインスタイルを使用したレスポンシブなプロットのスタイル設定
// Use new linestyle parameter for visual hierarchy
ma = ta.ema(close, maLength)
maPlot = plot(ma, "MA", color.blue, linewidth=2,
    linestyle=plot.linestyle_solid)  // Primary: solid

// Secondary indicators: dashed
plot(upperBand, "Upper", color.gray,
    linestyle=plot.linestyle_dashed)
plot(lowerBand, "Lower", color.gray,
    linestyle=plot.linestyle_dashed)

// Projections/targets: dotted
plot(showTargets ? target : na, "Target", color.green,
    linestyle=plot.linestyle_dotted)
4. スマートなアラートメッセージ
// Comprehensive alert with all relevant info
buildAlert(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))

パフォーマンスチェックリスト

アーキテクチャ(最初に確認!)
  • 複雑なデータ構造には、UDT を中心とした構成を使用する
  • 並列配列を 1 つの UDT 配列に置き換える
  • 描画には xloc.bar_time を使用する(クランプ処理を排除)
  • 各座標の時刻と bar_index を保存する
  • ロジックをカプセル化するため、UDT にメソッドを追加する
必須の最適化
  • 繰り返し行われるすべての計算をキャッシュする
  • security() 呼び出しをタプルにまとめる
  • ループの境界値をキャッシュする(2025 年 3 月の重要事項)
  • コストの低い条件を、コストの高い条件より先に記述する
  • バーごとに変化しない値には var を使用する
UX の最適化(2025 年の機能)
  • 条件に応じた入力項目には active パラメーターを使用する
  • 関連する入力項目を論理的にグループ化する
  • 複雑な入力項目にツールチップを追加する
  • 視覚的な階層を表現するため、新しい linestyle パラメーターを使用する
  • モバイルに適したコンパクトモードのオプションを実装する
視覚的な最適化
  • 一貫性のある配色を使用する
  • 強さを表すグラデーションカラーを実装する
  • 適切なプロットの線幅を使用する
  • 背景色に透明度を加える
  • ダークモードでも見やすいテーブルにする

モバイル向け最適化

// Compact mode for mobile viewing
compactMode = input.bool(false, "📱 Compact Mode",
    group="Display",
    tooltip="Enable for better mobile viewing")

// Adjust based on mode
plotWidth = compactMode ? 1 : 2
labelSize = compactMode ? size.tiny : size.small

// Conditional table display
if not compactMode
    // Full table with details
    table.cell(infoTable, 0, 0, "Full Statistics", text_color=color.white)
    // ... more cells
else
    // Minimal display
    table.cell(infoTable, 0, 0, bullish ? "↑" : "↓",
        text_color=bullish ? BULL : BEAR,
        text_size=size.large)

メモリの最適化

// Use var for persistent values
var float highestHigh = na
var int barsSinceSignal = 0

// Limit array sizes
var array<float> recentPrices = array.new<float>(100)
if barstate.isconfirmed
    array.push(recentPrices, close)
    if array.size(recentPrices) > 100
        array.shift(recentPrices)

// Clear unused data
if newDay
    array.clear(intradayData)

最適化のクイックウィン

問題最適化前最適化後効果
並列配列同期が必要な配列が6個以上UDT配列1個コード量を80%削減
bar_index による描画クランプ処理+5000の上限xloc.bar_timeルックバックの上限なし
描画コード重複するブロックUDTメソッドDRYで保守しやすい
SMAの繰り返しta.sma(close,20) x5変数にキャッシュ5倍高速
security() の複数呼び出し個別に4回呼び出しタプルで1回呼び出し4倍高速
ループ境界ループ内でarray.size(arr)ループ前にキャッシュハングを防止
すべての入力を表示UIが煩雑activeパラメーターを使用すっきりしたUX
線のスタイルが1種類すべて実線実線/破線/点線階層が明確

最も効果が大きい最適化は、上位3つのUDT関連のものです。 最適化と読みやすさのバランスを取りましょう。保守性を犠牲にしてまで過剰に最適化しないでください。

コメント