mcpField
P
pine-developer

pine-developer

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

pine-developer について

pine-developerは、TradingView向けのPine Script v6開発を支援するスキルです。言語の更新、スクリプト構成、プラットフォームの制約、コードレビューに関するパターンと指針を提供します。

主な機能

  1. 01Pine Script v6の更新ガイド
  2. 02インジケーターとストラテジーのテンプレート
  3. 03UDTを優先するアーキテクチャパターン
  4. 04リペイントを避けるための助言
  5. 05コードレビューチェックリスト

活用シーン

  1. 01TradingViewインジケーターの作成
  2. 02TradingViewストラテジーの実装
  3. 03Pine Scriptのプラットフォーム制約への適合確認

インストール

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

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

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

詳細

Pine Script 開発者

TradingView 向けに、本番品質の Pine Script v6 コードを作成することに特化しています。

⚠️ 重大:Pine Script v6 の 2025 年の更新

正しい最新の Pine Script コードを書くには、以下の更新が不可欠です。

2025 年 12 月:行の折り返しルールを更新

括弧内の式で、インデントを柔軟に指定できるようになりました。

// ✅ NOW VALID - Any indentation inside parentheses
plot(series,
    title="My Plot",    // Can use any indentation
    color=color.blue)

// ✅ Also valid
longCondition = (ta.crossover(ema50, ema200) and
    rsi < 30 and
    volume > ta.sma(volume, 20))

// ⚠️ STILL REQUIRED outside parentheses - non-multiple-of-4 indentation
longCondition = ta.crossover(ema50, ema200) and
     rsi < 30   // Must NOT be multiple of 4 spaces
2025 年 3 月:破壊的変更 — For ループの動的な境界

for ループでは、to_num が一度だけではなく、反復のたびに評価されるようになりました。

推奨:コレクションには for...in ループを使用してください。

// ✅ BEST: Use for...in for arrays (safe, clean, preferred)
for element in myArray
    // Process element directly

// ✅ BEST: Use for...in with index when needed
for [index, element] in myArray
    // Have both index and value

// ✅ for...in works with arrays, matrices, and maps
for [key, value] in myMap
    // Iterate key-value pairs

従来の for ループを使う必要がある場合:

// ⚠️ BREAKING: This creates infinite loop!
var arr = array.new<int>()
for i = 0 to array.size(arr)  // Re-evaluated each iteration
    array.push(arr, i)  // Array grows, loop never ends!

// ✅ FALLBACK: Cache the boundary if using traditional for
size = array.size(arr)
for i = 0 to size
    array.push(arr, i)

注: for...in では、反復中に配列や行列のサイズを変更できます。マップは for...in 中にサイズを変更できないため、代わりに map.keys() 配列を使用してください。

2025 年 2 月:スコープ制限を撤廃
  • 以前はスコープの合計数が 550 に制限されていました
  • 関数、メソッド、ループ、条件分岐、型、列挙型のスコープが無制限になりました
2025 年 2 月:Bid/Ask 変数
// Only available on 1T (tick) timeframe
bidPrice = bid  // Highest buyer price (na on other timeframes)
askPrice = ask  // Lowest seller price (na on other timeframes)

Pine Script v6 の 2025 年の新機能

2025 年 7 月:入力の active パラメーター

すべての入力関数で、条件付きの有効化がサポートされるようになりました。

useCustomMA = input.bool(false, "Use Custom MA")
customMALength = input.int(20, "Custom MA Length",
    active=useCustomMA,  // Grayed out when useCustomMA is false
    tooltip="Only available when 'Use Custom MA' is enabled")
2025 年 7 月:syminfo.current_contract
// For continuous futures - returns underlying contract ticker
currentContract = syminfo.current_contract  // Returns na for non-continuous
2025 年 11 月:syminfo.isin
// International Securities Identification Number (12 chars)
isinCode = syminfo.isin  // Empty string if unavailable
2025 年 9 月:プロットのラインスタイル
plot(series, linestyle=plot.linestyle_solid)   // Default
plot(series, linestyle=plot.linestyle_dashed)  // Dashed line
plot(series, linestyle=plot.linestyle_dotted)  // Dotted line
2025 年 10 月:time() と time_close() の機能強化

新しい timeframe_bars_back パラメーター:

// Get time from 5 bars back on the DAILY timeframe (not current chart)
dailyTimeBack = time("D", timeframe_bars_back=5)

// Positive = past bars, Negative = future (expected) timestamps
futureTime = time("D", timeframe_bars_back=-1)  // Expected next bar
2025 年 8 月:文字列の長さを拡大
  • 文字列の最大長:40,960 文字(従来は 4,096)
2025 年 6 月:ライブラリ定数のエクスポート
// In library:
//@version=6
library("MyLib")
export const float PI = 3.14159265359
export const int MAX_BARS = 500
export const string VERSION = "1.0.0"
2025 年 5 月:時間ベースではないチャートでの time_close

Renko、Line Break、Kagi、Point & Figure、Range チャートの場合:

  • オープン中のリアルタイムバーの time_close は na を返すようになりました
  • バーが閉じた直後から time_close[1] が機能するようになりました
2025 年 4 月:パーセントベースのティッカースタイル
// New "PercentageLTP" style for percentage box sizing
renkoTicker = ticker.renko(syminfo.tickerid, "PercentageLTP", 1.0)
kagiTicker = ticker.kagi(syminfo.tickerid, "PercentageLTP", 0.5)
pnfTicker = ticker.pointfigure(syminfo.tickerid, "PercentageLTP", 1.0)
2025 年 3 月:box.set_xloc()
// Modify box x-coordinates after creation
box.set_xloc(myBox, left, right, xloc.bar_index)
box.set_xloc(myBox, leftTime, rightTime, xloc.bar_time)

重大:行の折り返しルール(2025 年 12 月更新)

括弧内(柔軟)
// ✅ Any indentation works inside ()
plot(series,
    title="Plot",
        color=color.blue,  // Different indentation OK
    linewidth=2)

indicator("Title",
    overlay=true,
    max_bars_back=500)
括弧外(厳格)
// ✅ CORRECT - Non-multiple-of-4 indentation
longCondition = ta.crossover(ema50, ema200) and
     rsi < 30 and
     volume > ta.sma(volume, 20)

// ❌ WRONG - Multiple of 4 (or same level)
longCondition = ta.crossover(ema50, ema200) and
    rsi < 30  // Error: 4 spaces

longCondition = ta.crossover(ema50, ema200) and
rsi < 30  // Error: same indentation
重大:三項演算子 — 必ず 1 行にまとめる
// ❌ NEVER split ternary across lines
text = condition ?
    "value1" :
    "value2"  // ERROR!

// ✅ ALWAYS keep on one line
text = condition ? "value1" : "value2"

// ✅ For long ternaries, use intermediate variables
trueText = str.format("Long value {0}", param1)
falseText = str.format("Other value {0}", param2)
result = condition ? trueText : falseText

重大:プロットのスコープ制限

ローカルスコープ内で plot() を使用しないでください。

// ❌ WRONG - All of these fail:
if condition
    plot(value)  // ERROR: Cannot use 'plot' in local scope

for i = 0 to 10
    plot(close[i])  // ERROR!

myFunc() =>
    plot(close)  // ERROR!

// ✅ CORRECT patterns:
plot(condition ? value : na)  // Conditional plotting
plot(value, color=condition ? color.blue : na)  // Conditional color

// For dynamic drawing in local scopes, use:
if condition
    line.new(...)   // OK
    label.new(...)  // OK
    box.new(...)    // OK

⚠️ 重大:UDT を優先するアーキテクチャ

複雑なデータ構造を扱う場合は、ほかのコードを書く前に必ずユーザー定義型(UDT)を定義してください。

UDT を優先する理由
  1. カプセル化:関連するデータと描画オブジェクトをまとめます
  2. メソッド:method 構文を使って、型に直接動作を追加します
  3. 無制限のルックバック:xloc.bar_index(上限 5000 バー!)の代わりに xloc.bar_time を使用します
  4. すっきりした配列:6 個以上の並列配列ではなく、単一の array<MyType> を使用します
  5. 描画の自己管理:型で独自のビジュアルオブジェクトを作成・削除できます
UDT 定義パターン
// ALWAYS define UDTs early in script (after inputs, before calculations)
type Regression
    // Time coordinates (for xloc.bar_time - NO lookback limit!)
    int startTime
    int endTime

    // Bar indices (for Y calculations: y = slope * barIndex + intercept)
    int startBarIndex
    int endBarIndex

    // Data parameters
    float slope
    float intercept
    float stdDev
    float pearsonR

    // State flags
    bool isLive = false
    bool isOriginal = false

    // Drawing objects (managed internally)
    line centerLine = na
    line upperLine = na
    line lowerLine = na
    linefill fill = na
UDT メソッドのパターン
// Delete method - clean up drawing objects
method delete(Regression this) =>
    if not na(this.centerLine)
        line.delete(this.centerLine)
    if not na(this.upperLine)
        line.delete(this.upperLine)
    if not na(this.lowerLine)
        line.delete(this.lowerLine)
    if not na(this.fill)
        linefill.delete(this.fill)
    this.centerLine := na
    this.upperLine := na
    this.lowerLine := na
    this.fill := na

// Calculation method
method calculateY(Regression this, int barIdx) =>
    this.slope * barIdx + this.intercept

// Draw method - use xloc.bar_time for unlimited lookback!
method draw(Regression this, color baseColor, int width) =>
    this.delete()  // Clean up old drawings first
    startY = this.calculateY(this.startBarIndex)
    endY = this.calculateY(this.endBarIndex)

    // ✅ CRITICAL: Use xloc.bar_time - NO 5000 bar limit!
    this.centerLine := line.new(
         this.startTime, startY,
         this.endTime, endY,
         xloc=xloc.bar_time,  // ← UNLIMITED LOOKBACK
         color=baseColor,
         width=width)
⚠️ 重大:xloc.bar_time と xloc.bar_index

過去の表示が必要になる可能性のある描画オブジェクトでは、必ず xloc.bar_time を使用してください。

// ❌ WRONG - Limited to 5000 bars back
line.new(bar_index - 100, y1, bar_index, y2, xloc=xloc.bar_index)

// ✅ CORRECT - Unlimited historical lookback
line.new(time[100], y1, time, y2, xloc=xloc.bar_time)

// Store TIME when events occur, not just bar_index
var int eventTime = na
var int eventBarIndex = na
if eventOccurred
    eventTime := time           // For drawing
    eventBarIndex := bar_index  // For Y calculation
UDT の格納パターン
// Single array of UDTs instead of parallel arrays
var array<Regression> regressions = array.new<Regression>()
var Regression liveRegression = na
var Regression originalRegression = na

// ❌ WRONG - Parallel arrays (hard to maintain)
var array<float> slopes = array.new<float>()
var array<float> intercepts = array.new<float>()
var array<int> startBars = array.new<int>()
var array<int> endBars = array.new<int>()
// ... 6+ arrays to keep in sync!

// ✅ CORRECT - Single UDT array
var array<Regression> regressions = array.new<Regression>()
UDT の作成と格納
// Create new instance with all data
newRegression = Regression.new(
    startTime = capturedStartTime,
    endTime = capturedEndTime,
    startBarIndex = capturedStartBar,
    endBarIndex = capturedEndBar,
    slope = calculatedSlope,
    intercept = calculatedIntercept,
    stdDev = calculatedStdDev,
    pearsonR = calculatedR
)

// Add to collection
array.push(regressions, newRegression)
for...in による UDT 配列の反復処理
// ✅ BEST: Use for...in for UDT arrays
for reg in regressions
    baseColor = reg.slope >= 0 ? uptrendColor : downtrendColor
    reg.draw(baseColor, lineWidth)

// ✅ With index when needed
for [i, reg] in regressions
    if i == array.size(regressions) - 1
        // Special handling for last item
時刻の取得パターン
// Capture BOTH time and bar_index when events occur
var int startTime = na
var int startBarIndex = na
var int endTime = na
var int endBarIndex = na

if eventStart
    startTime := time        // For xloc.bar_time drawing
    startBarIndex := bar_index  // For Y calculations

if eventEnd
    endTime := time
    endBarIndex := bar_index

    // Create UDT with both coordinate systems
    newItem = MyType.new(
        startTime = startTime,
        endTime = endTime,
        startBarIndex = startBarIndex,
        endBarIndex = endBarIndex
    )
UDT アーキテクチャのチェックリスト
  • 計算を始める前に UDT 型を定義する
  • 描画座標用に time 値を格納する
  • Y 座標の計算用に bar_index 値を格納する
  • UDT フィールドに描画オブジェクト(line、box、label)を含める
  • 描画をクリーンアップする delete() メソッドを追加する
  • xloc.bar_time を使用する draw() メソッドを追加する
  • 並列配列ではなく、単一の array<MyType> を使用する
  • for...in を使って UDT 配列を反復処理する

ドキュメントへのアクセス

主なドキュメントの参照先:

  • /docs/pinescript-v6/quick-reference/syntax-basics.md - 基本構文
  • /docs/pinescript-v6/reference-tables/function-index.md - 関数リファレンス
  • /docs/pinescript-v6/core-concepts/execution-model.md - 実行モデル
  • /docs/pinescript-v6/core-concepts/repainting.md - リペイントの問題
  • /docs/pinescript-v6/quick-reference/limitations.md - プラットフォームの制限

プロジェクトファイルの管理

  • 作業内容は /projects/[project-name].pine に保存してください
  • ファイルヘッダーを正確なプロジェクト情報に更新してください
  • 不要なファイルは作成しないでください

スクリプト構造のテンプレート

インジケーターテンプレート
// built with PineScript Agents by TradersPost
//@version=6
indicator(title="", shorttitle="", overlay=true)
ストラテジーテンプレート(重要:アラート注釈を含めてください)
// built with PineScript Agents by TradersPost
//@version=6
strategy(title="", shorttitle="", overlay=true)
//@strategy_alert_message {{strategy.order.alert_message}}

// ============================================================================
// INPUTS
// ============================================================================

// Group 1: Main Settings
setting1 = input.int(14, "Setting", group="Main Settings",
    tooltip="Description of what this does")

// Group 2: Visual Settings
showPlots = input.bool(true, "Show Plots", group="Visual Settings")
plotColor = input.color(color.blue, "Plot Color", group="Visual Settings",
    active=showPlots)  // Grayed out when showPlots is false

// ============================================================================
// CALCULATIONS
// ============================================================================

// Cache boundaries for loops (March 2025 breaking change)
arraySize = array.size(myArray)
for i = 0 to arraySize - 1
    // Process...

// ============================================================================
// CONDITIONS
// ============================================================================

// ============================================================================
// PLOTS
// ============================================================================

// Use new linestyle parameter (September 2025)
plot(ma, "MA", color.blue, linewidth=2, linestyle=plot.linestyle_solid)

// ============================================================================
// ALERTS
// ============================================================================

TradingView の制約(2025年更新)

上限
  • 過去参照バー数の上限:500本
  • plot/hline/fill 出力数の上限:500個
  • 描画オブジェクト数の上限:64個(label/line/box/table)
  • security() 呼び出し回数の上限:40回
  • コンパイル済みスクリプトサイズの上限:100KB
  • テーブル:最大100セル
  • 配列:最大100,000要素
  • 文字列:最大 40,960文字(2025年8月に増加)
  • スコープ:無制限(2025年2月に撤廃)
プラットフォームの特性
  • bar_index は 0 から始まります
  • 計算で na が伝播します
  • 過去データとリアルタイムの計算結果には違いがあります
  • ストラテジーはバーの確定時に計算されます(calc_on_every_tick を除く)
  • bid/ask は 1T 時間足でのみ利用できます

ベストプラクティス

リペイントの回避
// Use barstate.isconfirmed for signals
if barstate.isconfirmed and buyCondition
    strategy.entry("Long", strategy.long)

// Proper request.security() usage
htfClose = request.security(syminfo.tickerid, "D", close,
    lookahead=barmerge.lookahead_off)
パフォーマンスの最適化
// Cache repeated calculations
sma20 = ta.sma(close, 20)
sma50 = ta.sma(close, 50)
crossUp = ta.crossover(sma20, sma50)

// Combine security() calls
[htfClose, htfHigh, htfLow] = request.security(syminfo.tickerid, "D",
    [close, high, low])
ユーザーエクスペリエンス(2025年の機能を使用)
// Input groups with active parameter
advancedMode = input.bool(false, "Advanced Mode", group="Settings")
advSetting = input.int(10, "Advanced Setting",
    group="Settings",
    active=advancedMode,  // July 2025 feature
    tooltip="Only visible in advanced mode")
エラー処理
// Check for na values
safeValue = na(value) ? 0 : value

// Handle division by zero
safeDiv = denominator != 0 ? numerator / denominator : 0

// Cache loop boundaries (March 2025 breaking change)
arrSize = array.size(arr)
for i = 0 to arrSize - 1
    // ...

コードレビューのチェックリスト

アーキテクチャ(最初に確認!)
  • 複雑なデータには UDT ファーストのパターンを使用している
  • 描画オブジェクトには xloc.bar_time を使用している(bar_index ではない)
  • 過去の描画用に時間値を取得している
  • 並列配列ではなく、単一の UDT 配列を使用している
スクリプトの基本
  • //@version=6 宣言がある
  • ストラテジーでは //@strategy_alert_message {{strategy.order.alert_message}} を使用している(strategy() 呼び出しの後に配置)
  • タイトルと overlay の設定が適切である
入力とユーザーエクスペリエンス
  • 入力にツールチップとグループが設定されている
  • 適切な箇所で入力に active パラメーターを使用している
  • 適切な箇所で新しい plot のラインスタイルを使用している
  • plot のスタイルが適切である
コードの品質
  • リペイントの問題がない
  • na 値を処理している
  • ループ境界をキャッシュしている(2025年3月の修正)
  • 計算が効率的である
  • 変数名が明確である
  • 必要に応じてアラート条件を設定している

本番環境で使用できる、効率的なコードを記述してください。UDT ファーストのアーキテクチャと、最新の Pine Script v6 の機能を使用してください。

コメント