1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIが自分でPineスクリプトを改良してバックテストまで回せるMCPを作ってみた

1
Posted at
  • TradingView デスクトップアプリ(Electron製)をデバッグポート付きで起動すると、Chrome DevTools Protocol 経由でチャートの中身を読み書きできる
  • これを MCP(Model Context Protocol) サーバーにして、Claude Code / Codex / Antigravity などの AI エージェントに全23ツールを提供した
  • 読めるもの: チャート画像、ローソク足、インジケーターの値・設定・描画物(ラベル/ライン/ボックス/テーブル)、自作Pineスクリプトのソースコード、ストラテジーのバックテストレポート
  • 最終的に「ソースを読む → AI が改良 → 保存 → バックテスト → 比較評価」という Pine スクリプト改修の PDCA ループが AI だけで回るようになった

リポジトリ: https://github.com/tedorigawa001/TradingView-MCP

モチベーション

TradingView には公式 API がほぼありません(Webhookとスクリーナーくらい)。
チャート分析を AI に手伝わせたくても、スクリーンショットを手動で貼るくらいしかない。

でも TradingView のデスクトップアプリは中身が Electron = Chromium です。つまり:

open -a TradingView --args --remote-debugging-port=9222

で起動すれば、localhost:9222 に Chrome DevTools Protocol (CDP) が生えます。
ページ内には window.TradingViewApi という charting library の API が露出していて、Runtime.evaluate で叩き放題。
ログイン済みセッション・保存済みレイアウト・購入済みインジケーターがそのまま使えるのが、スクレイピングや非公式REST叩きに対する決定的なアドバンテージです。

アーキテクチャ

AIエージェント ⇄ (stdio/MCP) ⇄ tradingview-mcp ⇄ (CDP/WebSocket) ⇄ TradingViewデスクトップ
                                       │
                                       └⇄ (HTTPS) scanner.tradingview.com / economic-calendar.tradingview.com
  • TypeScript + @modelcontextprotocol/sdk。stdio トランスポートで各エージェントに接続
  • CDP クライアントは自前実装(ws + Runtime.evaluate / Page.captureScreenshot)。数百行で足ります
  • ページ内 API で完結しないもの(クォート・スクリーナー・経済指標)は公開エンドポイントを Node 側から直接叩く

ツール一覧(全23種)

グループ ツール
チャートを読む get_chart_context / get_chart_screenshot / get_ohlcv / get_indicator_values / get_indicator_inputs / get_indicator_graphics / get_indicator_tables / get_key_levels / load_more_history
チャートを操作 set_symbol / set_timeframe(失敗時は自動ロールバック)
チャート外データ get_quotes / get_mtf_overview / scan_market / get_economic_events / get_watchlist / list_alerts
Pineスクリプト list_pine_scripts / get_pine_source / save_pine_script / add_pine_to_chart
バックテスト run_backtest / get_strategy_report

エージェントに「今のチャートを分析して」と言うだけで、AI が context → screenshot → ohlcv → indicator_values を勝手に組み合わせて環境認識してくれます。

ハマりどころ集(本編)

作る過程はほぼ「内部APIの遺跡発掘」でした。同じことをやる人のために罠を残しておきます。

1. デスクトップビルドでは公式APIの一部が無効化されている

chart.exportData()setVisibleRange()watchlist() などは呼ぶと "not implemented"。代替として内部モデルを直接読みます:

// OHLCV は内部シリーズから
chart.chartModel().mainSeries().bars()._items  // [{index, value:[time,O,H,L,C,V]}]

// 過去データの追加ロードは requestMoreData
series.requestMoreData(300)  // + ポーリングで完了検知

2. インジケーターの描画物は「二重ストア」に入っている

Pine の label.new / line.new / box.new で描かれたものは source.graphics()._primitivesCollection.{dwglabels,dwglines,dwgboxes} にあるのですが、格納場所が2形態あります:

  • 生データ: store._primitivesDataById(x座標は _indexes 経由の変換が必要、フィールド名は t/sz など短縮形)
  • 実体化後: store._primitiveById(Map。履歴ロード後はこちらに移り、x はモデルインデックス直、フィールド名は text/size)

さらに dwgtablecells(Pineのテーブル)だけネストの深さが1段浅いという罠つき。これを読めると、Smart Money 系インジケーターの MTF トレンド表やエリオット波動のカウントラベルが構造化データとして取れます。

3. オシレーターの値を「価格」と誤認する問題

サポレジ集約ツール(get_key_levels)を作ったとき、RSI=50 が50ドル付近の銘柄で偽サポートとして混入しました。metaInfo の is_price_study フラグでオシレーターペインを除外し、さらにプロット名の許可リスト(support/resist/pivot/vwap/BOS/CHoCH…)で high/low/close のような表示用プロットを弾いて解決。
AI に渡すデータは「取れる」だけでなく「誤読されない」形にするのが大事でした。

4. Pineソースの取得 — チャート側はコンパイル済みIL

チャート上のスタディが持つ隠し入力 text にソースが入っている…と思いきや、中身は難読化されたコンパイル済みIL。原文は Pine Editor が使う REST(pine-facade.tradingview.com)にあります:

GET /pine-facade/list/?filter=saved      → 自作スクリプト一覧
GET /pine-facade/get/<pineId>/<version>  → ソース原文(バージョン指定可)
POST /pine-facade/save/next/<pineId>     → 新バージョン保存(コンパイル結果つき)

保存レスポンスに行番号付きのコンパイルエラーが返るのが AI 的に最高で、AI が構文エラーを自分で直せます。ただし「コンパイル失敗でもバージョンとして保存される」仕様なので、結果に compileOk と復元手順を必ず含めるようにしました。

5. バックテストレポートの残留 — 最大の罠

ストラテジーテスターは backtestingStrategyApi()activeStrategyReportData(WatchedValue)から読めます。ただしこの値、ストラテジーをチャートから外しても前回のレポートを保持し続けます

最初の対策「アクティブなストラテジー名と一致する時だけ受理」には抜け穴がありました。改良版を保存して再テストすると名前が同じなので、v2 適用直後・計算完了前のポーリングが v1 の残留レポートを受理してしまう。実際、v2 のバックテストが v1 と小数点以下まで完全一致して発覚しました(改良の効果ゼロと誤診するところだった)。

対策は「適用のレポートオブジェクトを覚えておき、オブジェクト同一性で置き換わったものだけ受理」。AI に測定系を渡すなら、古い値を新しい値として返さないことに一番気を使うべき、という教訓です。

セキュリティ設計

デバッグポート開放中は同一PC上のプロセスからログインセッションを操作できる状態になるので、設計は保守的に:

  • 読み取り中心。注文・アラート作成・ウォッチリスト変更・スクリプト削除は実装しない(削除APIは調査で見つけたが意図的に非公開)
  • 唯一の書き込み save_pine_script は、①confirm: true なしではドライランのみ ②上書き禁止(新規 or 新バージョン追記のみ) ③全旧バージョンが取得可能 = 常に復元できる、の3点セット
  • 他人の保護/招待制スクリプトのソースには触れない(USER; プレフィックスのIDのみ許可、チャート側ILのフィルタも維持)
  • ページへ渡す値は正規表現ホワイトリスト+JSON.stringify 埋め込みで注入対策、MCP層でも zod で二重検証

実戦: AI にストラテジーを改良させてみた

自作の Smart Money 系ストラテジー(EURUSD 日足でPF 0.90の赤字)を題材に、AI にこう頼みました:

ソースを読んで、ダマシを減らす改良を実装して。保存してバックテストし、元と比較して

AI がやったこと:

  1. get_pine_source でソースを読み、ブレイク判定が「終値がレベルを1tickでも超えたら成立」なのを特定
  2. ATRブレイク確認バッファ(終値がレベル±0.15×ATRを超えた時のみ成立)と実体方向フィルター(ブレイク足の実体が方向と一致)を実装
  3. save_pine_script で v2 として保存(ドライラン→confirm)
  4. run_backtest で比較、さらに set_symbol を回して多銘柄A/B検証(v2にはフィルターを無効化するとv1と同一挙動になる入力を用意し、setStrategyInput で同一データ上のフェア比較)

結果:

市場 v1 PF v2 PF 純損益の変化
EURUSD 1D 0.90 1.12 赤字→黒字
XAUUSD 1D 1.32 2.00 +15,426 → +30,575
GBPUSD 1D 0.62 0.78 損失半減
EURUSD 4H 1.36 1.38 微改善
USDJPY 1D 0.95 0.94 微悪化(フィルターほぼ非発動)

5市場中4市場で改善。もちろんサンプル数は少なくフォワードでの検証は必要ですが、「AIがソースを読み、仮説を立て、実装し、複数市場で検証し、結果を正直に報告する」ループが人間はチャットで依頼するだけで回ったのは感動がありました。

Screenshot 2026-07-08 at 20.51.36.png

セットアップ

git clone https://github.com/tedorigawa001/TradingView-MCP.git
cd TradingView-MCP && npm install && npm run build

# TradingView をデバッグモードで起動(通常起動では見えません)
open -a TradingView --args --remote-debugging-port=9222

# Claude Code なら1コマンドで登録
claude mcp add tradingview -- node /path/to/TradingView-MCP/build/index.js

Codex(~/.codex/config.toml)や Antigravity(~/.gemini/config/mcp_config.json)の設定例は README にあります。

おわりに

  • Electron アプリ + CDP + MCP の組み合わせは、公式APIのないデスクトップアプリを AI ツール化する汎用パターンとして強力です
  • 内部API依存なのでアプリ更新で壊れるリスクは常にあります。統合スモークテスト(実アプリに対して27チェック)で検知する構えにしています
  • 投資判断は自己責任で。バックテストの数字は過去の話です
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?