Pine Scriptのリスク制限機能|ドローダウン・日次損失・建玉上限
strategy.exit()の逆指値は一つの建玉やエントリーを閉じる注文ですが、strategy.risk.*は戦略全体に適用され、条件到達時に未約定注文の取消、保有中の建玉の決済、追加取引の停止や数量縮小を強制します。本記事は「何%で止めるべきか」を推奨しません。各命令がどの範囲へ、いつ、何を強制し、その結果として取引母集団がどう変わるかを監査します。
この記事が役立つ方: Pineストラテジーへ戦略全体の制限を追加したい開発者/リスク制御命令の発動後に注文が消える理由を調べたい人
まず押さえる重要ポイント
- 取引ごとの決済、注文数量、戦略全体のリスク制御命令を三つの別レイヤーとして設計する。
strategy.risk.*はコード位置にかかわらず戦略全体へ適用され、特定実行だけ一時無効にする用途ではない。- ドローダウン、日内損失、連敗日数、約定回数、建玉サイズ、許可方向は、発動条件と停止期間がそれぞれ異なる。
- 日足より上の時間足では日内制御が1本のチャートバー単位になる仕様など、名称だけで挙動を推測しない。
- 全体制限追加後は取引数・決済理由・損益分布が変わるため、元ストラテジーとは別バージョンとして出力・比較する。
strategy.riskは戦略全体に適用する強制ルール
- 01シグナルと数量設計
エントリー条件/注文数量/同方向の追加建玉いつ・どれだけ建てるか
- 02取引単位の決済
strategy.exit/strategy.close個別エントリーをどう閉じるか
- 03戦略全体の制限
strategy.risk.*戦略全体の許可・上限・停止
- 1しきい値へ到達
- 2未約定注文を取り消す
- 3建玉を決済または縮小する
- 4命令の適用範囲で以後の取引を停止する
結論:リスク制御命令は成績指標ではなく強制ルール
strategy.risk.max_drawdown()は最大ドローダウンを表示する変数ではありません。指定条件へ達すると未約定注文を取り消し、保有中の建玉を閉じ、追加の取引を停止する全体ルールです。一方、strategy.max_drawdownやストラテジーテスターのドローダウンは、過去に起きた結果を表す指標です。名前が近くても役割は別です。
| 層 | 代表例 | 作用 | 質問 |
|---|---|---|---|
| 計測 | strategy.max_drawdown/ドローダウンレポート | 結果を測る | 過去にどれだけ沈んだか |
| 取引単位の制御 | strategy.exitの逆指値 | 特定エントリーの決済注文 | この建玉をどこで閉じるか |
| 戦略全体の強制動作 | strategy.risk.* | 全注文・全建玉へ制約 | 戦略の行動をいつ止めるか |
測定値を見ているのか、将来のシミュレーション行動を変更しているのかを区別します。
六つの命令を発動条件と作用範囲で選ぶ
| 命令 | 監視するもの | 主な発動時の作用 | 境界上の注意 |
|---|---|---|---|
| allow_entry_in | 許可する方向 | 反対方向エントリーを新規反転でなく既存建玉の終了へ制限 | strategy.entryへの作用を確認 |
| max_cons_loss_days | 連続する損失日数 | 未約定注文の取消、保有建玉の決済、追加取引の停止 | 「日」の区切りを確認 |
| max_drawdown | 最大資産残高からのドローダウン額または率 | 未約定注文の取消、保有建玉の決済、以後の取引停止 | 割合は最大資産残高が基準 |
| max_intraday_filled_orders | 日内約定注文数 | 上限後、セッション終了まで取消・決済・停止 | 日足より上では1本のチャートバー単位 |
| max_intraday_loss | 日内損失額または率 | 到達後、セッション終了まで取消・決済・停止 | 日足より上では1本のチャートバー単位 |
| max_position_size | strategy.entry後の建玉数量 | 上限内へエントリー数量を縮小し、不可能なら注文を抑止 | strategy.orderなどへ同じ形で効くとは限らない |
正確な引数、単位、再開条件は現行TradingView公式ドキュメントを優先してください。
これらは互いに排他的ではなく、複数を同時に置けます。その場合、最初に発動した制約が注文や建玉を変え、後続の測定系列も変わります。「どの命令が発動したか」を取引一覧だけから完全に推測しにくいため、alert_message、注文コメント、Pine Log、バージョン名で設定を残します。
ifの中へ置いて一時的に有効化する発想を捨てる
TradingViewの公式説明では、リスク管理命令は計算動作の変更にかかわらず、各ティックと注文実行イベントで作用し、コードの場所に関係なくストラテジーへ適用されます。特定バーだけ無効化する仕組みではありません。条件付きで呼べば時間帯だけ全体制限が有効になる、と推測せず、入力値を固定した独立バージョンとして設計します。
特に「日内」という名称の挙動は時間足に依存します。日足より高い時間足では、最大日内損失や日内約定数が1本のチャートバー単位として扱われます。週足で「毎日リセットされる」と考えるのは誤りです。セッションの境界も銘柄とチャート条件で確認します。
| 順序 | 確認内容 | 証拠 |
|---|---|---|
| 1 | しきい値へ到達したバー/ティック | 資産残高、日内損益、約定注文数 |
| 2 | 未約定注文の取消 | 注文ID、取消後の再発行有無 |
| 3 | 保有中の建玉の強制決済または数量縮小 | 決済コメント、価格、注文数量 |
| 4 | 追加エントリーが停止した範囲 | 次に条件がtrueとなった時点と注文の不在 |
| 5 | 再開またはシミュレーション終了 | 取引時間帯境界、次バー、以後の取引一覧 |
命令ごとに停止範囲が異なるため、同じ表を別々に埋めます。
決済・同方向の追加建玉・必要証拠金・取引時間帯との交差を確認する
戦略全体の命令は、個別決済の代替ではありません。各取引の価格ベース逆指値が先に約定する場合もあれば、日内損失制限が先に全建玉を閉じる場合もあります。決済理由が変わればMFE/MAEや保有時間も変わるため、通常決済とリスク制御による決済を同じラベルへまとめません。
| 相手側 | 起きること | 監査方法 |
|---|---|---|
| strategy.exitの利確・損切り注文 | 個別SL/TPと全体制限の先着競争 | 決済ID/コメントで決済理由を分ける |
| 同方向の追加建玉 | 複数エントリーが建玉上限や日内約定注文数の上限へ早く到達 | opentradesと約定処理数を両方記録 |
| 必要証拠金 | リスクしきい値前に証拠金不足による強制処理が建玉を縮小 | 必要証拠金イベントを制限発動と混同しない |
| セッションフィルター | エントリー候補と日内リセット境界が変わる | IANAタイムゾーンとセッションを固定 |
| process_orders_on_close | 強制決済の約定時点が変わり得る | 注文作成バーと約定バーを分ける |
TV16は数量、TV17は注文状態、TV19は取引時間帯判定を個別に扱います。
max_position_size()はstrategy.entry()で結果建玉が上限を超えるとき、エントリー数量を許容範囲へ縮小します。指定最小数量でも上限を満たせなければエントリーを作らない場合があります。strategy.order()まで万能に制限する前提を置かず、使う注文APIごとに小さなテストを作ります。
教育用閾値を入力値へ出し、基準版との差を一つずつ測る
以下は複数のリスク制御命令を宣言する構造例です。初期値は機能確認用の架空値で、安全値や推奨値ではありません。実務では最初にすべてを入れず、一つの命令だけ有効なバージョンから比較してください。単純な移動平均交差も動作を発生させるための例です。
//@version=6
strategy("Strategy risk guardrail audit", overlay = true, pyramiding = 3,
initial_capital = 100000, margin_long = 100, margin_short = 100)
float maxDrawdownInput = input.float(20.0, "Max drawdown (%)", minval = 0.1, maxval = 100)
float maxDayLossInput = input.float(4.0, "Max intraday loss (%)", minval = 0.1, maxval = 100)
int maxFillsInput = input.int(6, "Max intraday filled orders", minval = 1)
int maxLossDaysInput = input.int(3, "Max consecutive loss days", minval = 1)
float maxPositionInput = input.float(4.0, "Max position units", minval = 1)
strategy.risk.max_drawdown(maxDrawdownInput, strategy.percent_of_equity)
strategy.risk.max_intraday_loss(maxDayLossInput, strategy.percent_of_equity)
strategy.risk.max_intraday_filled_orders(maxFillsInput)
strategy.risk.max_cons_loss_days(maxLossDaysInput)
strategy.risk.max_position_size(maxPositionInput)
float fast = ta.ema(close, 20)
float slow = ta.ema(close, 50)
bool longSignal = ta.crossover(fast, slow)
bool shortSignal = ta.crossunder(fast, slow)
if longSignal
strategy.entry("Long", strategy.long, qty = 2)
if shortSignal
strategy.entry("Short", strategy.short, qty = 2)
plot(fast, "Fast", color.aqua)
plot(slow, "Slow", color.orange)
plot(strategy.equity, "Equity", display = display.data_window)
plot(strategy.position_size, "Position size", display = display.data_window)初期値は架空の機能確認用です。一つずつ命令を外した基準版と同じ期間・銘柄・コストで比較してください。
公開前には各リスク制御命令へ説明的な入力値名と補足説明を付け、割合と金額の単位を混ぜないようにします。strategy.max_drawdown、strategy.equity、建玉サイズ、決済済み取引をデータウィンドウへ表示し、リスク制御命令の設定値とは別欄にします。
最大資産残高から現在地と仮想次損失を測る
ミニ計算機は、現在資産≤過去最高資産を入力前提とし、過去最高資産、現在資産、設定したドローダウン率、次に仮定する損失額から、現在ドローダウン率・損失後ドローダウン率・設定した上限までの現在時点の残額を表示します。しきい値の推奨や発動価格の予測ではありません。公式の資産比率によるドローダウン制御が最大資産残高を基準にする関係を理解する教育用です。
現在のドローダウン額 = max(過去最高資産 − 現在資産, 0)現在のドローダウン率 = 現在のドローダウン額 ÷ 過去最高資産 × 100想定後のドローダウン率 = max(過去最高資産 − (現在資産 − 次の損失), 0) ÷ 過去最高資産 × 100現在の残額 = max(過去最高資産 × 設定上限率 ÷ 100 − 現在のドローダウン額, 0)現在資産≤過去最高資産が前提です。含み益の変動、注文約定、窓、スリッページ、命令の内部評価順序は再現しません。strategy.risk.max_drawdownをstrategy.percent_of_equityで指定した状態で資産残高が0以下になると、注文取消・建玉決済後に新規注文が以後停止するため、100%超の単純ドローダウンを継続可能な余力と解釈しません。- 基準版を保存
リスク制御命令なしのストラテジーテスター結果と設定を出力します。
- 一つ追加
建玉上限など一つだけを加え、同じ条件で再実行します。
- 発動取引を特定
最初に取引一覧が分岐したバー、注文、建玉を記録します。
- 母集団差を確認
取引数、決済理由、保有時間、損益分布、ドローダウンを比較します。
- 複合版を作る
単独差分を説明できた命令だけを組み合わせます。
発動イベント台帳を基準版と制限あり版へ結び付ける
- 命令名、値、金額/割合単位をバージョン記録へ残したか
- 発動前後の未約定、保有中の建玉、追加エントリーを追跡したか
- リスク制御による決済、通常決済、証拠金不足による強制処理を区別したか
- 時間足とセッション境界、とくに日足より上での日内挙動を確認したか
- max_position_sizeが使う注文APIへ実際に作用したか
- 基準版と同じ銘柄・期間・数量・コストでCSVを再出力したか
ドローダウン曲線だけでは発動の証拠にならないため、全体制限の発動台帳を作ります。命令ごとにバージョンID、引数と単位、監視基準、最初の発動バー、発動直前値、取消注文、強制決済、縮小注文数量、以後拒否されたエントリーを一行で残し、基準版と制限あり版のCSVへ結び付けます。
最初に取引一覧が分岐した事象を台帳で説明できなければ、ドローダウン差を全体制限の効果と断定しません。複数命令版は、単独命令版の発動行をすべて説明できた後にだけ作り、リスク制御による決済、通常決済、証拠金不足による強制処理を別の理由として保存します。
過去最高資産からのドローダウン概算
現在資産≤過去最高資産を入力前提として、現在ドローダウンと仮想次損失後のドローダウンを最大資産残高を基準に確認します。しきい値の推奨ではありません。
入力前提:b≤a。現在ドローダウン=max(a−b,0)÷a×100、想定後ドローダウン=max(a−(b−d),0)÷a×100、残り=max(a×c÷100−max(a−b,0),0)。残りは現在ドローダウンから見た現在時点の残額です。注文・含み益・窓・スリッページ・内部発動順序は含みません。資産残高≤0時の資産比率によるリスク制御命令の停止動作は別途確認します。
よくある質問
strategy.risk.max_drawdown()とstrategy.max_drawdownは同じですか?
違います。前者は条件到達時に戦略行動を止める命令、後者はシミュレーションで観測された最大ドローダウンの値です。
リスク制御命令をifの中に置けば特定時間だけ有効になりますか?
そのような一時切替として設計しないでください。公式説明ではリスク制御命令はコード位置にかかわらずストラテジー全体へ適用され、特定実行だけ無効化できません。
max_intraday_lossは週足でも毎日リセットされますか?
日足より高い時間足では1本のチャートバー単位として扱われる仕様があります。名称だけで推測せず、対象時間足とセッションで小さなテストを行ってください。
資産比率のmax_drawdownで資産残高が0以下になるとどうなりますか?
strategy.risk.max_drawdown()をstrategy.percent_of_equityで使う場合、資産残高が0以下になると未約定注文は取り消され、保有中の建玉は決済され、新しい注文は以後作成できません。ミニ計算機の100%超ドローダウンは算術表示であり、ストラテジーが取引を継続できる意味ではありません。
strategy.risk.max_position_size()は大きすぎるエントリーを必ず拒否しますか?
必ずしも全面的に拒否されるわけではありません。上限内へ収まる有効数量へ縮小できる場合は注文数量が減り、銘柄の最小取引数量でも上限を超える場合は注文が作成されません。要求注文数量と実効注文数量を発動台帳で分けます。
根拠資料と確認先
- TradingView Pine Script — Strategiesリスク管理命令、必要証拠金、注文の相互作用に関する公式解説。
- TradingView Pine Script — Reference Manual v6各strategy.risk命令の引数・型・作用を確認できる公式リファレンス。
- TradingView Pine Script — Strategies FAQポジションサイジング、独自統計、ストラテジー動作に関する公式FAQ。
- TradingView Help — Strategy properties資金・数量・必要証拠金・再計算条件の公式対応表。
- TradingView Pine Script — Migration to v6v6の既定の必要証拠金など、バージョン差に関する公式説明。
編集・発行: SG Group · 編集方針: TradingView公式ヘルプとPine Script公式文書を優先し、金融市場・商品に関する説明は取引所、監督当局、一次資料で補完しています。機能、データ、料金、接続条件は変わるため、実際の利用前に公式画面とリンク先の最新情報を確認してください。
重要事項: 本記事はTradingViewの画面、チャート、アラート、スクリーナー、ペーパートレード、Pine Script等の一般的な学習情報です。投資助言、売買シグナル、特定商品・データ提供者・ブローカーの推奨、将来価格や利益の保証ではありません。機能、料金、データ、取引所区分、通知、注文連携、Pine Scriptの仕様はプラン・地域・接続先・時点で異なり変更されることがあります。実際の資金を使う前に、TradingView公式資料、データ提供元、接続先事業者の最新条件を確認し、架空データまたはペーパートレードで手順を検証してください。

