mcpField
P
pinescript

pinescript

github.com/iliaal開発45212 回インストール3 日前に更新
リポジトリ

pinescript について

TradingViewのインジケーターやストラテジーを開発する人向けのPine Scriptスキルです。最新ドキュメントの確認、構文やプラットフォーム制限の把握、シグナルとバックテストの検証を重視します。

主な機能

  1. 01バージョン別ドキュメントの確認
  2. 02構文とプラットフォーム制限の指針
  3. 03パフォーマンスとデバッグの実践
  4. 04ストラテジー検証と公開の指針

活用シーン

  1. 01Pine Scriptインジケーターの実装
  2. 02トレードストラテジーの構築とテスト
  3. 03シグナルやリペイント挙動のデバッグ

インストール

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

$npx skills add https://github.com/iliaal/ai-skills --skill pinescript

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

同梱ファイルreferences/evidence/findings-log.mdSPEC.md

詳細

Pine Script の開発

実装前に確認してください:Pine Script のバージョン固有の構文や新しい組み込み関数については、コードを書く前に最新の公式ドキュメントを確認してください。利用可能な場合は Context7(query-docs)を優先してください。それ以外の場合は、利用可能なウェブツールを使用して、スクリプトのバージョンに対応するTradingView Pine Script ドキュメントを参照してください。TradingView は Pine Script を頻繁に更新しているため、学習データは古くなっている可能性があります。

重要な構文ルール

  • シンプルな三項演算子は読みやすく保ってください。複数行の式では、継続行のインデントを正しくする必要があります。複雑な三項演算子には、中間変数を使用してください:
    isBull = close > open
    barColor = isBull ? color.green : color.red
    
  • 括弧の外にある継続行は、4 の倍数ではない数のスペースでインデントする必要があります:開始行と同じインデントではエラーになり、スペースを 4/8/12 個にするとローカルブロックとして解釈され、こちらもエラーになります(慣例としてはスペース 2 個を使用します)。括弧内(関数呼び出しや括弧で囲まれた式)では、4 の倍数を含め、どのようにインデントしてもかまいません
  • ローカルスコープ(if/for/関数内)では絶対に plot() を使用しないでください。代わりに条件付きの値を使用してください:plot(condition ? value : na)
  • シグナルでチャートバーの終値が必要な場合は、barstate.isconfirmed を使用してください。これは、要求した上位時間足の値が確定済みであることを保証するものではありません。request.security() のオフセットと lookahead は別途確認してください。

プラットフォームの制限

スクリプトの規模を決める前に、最新のプラットフォームの制限を確認してください:プロット数は 64(1 回の呼び出しで複数カウントされる場合があります)、line・box・label の各 ID は最大 500 個、polyline ID は 100 個、固有の request.*() 呼び出しは 40 回(Ultimate では 64 回)、コンパイル済みトークンは 100,000 個です。履歴バッファ、要求したイントラバー、チャート履歴にはそれぞれ異なる制限があります。request.security() の履歴制限が一律に 500 バーというわけではありません。

  • xloc.bar_index で配置した描画は、過去 9,999 バー、未来 500 バーまでしか指定できません。それより古い位置を指定する場合は、描画を xloc.bar_time に切り替えてタイムスタンプを渡してください(xloc.bar_time を指定せずに時刻の値を渡すと、未来のバーインデックスとして扱われ、エラーになります)
  • 該当する max_*_count 宣言パラメーターを設定し、循環バッファーを使って増加を制限してください。各オブジェクトを追加し、指定した線の数を超えたら line.delete(arr.shift()) を実行します。描画タイプごとのデフォルト表示数は約 50 個です。

パフォーマンス

  • タプルを使った security 呼び出し:request.security() で [close, high, low] を返すようにすると、個別に 3 回呼び出すより効率的です
  • array.new<type>(size) を使って配列を事前に確保し、追加とサイズ変更を繰り返さないようにします
  • ta.rsi() など、履歴に依存する関数は、すべてのバーでグローバルスコープから評価してください。保存した結果を使ってシグナルの述語を短絡評価します。Pine v6 の遅延評価を参照してください。
  • 繰り返し行う計算は変数にキャッシュしてください。Pine はバーごとに再計算します
  • for i = 0 to array.size(...) - 1 ではなく、for item in myArray(または for [i, item] in myArray)でコレクションを反復処理してください。どちらの形式でも、後続の反復ではコレクションの更新後のサイズが使われます
  • for...in では、反復中の境界の変化を考慮して配列や行列のサイズを変更してください。マップのエントリーを追加または削除する場合は、元のマップを変更しながら map.keys() のスナップショットまたは map.copy() を反復処理してください。ループの結果で var/varip を直接初期化しないでください。ループは最初の反復後に停止します。先に宣言してから := で代入するか、関数からループの結果を返してください。Pine v6 のループ規則を参照してください。
  • 関連する値は並列配列ではなく、ユーザー定義型としてモデル化してください。たとえば float entry と int startBar、さらに method 関数を持つ type Trade を作成し、単一の array<Trade> に格納します。並列配列(entries、startBars など)は、追加や削除が 1 回でも漏れると同期が崩れ、すべての操作を配列ごとに繰り返す必要があります。型付き配列を 1 つ使えば、各オブジェクトのフィールドをまとめて管理できます

デバッグ

log.info()、log.warning()、log.error()を使って Pine Logsを利用し、次のビジュアルチェックも行います。

  • ラベルによるデバッグ:label.new(bar_index, high, str.tostring(myVar))で値を確認します。保持するラベル数には明示的な上限を設けます。
  • テーブルモニター:barstate.islastとtable.new()を使って、リアルタイムの変数ダッシュボードを表示します。
  • デバッグモードの切り替え:ローカルのデバッグコードにはif input.bool(false, "Debug")を使います。プロット呼び出しはグローバルスコープに置きます。
  • リペイントの確認:ライブシグナルをタイムスタンプ付きで記録し、再読み込み後に同じバーと比較します。value[1]は1つ前のバーを参照するため、それ以前の計算結果の修正は検出できません。

ストラテジーとバックテスト

  • strategy.*関数を使います:strategy.wintrades、strategy.losstrades、strategy.grossprofit
  • ドローダウンの永続状態は、更新前に宣言します。
    var float maxEquity = strategy.equity
    maxEquity := math.max(maxEquity, strategy.equity)
    dd = maxEquity > 0 ? (maxEquity - strategy.equity) / maxEquity * 100 : na
    
  • 年率換算シャープレシオは、超過リターンの平均を標準偏差で割り、1年あたりの期間数の平方根を掛けて推定します。サンプリング間隔と年率換算の前提を明記し、分散がゼロの場合も処理します。
  • ウォークフォワード検証:期間1で最適化し、期間2でテストします。次に期間2で再最適化し、期間3でテストします。劣化の度合いを、サンプリングの不確実性、コスト、レジームの変化と比較します。過学習を示す普遍的な割合はありません。
  • インジケーターの精度テスト:バーtで、prediction[horizon]を、close > close[horizon]など、現時点で実現している結果と照合して評価し、ウォームアップバーは除外します。正のオフセットは過去を参照し、未来のバーを参照することはありません。履歴参照を参照してください。
  • スライスごとの評価回数を数える:調整中にあるスライスをN回評価した場合、どのようなラベルが付いていても、それは調整用データです。すべてのスライスで複数パラメーターのスイープを実行すると、「検証」の数値は選択バイアスを受けます。少なくとも1つのスライスは、明確な参照回数の上限を設定して確保し、パラメーターを確定した後に使用します。「もう一度だけ見る」を停止の合図とします。
  • スライスごとに最適値が異なる場合は不安定性を示しています:レジーム分類器を追加する前に、堅牢な固定パラメーターをよりシンプルなストラテジーと比較します。分類器を使う場合は、エントリー前に利用できる情報で学習させ、未使用のデータで検証します。最適値が異なることだけでは、すべての固定パラメーターが機能しないとは言えません。
  • レジームゲートを有効にして、すべてのパラメータースイープを再実行します:ゲート適用前のスイープ結果はそのまま引き継げません。ゲートなしで損失となるセッションが、パラメーターの実際の効果を覆い隠すためです。あるストラテジーの失敗パターンに合わせて調整したフィルターを、同じシグナルを使う別のストラテジーに流用することはできません。

可視化

  • トレンドの強さの色分けにはcolor.from_gradient()を使います。
  • テキストサイズを適応させます:日中足にはsize.small、日足以上にはsize.normalを使います。
  • テーブルの行を動的に調整します:入力の切り替えに応じて、有効な機能の数に合わせてサイズを変更します。
  • input.*(..., active = condition)を使うと、制御用の切り替えがオフのときに入力をグレーアウトできます(たとえば、「Use smoothing」がチェックされている場合のみ平滑化の長さを編集できるようにします)。「無効にしない限り無視されます」というツールチップよりも明確です。
  • プロフェッショナルな色定数:透明度を指定して、BULL_COLOR、BEAR_COLOR、NEUTRAL_COLORを一度だけ定義します。

公開

  • ドキュメントは.pineファイルの先頭に、indicator()/strategy()より前のコメントとして記述します。
  • @version、@description、@paramタグを使います。
  • 複数行のツールチップには、tooltip="Line 1" + "\n" + "Line 2"を使います。
  • 公開する前に、スクリプトの公開範囲とカテゴリーに関する現在のTradingView公開ルールを確認します。固定のチェックリストからプラットフォームのポリシーを推測しないでください。

よくあるコーディングミス

  • インジケーターの重ねすぎ(RSI + Stochastics + CCI):すべて同じもの(モメンタム)を測定します。代わりに、異なるカテゴリのインジケーターを使用してください。
  • 未使用のデータでパラメーターの安定性を評価してください。異様に具体的な値であることは過剰適合の証拠ではなく、切りのよい数値でも過剰適合は防げません。
  • シグナルを意図的にバー内で更新するのか、確定したバーを必要とするのかを明記してください。要求された時間足も含め、その動作をテストしてください。
  • input() を使わずにしきい値をハードコードすると、銘柄ごとのスクリプトのテストができません。

ワークフロー

  1. Pine Editor でインジケーター/ストラテジーを作成します
  2. 複数の時間足で、バーリプレイとストラテジーテスターを使ってテストします
  3. バックテストの結果を信頼する前に、ウォークフォワード検証を行います(上記の「ストラテジーとバックテスト」を参照)
  4. 確認します:3銘柄以上、2つ以上の時間足で実行します

確認

  • TradingView でインジケーターがエラーなくコンパイルされる
  • ライブバーと再読み込み後のバーを比較してシグナルの安定性を確認し、上位時間足のリクエストを調べてください。ガードがあるだけでは、正しく動作する証拠になりません。
  • 異なる時間足で3銘柄以上を使ってウォークフォワードテストを実施済み

コメント