TradingView と alpha-strike の連携(ペイロード仕様)¶
alpha-strike は TradingView のアラートを Webhook で受け取り、moomoo / OANDA に自動発注します。本ページは Webhook ペイロードの JSON 仕様 と TradingView 側のアラート設定 に焦点を当てた仕様書です。
インフラ構築(VM / Cloudflare Tunnel / WAF / OpenD / systemd 等)の手順は、別ページの alpha-strike セットアップガイド(ペーパートレード本格運用) を参照してください。
1. Webhook エンドポイント¶
| 項目 | 本番運用構成 |
|---|---|
| URL | https://strike.yourdomain.com/webhook(Cloudflare Tunnel 経由・自分のドメインに置換) |
| HTTPS | 必須 — TradingView は HTTPS のみ受理。Cloudflare Tunnel が自動で証明書を提供 |
| 認証 | リクエストボディ内 passphrase フィールドが .env の WEBHOOK_PASSPHRASE と一致すること |
| Rate limit | 10 req/min/IP(slowapi で実装) |
| 推奨防御層 | Cloudflare WAF Custom Rule で TradingView 公式 IP 4 件のみ通過させる(セットアップガイド §4) |
2. TradingView アラート作成手順¶
- 対象チャートでベルアイコン → Create Alert
- Condition: ストラテジー / インジケータ等の発火条件を選択
- Notifications タブ:
- ✅ Webhook URL にチェック → URL に
https://strike.yourdomain.com/webhookを入力 - Message 欄に下記の JSON を貼付(後述)
- Create で保存
TradingView プラン要件
Webhook URL は Essential プラン以上(アラート数 20 件まで)で利用可能。Free / Basic では使えません。
3. ペイロード JSON 仕様¶
3-1. moomoo SIMULATE / REAL¶
{
"passphrase": "<WEBHOOK_PASSPHRASE>",
"broker": "moomoo",
"asset_class": "US",
"action": "buy",
"ticker": "US.AAPL",
"quantity": 10,
"run_mode": "paper",
"strategy_id": "demo_buy_v1",
"alert_name": "{{strategy.order.alert_message}}"
}
3-1b. moomoo CRYPTO (BTC / ETH / XRP)¶
{
"passphrase": "<WEBHOOK_PASSPHRASE>",
"broker": "moomoo",
"asset_class": "CRYPTO",
"action": "buy",
"ticker": "CC.BTC",
"quantity": 0.01,
"run_mode": "paper",
"strategy_id": "btc_ema_sma_trail40_v1"
}
moomoo crypto の前提: - 24/7 取引・unlimited T+0 - 米国居住者制限あり(FinCEN MSB 経由)。broker 側のアカウント有効化が前提 - SDK 内部では
OpenSecTradeContext(filter_trdmarket=TrdMarket.CRYPTO, security_firm=SecurityFirm.NONE)を使用 - 銘柄コードはCC.BTC/CC.ETH/CC.XRP等(CC.プレフィックス + 大文字シンボル)
moomoo crypto は live (REAL) only — SIMULATE 不可
moomoo の crypto trading API は live 環境専用で、MOOMOO_TRD_ENV=SIMULATE で
crypto order を送ると moomoo SDK が the type of environment param is wrong を返す。
alpha-strike は OpenD 接続前にこの組み合わせを検出し、以下の ValueError で早期拒否する:
moomoo crypto は SIMULATE 環境を受け付けません(live only)。
paper 運用したい場合は BTC ETF (US.IBIT / US.FBTC / US.BITO 等) を
asset_class=US で発注するか、MOOMOO_TRD_ENV=REAL で実 money 運用してください。
ペーパー検証したい場合は以下のいずれか:
- BTC ETF (
US.IBIT/US.FBTC/US.BITO) をasset_class=USで発注(推奨) MOOMOO_TRD_ENV=REALで少額(0.001 BTC ≈ $80)から開始- alpha-strike を経由せず TradingView Paper Trading 内蔵を使う
3-2. OANDA PRACTICE / LIVE¶
{
"passphrase": "<WEBHOOK_PASSPHRASE>",
"broker": "oanda",
"asset_class": "FX",
"action": "buy",
"ticker": "USDJPY",
"quantity": 1000,
"run_mode": "paper",
"strategy_id": "fx_demo_v1"
}
3-3. フィールド一覧¶
| フィールド | 必須 | 説明 | 例 |
|---|---|---|---|
passphrase |
✅ | .env の WEBHOOK_PASSPHRASE と完全一致 |
"32文字のランダム文字列" |
broker |
✅ | 発注先 | "moomoo" / "oanda" |
asset_class |
✅ | アセットクラス | "FX" / "COMMODITY" / "US" / "HK" / "INDEX" / "CRYPTO" |
action |
✅ | 注文方向 | "buy" / "sell"(小文字) |
ticker |
✅ | 銘柄コード(パターン ^[A-Z0-9_.]{1,20}$) |
moomoo: "US.AAPL" / OANDA: "USDJPY" |
quantity |
✅ | 注文数量(正数) | 10 / 1000 |
run_mode |
— | "paper" / "live"(既定 "live") |
"paper" |
strategy_id |
— | alpha-forge 側の strategy_id | "cl_hmm_bb_rsi_v1" |
strategy_version |
— | 戦略バージョン | "1.2.0" |
snapshot_id |
— | alpha-forge journal snapshot_id | "snap_20260517170105122499" |
signal_id |
— | シグナル一意 ID(未指定なら採番) | "sig_xxx" |
timeframe |
— | 時間軸 | "1m" / "5m" / "1h" |
alert_timestamp |
— | シグナル発火時刻(ISO 8601) | "2026-05-17T08:45:10Z" |
alert_name |
— | TradingView アラート名 | "BTC breakout" |
order_comment |
— | 任意メモ | "manual override" |
3-4. ティッカーフォーマット¶
moomoo¶
市場.コード 形式で指定:
| 市場 | 形式 | 例 |
|---|---|---|
| 米国株 | US.<TICKER> |
US.AAPL |
| 香港株 | HK.<CODE> |
HK.00700 |
| 中国 A 株 | SH.<CODE> / SZ.<CODE> |
SH.600000 |
| 暗号資産 | CC.<SYMBOL> |
CC.BTC / CC.ETH / CC.XRP |
TradingView の {{ticker}} は市場プレフィックスなしの形式なので、Pine 側で "US." + syminfo.ticker のように加工するのが確実です(セットアップガイド §7 参照)。
OANDA¶
asset_class に応じて自動変換:
| asset_class | TradingView 例 | OANDA instrument |
|---|---|---|
FX / COMMODITY |
USDJPY |
USD_JPY |
US / INDEX |
AAPL |
AAPL_USD |
OANDA instrument を直接指定したい場合は asset_class に "RAW" 等の値を入れるとパススルーされます。
3-5. 動的フィールド(TradingView プレースホルダ)¶
| プレースホルダ | 内容 | 用途 |
|---|---|---|
{{ticker}} |
銘柄(例: AAPL) |
ticker フィールドに展開 |
{{strategy.order.action}} |
buy / sell |
action フィールドに展開 |
{{strategy.order.contracts}} |
注文数量 | quantity フィールドに展開 |
{{strategy.position_size}} |
ポジションサイズ | 補助情報 |
{{strategy.order.alert_message}} |
Pine 側で alert() に渡した文字列 |
alert_name 等に展開 |
{{time}} |
アラート発火時刻(UTC ISO) | alert_timestamp に展開 |
Pine 側で完全な JSON を組み立てる
quantity のような数値フィールドにプレースホルダを使うと TradingView 側の出力次第で 422 エラーになることがあります。確実に動的化したい場合は Pine スクリプト内で alert() の引数に完全な JSON 文字列を渡してください(次節)。
4. Pine v6 から完全な JSON を生成する¶
手書き不要: alpha-forge pine generate --with-webhook
以下は手書きの参考例ですが、alpha-forge pine generate --strategy <id> --with-webhook を使えばこの passphrase input・make_payload()・alert() ブロックが自動で配線済みの Pine が出力されます(Pine 反映ガイド 参照)。
//@version=6
strategy("alpha-strike webhook demo", overlay=true)
// === 設定値 ===
passphrase = "<WEBHOOK_PASSPHRASE>"
broker = "moomoo"
asset_class = "US"
strategy_id = "demo_buy_v1"
run_mode = "paper"
// === シグナル例: RSI クロス ===
rsi_val = ta.rsi(close, 14)
long_signal = ta.crossover(rsi_val, 30)
short_signal = ta.crossunder(rsi_val, 70)
// === JSON 生成ヘルパー ===
// asset_class が US / HK / CRYPTO のときは moomoo フォーマットの prefix を付ける
// US → "US.AAPL"
// HK → "HK.00700"
// CRYPTO → "CC.BTC"
get_market_prefix(string ac) =>
ac == "US" ? "US." :
ac == "HK" ? "HK." :
ac == "CRYPTO" ? "CC." :
""
make_payload(string action, float qty) =>
ticker_full = get_market_prefix(asset_class) + syminfo.ticker
'{"passphrase":"' + passphrase + '",' +
'"broker":"' + broker + '",' +
'"asset_class":"' + asset_class + '",' +
'"action":"' + action + '",' +
'"ticker":"' + ticker_full + '",' +
'"quantity":' + str.tostring(qty) + ',' +
'"strategy_id":"' + strategy_id + '",' +
'"run_mode":"' + run_mode + '"}'
// === 発注 + アラート ===
if long_signal
strategy.entry("LONG", strategy.long, qty = 10)
alert(make_payload("buy", 10), alert.freq_once_per_bar_close)
if short_signal
strategy.close("LONG")
alert(make_payload("sell", 10), alert.freq_once_per_bar_close)
alert() をストラテジー本体で発火させると、TradingView アラートの Message 欄を空にしたまま Pine で組み立てた JSON がそのまま Webhook に送られます。alert.freq_once_per_bar_close で足確定時のみ発火し、リペイント・重複発注を抑制できます。
4-bis. Idempotency(重複発注の自動拒否)¶
TradingView Webhook は ネットワーク再送・alert 再評価・Restart 連打 などで同一シグナルが複数回到達することがあります。alpha-strike v0.5.0+ は signal_id を idempotency key として使い、TTL 内に同じ signal_id が再到達した場合は broker に流さず 200 を返します(TradingView 側の自動リトライを止めるため、409 にはしない)。
動作仕様¶
| 条件 | 動作 |
|---|---|
signal_id 指定あり + 初回到達 |
通常の発注フローを実行 |
signal_id 指定あり + TTL 内に再到達 |
broker 呼び出しスキップ、200 {"status":"success", "message":"duplicate signal_id — already processed"} |
signal_id 指定あり + TTL 経過後の再到達 |
通常の発注フローを実行(履歴 evict 済み) |
signal_id 未指定 |
idempotency 検証スキップ(後方互換、毎回 broker に流れる) |
環境変数¶
| 変数 | 既定 | 説明 |
|---|---|---|
IDEMPOTENCY_TTL_SECONDS |
600 |
重複拒否対象とする保持期間(秒)。TradingView 自動リトライ最長間隔をカバー。プロセス内 in-memory のため restart 時は破棄 |
Pine v6 推奨パターン¶
bar 確定時刻 + strategy_id + timeframe で 同一バー内の再発火を必ず idempotency で弾ける 形にします:
//@version=6
strategy("idempotent demo", overlay=true)
strategy_id = "demo_buy_v1"
passphrase = "<WEBHOOK_PASSPHRASE>"
make_signal_id() =>
// <strategy_id>_<timeframe>_<bar_open_time> 形式で一意性を担保
strategy_id + "_" + timeframe.period + "_" + str.format_time(time, "yyyy-MM-dd_HH-mm")
make_payload(string action, float qty) =>
sig = make_signal_id()
'{"passphrase":"' + passphrase + '",' +
'"broker":"moomoo",' +
'"asset_class":"US",' +
'"action":"' + action + '",' +
'"ticker":"US." + syminfo.ticker + '",' +
'"quantity":' + str.tostring(qty) + ',' +
'"signal_id":"' + sig + '",' +
'"strategy_id":"' + strategy_id + '",' +
'"run_mode":"paper"}'
同一バー内再発火の防止効果:
signal_idを<strategy_id>_<timeframe>_<bar_open_time>形式で組み立てれば、alert.freq_once_per_bar_closeを使っていても何らかの理由で同一バー内に複数回alert()が走った場合に alpha-strike 側で必ず 200 + duplicate 扱い となり broker への二重発注を防げます。後方互換: 既存の payload(
signal_id未指定)は従来通り動作。重複発注リスクを低減したい場合は明示的にsignal_idを含めることを強く推奨。
5. レスポンス例¶
5-1. 成功(200 OK)¶
{
"status": "success",
"broker": "moomoo",
"ticker": "US.AAPL",
"message": "{'order_id': '356604', 'ret_code': 0, 'filled_qty': 0.0, 'filled_price': 0.0}",
"signal_id": "sig_20260517170105122499",
"order_id": "ord_20260517170105123793",
"broker_order_id": "356604",
"event_id": "evt_20260517170105232506"
}
5-2. 認証失敗(401)¶
6. エラー一覧¶
| HTTP | 原因 | 対処 |
|---|---|---|
| 401 Unauthorized | passphrase 不一致 |
.env の WEBHOOK_PASSPHRASE と TradingView Message 欄を再確認 |
| 422 Unprocessable Entity | JSON パース失敗 / フィールド検証失敗 | broker action run_mode は小文字、ticker は ^[A-Z0-9_.]{1,20}$、quantity は正数 |
| 429 Too Many Requests | rate limit (10/min/IP) 超過 | アラート頻度を抑える |
| 503 Service Unavailable | Kill switch (maintenance mode) が ON | /etc/alpha-strike/MAINTENANCE が存在、または MAINTENANCE_MODE=1 が設定されている。sudo rm /etc/alpha-strike/MAINTENANCE で解除(セットアップガイド §10-3 参照) |
| 500 Internal Server Error | broker 認証情報未設定 | journalctl -u alpha-strike でエラー詳細を確認 |
| 502 Bad Gateway | broker API 呼び出し失敗 | moomoo: OpenD 起動状態 / oanda: API key の有効性 |
| 403 Forbidden(Cloudflare) | WAF Custom Rule で遮断 | 送信元 IP が TradingView 公式 4 件のいずれかか確認 |
7. ローカル開発時のテスト¶
VM デプロイ前にローカル PC で alpha-strike を起動して動作確認する場合:
# alpha-strike リポジトリで
uv run uvicorn webhook_server:app --host 0.0.0.0 --port 8080 --reload
# 別ターミナルから
curl http://localhost:8080/health
# → {"status":"ok"}
curl -X POST http://localhost:8080/webhook \
-H "Content-Type: application/json" \
-d '{"passphrase":"test","broker":"moomoo","asset_class":"US","action":"buy","ticker":"US.AAPL","quantity":1,"run_mode":"paper"}'
TradingView から外部 URL に到達させたい場合は本番デプロイ(Cloudflare Tunnel)を使うのが最も確実です。ローカル PC を直接公開したい場合は ngrok や cloudflared tunnel --url http://localhost:8080 で一時的なトンネルを張れます。
関連ドキュメント¶
- alpha-strike セットアップガイド(ペーパートレード本格運用) — VM・Cloudflare・WAF・OpenD・systemd の完全手順
- TradingView への Pine Script 反映 — alpha-forge 出力の Pine スクリプトを TradingView に貼る方法
- エンドツーエンド戦略開発ワークフロー — 戦略開発から本番運用までの全体フロー