Pineスクリプトでインジケーターを作ったら、次にやりたいのがアラートの実装だ。チャートに張り付かなくても、条件を満たした瞬間にスマホやメールで通知を受け取れる。
しかし、Pineスクリプトのアラートには2つの関数がある。alertcondition()とalert()だ。どちらを使えばいいのか、何が違うのか。初心者がつまずくポイントはここだ。
結論から言うと、インジケーターならalertcondition()が基本。ストラテジーならalert()を使う。そしてどちらも、コードを書いただけではアラートは鳴らない。TradingView上でアラートを手動作成する必要がある。
この記事では、2つのアラート関数の違いから、実用的なアラート付きインジケーターの作成、Webhook連携まで、v6ベースのコード付きで解説する。
alertcondition()とalert()の違い
Pineスクリプトには2つのアラート関数がある。名前が似ているが、仕組みがまったく異なる。
alertcondition() — アラート条件を「登録」する関数。インジケーター専用。この関数を書くと、TradingViewのアラート作成ダイアログのドロップダウンに選択肢として表示される。1つのスクリプトに複数のalertcondition()を書ける。
alert() — アラートを「直接発火」する関数。インジケーターにもストラテジーにも使える。条件を満たしたときにスクリプト内から直接アラートをトリガーする。メッセージに動的な値(価格、RSI値など)を含められる。
使い分けの基準はこうだ。
alertcondition()を使うケース: インジケーターに複数のアラート条件を登録したいとき。ユーザーがアラート作成時に条件を選べるようにしたいとき。
alert()を使うケース: アラートメッセージに動的な値(現在価格やインジケーターの数値)を含めたいとき。ストラテジーでアラートを使いたいとき。Webhook連携で動的なJSONを送りたいとき。
どちらを使っても、コードを書いただけではアラートは発動しない。TradingViewの「アラート作成」ダイアログで手動でアラートを設定する必要がある。ここを見落とす初心者が非常に多い。
alertcondition()の基本構文
alertcondition()の構文はシンプルだ。3つの引数を取る。
//@version=6
indicator("アラート基本", overlay=true)
sma20 = ta.sma(close, 20)
// alertcondition(条件, タイトル, メッセージ)
alertcondition(ta.crossover(close, sma20), "SMA上抜け", "{{ticker}}: 終値がSMA20を上抜けました")
alertcondition(ta.crossunder(close, sma20), "SMA下抜け", "{{ticker}}: 終値がSMA20を下抜けました")
plot(sma20, "SMA20", color.blue, 2)
第1引数(condition) — true/falseを返す条件式。trueになった瞬間にアラートがトリガーされる。
第2引数(title) — アラート作成ダイアログのドロップダウンに表示される名前。わかりやすい日本語で付ける。
第3引数(message) — アラート発動時に表示されるメッセージ。{{ticker}}や{{close}}などのプレースホルダが使える。
このコードをチャートに追加した後、TradingViewの「アラート作成」で条件にこのインジケーターを選ぶと、「SMA上抜け」「SMA下抜け」の2つの条件が選択肢として表示される。
alertcondition()のプレースホルダ一覧
メッセージ内で使えるプレースホルダを整理する。これらはアラート発動時にTradingViewが実際の値に置換してくれる。
{{ticker}} — ティッカー名(例: BTCUSDT)。{{exchange}} — 取引所名(例: BINANCE)。{{close}} — 終値。{{open}} — 始値。{{high}} — 高値。{{low}} — 安値。{{volume}} — 出来高。{{time}} — バーの時刻。{{timenow}} — アラート発動時の現在時刻。{{interval}} — 時間足(例: 60)。
alertcondition(
condition,
"RSI過熱アラート",
"{{ticker}}({{interval}}分足) 終値={{close}} RSI過熱ゾーン突入 時刻={{timenow}}"
)
ただし、alertcondition()のプレースホルダではスクリプト内で計算した値(RSIの数値など)は埋め込めない。計算値をメッセージに含めたい場合は、後述のalert()関数を使う。
複数条件のアラートを実装する
実用的なインジケーターでは、複数のアラート条件を1つのスクリプトにまとめることが多い。
//@version=6
indicator("マルチアラート", overlay=true)
// パラメータ
fastLen = input.int(12, "短期EMA")
slowLen = input.int(26, "長期EMA")
rsiLen = input.int(14, "RSI期間")
rsiOB = input.int(70, "RSI買われすぎ")
rsiOS = input.int(30, "RSI売られすぎ")
// 計算
emaFast = ta.ema(close, fastLen)
emaSlow = ta.ema(close, slowLen)
rsi = ta.rsi(close, rsiLen)
// 条件
goldenCross = ta.crossover(emaFast, emaSlow)
deadCross = ta.crossunder(emaFast, emaSlow)
rsiOverbought = ta.crossover(rsi, rsiOB)
rsiOversold = ta.crossunder(rsi, rsiOS)
// アラート条件(4つ登録)
alertcondition(goldenCross, "ゴールデンクロス", "{{ticker}}: EMAゴールデンクロス発生")
alertcondition(deadCross, "デッドクロス", "{{ticker}}: EMAデッドクロス発生")
alertcondition(rsiOverbought, "RSI買われすぎ突入", "{{ticker}}: RSIが" + str.tostring(rsiOB) + "を超えました")
alertcondition(rsiOversold, "RSI売られすぎ突入", "{{ticker}}: RSIが" + str.tostring(rsiOS) + "を下回りました")
// 描画
plot(emaFast, "EMA Fast", color.blue, 2)
plot(emaSlow, "EMA Slow", color.red, 2)
plotshape(goldenCross, "GC", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(deadCross, "DC", shape.triangledown, location.abovebar, color.red, size=size.small)
1つのインジケーターにalertcondition()を何個でも書ける。アラート作成ダイアログで、どの条件を使うか選択する形になる。
注意点として、alertcondition()の第3引数(メッセージ)にstr.tostring(rsiOB)のようなinput変数の文字列化は使えるが、str.tostring(rsi)のようなシリーズ変数の文字列化は使えない。バーごとに変わる動的な値をメッセージに入れたい場合はalert()関数を使う。
alert()関数の基本構文
alert()は、条件を満たしたときにスクリプト内から直接アラートを発火する関数だ。
//@version=6
indicator("alert()の例", overlay=true)
sma20 = ta.sma(close, 20)
rsi = ta.rsi(close, 14)
if ta.crossover(close, sma20)
alert("SMA上抜け " + syminfo.ticker + " 価格=" + str.tostring(close) + " RSI=" + str.tostring(rsi, "#.#"), alert.freq_once_per_bar_close)
plot(sma20, "SMA20", color.blue, 2)
alert()の第1引数はメッセージ文字列。alertcondition()と違い、str.tostring(close)やstr.tostring(rsi)で動的な値をメッセージに直接埋め込める。これがalert()最大のメリットだ。
第2引数はトリガー頻度で、3つの選択肢がある。
alert.freq_once_per_bar — 1本のバーにつき最初の1回だけ発火。リアルタイムバーの途中でも条件を満たした瞬間に発火する。
alert.freq_once_per_bar_close — バーの確定時に1回だけ発火。リアルタイムバーの途中では発火しない。確定した値でのシグナルに使う。
alert.freq_all — 条件を満たすたびに毎回発火。リアルタイムバーのティックごとに発火する可能性がある。使いすぎるとアラートが大量に飛ぶので注意。
基本的にはalert.freq_once_per_bar_closeを使うのが安全だ。バーが確定する前の中途半端なシグナルでアラートが飛ぶのを防げる。
alert()を使った実用アラートインジケーター
EMAクロスとRSIフィルターを組み合わせた、実用レベルのアラートインジケーター。
//@version=6
indicator("EMA+RSI アラート", overlay=true)
// パラメータ
fastLen = input.int(12, "短期EMA", group="EMA")
slowLen = input.int(26, "長期EMA", group="EMA")
rsiLen = input.int(14, "RSI期間", group="RSI")
rsiFilter = input.bool(true, "RSIフィルター有効", group="RSI")
rsiOB = input.int(70, "買われすぎ", group="RSI")
rsiOS = input.int(30, "売られすぎ", group="RSI")
// 計算
emaFast = ta.ema(close, fastLen)
emaSlow = ta.ema(close, slowLen)
rsi = ta.rsi(close, rsiLen)
// エントリー条件(RSIフィルター付き)
longSignal = ta.crossover(emaFast, emaSlow) and (not rsiFilter or rsi < rsiOB)
shortSignal = ta.crossunder(emaFast, emaSlow) and (not rsiFilter or rsi > rsiOS)
// alert()で動的メッセージ送信
if longSignal
alert("🟢 買いシグナル\n" + syminfo.ticker + " (" + timeframe.period + ")\n" + "価格: " + str.tostring(close, format.mintick) + "\n" + "RSI: " + str.tostring(rsi, "#.#"), alert.freq_once_per_bar_close)
if shortSignal
alert("🔴 売りシグナル\n" + syminfo.ticker + " (" + timeframe.period + ")\n" + "価格: " + str.tostring(close, format.mintick) + "\n" + "RSI: " + str.tostring(rsi, "#.#"), alert.freq_once_per_bar_close)
// alertcondition()も併設(ユーザー選択用)
alertcondition(longSignal, "買いシグナル", "{{ticker}}: 買いシグナル発生")
alertcondition(shortSignal, "売りシグナル", "{{ticker}}: 売りシグナル発生")
// 描画
plot(emaFast, "EMA Fast", color.blue, 2)
plot(emaSlow, "EMA Slow", color.red, 2)
plotshape(longSignal, "Long", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(shortSignal, "Short", shape.triangledown, location.abovebar, color.red, size=size.small)
alert()とalertcondition()を同じスクリプトに併設しているのがポイントだ。alert()は動的なメッセージ(価格やRSI値入り)を送るため、alertcondition()はシンプルな通知が欲しいユーザーのため。TradingViewのアラート作成時にどちらを使うか選べる。
Pineスクリプトの基本構文を復習したい方はこちら。
→ Pineスクリプトの書き方|基本構文をコード付きで完全解説
ストラテジーでのアラート
strategy()で作成したストラテジーでは、alertcondition()は使えない。代わりに2つの方法がある。
方法①: strategy関数の約定イベントでアラート。コードの変更は不要。TradingViewのアラート作成ダイアログで、ストラテジーを選択すると「注文が約定」「注文が発注」などのイベントを選択できる。
方法②: alert()関数でカスタムアラート。
//@version=6
strategy("アラート付きストラテジー", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
fast = ta.ema(close, 12)
slow = ta.ema(close, 26)
if ta.crossover(fast, slow)
strategy.entry("Long", strategy.long)
alert("ENTRY LONG " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
if ta.crossunder(fast, slow)
strategy.close("Long")
alert("EXIT LONG " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
plot(fast, "Fast", color.blue)
plot(slow, "Slow", color.red)
ストラテジーではstrategy.entry()やstrategy.close()の直後にalert()を置くパターンが一般的だ。アラート作成ダイアログでは「alert()関数の呼び出し」を選択する。
Webhook連携でJSON送信
alert()のメッセージにJSON文字列を入れれば、Webhook経由で外部サービスに構造化データを送信できる。自動売買botとの連携に使われるパターンだ。
//@version=6
indicator("Webhookアラート", overlay=true)
fast = ta.ema(close, 12)
slow = ta.ema(close, 26)
longSignal = ta.crossover(fast, slow)
shortSignal = ta.crossunder(fast, slow)
if longSignal
alert('{"action":"buy","ticker":"' + syminfo.ticker + '","price":' + str.tostring(close) + ',"time":"' + str.tostring(timenow) + '"}', alert.freq_once_per_bar_close)
if shortSignal
alert('{"action":"sell","ticker":"' + syminfo.ticker + '","price":' + str.tostring(close) + ',"time":"' + str.tostring(timenow) + '"}', alert.freq_once_per_bar_close)
plot(fast, "Fast", color.blue)
plot(slow, "Slow", color.red)
TradingViewのアラート作成ダイアログで「通知」タブを開き、「Webhook URL」に受信先のURLを入力する。「メッセージ」欄は空にしておけば、alert()で指定した文字列がそのまま送信される。
Webhook連携はTradingViewの有料プラン(Pro以上)が必要だ。
時間帯限定アラート
特定の市場セッション内でのみアラートを鳴らすインジケーター。セッション外のノイズシグナルを除外できる。
//@version=6
indicator("セッション限定アラート", overlay=true)
// セッション設定
sessionStr = input.string("0800-1630", "セッション", tooltip="HHMM-HHMM")
sessionTZ = input.string("Europe/London", "タイムゾーン", options=["Asia/Tokyo", "Europe/London", "America/New_York"])
// EMA
fast = ta.ema(close, 12)
slow = ta.ema(close, 26)
// セッション内判定
inSession = not na(time(timeframe.period, sessionStr, sessionTZ))
// セッション内のみシグナル
longSig = ta.crossover(fast, slow) and inSession
shortSig = ta.crossunder(fast, slow) and inSession
// アラート
alertcondition(longSig, "セッション内買い", "{{ticker}}: セッション内でGC発生")
alertcondition(shortSig, "セッション内売り", "{{ticker}}: セッション内でDC発生")
if longSig
alert("BUY " + syminfo.ticker + " in " + sessionTZ + " session, price=" + str.tostring(close, format.mintick), alert.freq_once_per_bar_close)
// 描画
plot(fast, "Fast", color.blue)
plot(slow, "Slow", color.red)
bgcolor(inSession ? color.new(color.gray, 95) : na)
plotshape(longSig, "Long", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(shortSig, "Short", shape.triangledown, location.abovebar, color.red, size=size.small)
and inSessionの一句を条件に追加するだけで、セッション外のシグナルを完全に除外できる。時間帯の指定方法を詳しく知りたい方はこちら。
→ Pineスクリプトで時間指定する方法|東京・ロンドン・NY時間の実装コード
TradingViewでのアラート作成手順
コードを書いた後、TradingView上でアラートを有効化する手順を確認しておく。
ステップ1: インジケーターをチャートに追加する。Pineエディタで「保存」→「チャートへ追加」。
ステップ2: チャート上部のツールバーにある「アラート」アイコン(時計マーク)をクリック、またはAlt + A(Mac: Option + A)を押す。
ステップ3: 「条件」のドロップダウンで、追加したインジケーター名を選択する。
ステップ4: alertcondition()を使っている場合は、その下のドロップダウンでアラート条件(タイトル)を選ぶ。alert()を使っている場合は「alert()関数の呼び出し」を選ぶ。
ステップ5: トリガー頻度を設定する。「バーにつき1回」が一般的だ。
ステップ6: 「通知」タブで通知方法を選ぶ。アプリ通知、メール、Webhookなど。
ステップ7: 有効期限を設定し、「作成」をクリック。
重要なのは、スクリプトを変更した場合、既存のアラートには反映されないということだ。スクリプトを修正したら、古いアラートを削除して新しいアラートを作り直す必要がある。
アラートの制限事項
TradingViewのアラートにはプランによる制限がある。
無料プラン(Basic)はアクティブアラート1件。Essentialは20件。Plusは100件。Premiumは400件。Expertは800件。Ultimateは無制限だ。
スクリプトアラートが3分間に15回以上トリガーされると、自動的に停止される。alert.freq_allを使うときは特に注意が必要だ。
アラートはリアルタイムバーでのみトリガーされる。ヒストリカルバー(過去のバー)ではalertcondition()もalert()も発火しない。つまり、バックテストではアラートの動作を確認できない。
Webhook連携はPro以上の有料プランが必要だ。
よくあるミスと対処法
ミス①: コードを書いたのにアラートが鳴らない。alertcondition()はアラート条件を「登録」するだけ。TradingViewのアラート作成ダイアログで手動でアラートを作成する必要がある。
ミス②: alertcondition()をストラテジーで使おうとする。alertcondition()はインジケーター(indicator())専用。ストラテジー(strategy())では使えない。ストラテジーではalert()を使うか、約定イベントでアラートを設定する。
ミス③: スクリプト変更後もアラートが古い条件で発動する。アラート作成時のスクリプト状態がサーバーに保存される。スクリプトを変更したら、アラートを削除して作り直す。
ミス④: alertcondition()のメッセージに動的な値を入れようとする。str.tostring(rsi)のようなシリーズ変数はalertcondition()のメッセージには使えない。動的な値を含めたい場合はalert()関数を使う。
ミス⑤: alert.freq_allで大量アラートが飛ぶ。リアルタイムバーのティックごとに条件を評価するため、数秒間に何十回もアラートが発火する可能性がある。通常はalert.freq_once_per_bar_closeで十分だ。
まとめ
Pineスクリプトのアラートはalertcondition()とalert()の2つ。インジケーターで複数の条件を登録したいならalertcondition()、動的なメッセージやWebhook連携ならalert()を使う。どちらもコードを書いた後にTradingView上でアラートを手動作成する手順が必要だ。
アラートのトリガー頻度はalert.freq_once_per_bar_closeが安全。スクリプトを変更したらアラートは作り直す。この2点を押さえておけば、意図しない動作を防げる。
















