Pine Scriptのサンプルでstrategy.entryを書いてみたものの、

「これを動かすとMT5のEAと同じように実際の注文が飛ぶのか」

が分からず不安になったことはありませんか。

既刊ctrade-mql5.md/ordersend-mql5.mdでは、

MQL5のCTradeクラスとMqlTradeRequest構造体を、

使った発注方法を解説してきました。

この記事では、Pine Scriptの発注用関数

strategy.entry()/

strategy.close()/strategy.exit()を、

MQL5の発注方法と対比しながら解説します。

この記事で分かること
・strategy.entry/close/exitの基本
・CTrade/OrderSendとの対応
・発注コードがブローカーに直結していない設計
・v6で廃止されたwhenの書き直し方
・ネッティングの違い

strategy.entry/close/exitの基本とCTrade/OrderSendとの対応

まず、それぞれの基本的な書式を確認します。

Pine Scriptのstrategy.entry()の書式

strategy.entry(id = "Long", direction = strategy.long, qty = 1)

idは後で決済と紐付けるための名前、

directionはstrategy.long/strategy.shortの、

どちらかです。

CTrade/OrderSendとの対応表

役割 Pine Script MQL5
新規発注 strategy.entry() CTrade.Buy()/Sell()、またはOrderSend()
決済(個別) strategy.close(id) CTrade.PositionClose()
決済(全部) strategy.close_all() 保有中の全チケットをループしてPositionClose()
SL/TP変更 strategy.exit() CTrade.PositionModify()

最大の違い: Pine Scriptの発注コードはブローカーに直結していない

ここが、MQLユーザーが最初に戸惑うポイントです。

MQL5はMetaTrader端末自体がブローカーに接続している

MQL5のEAは、MetaTrader 5端末にアタッチして動かします。

端末自体がブローカーのサーバーに接続しているため、CTrade.Buy()を呼び出すと、

その場でブローカーへ注文が送信されます。

Pine Scriptのstrategy.*はTradingView内のシミュレーション

MQLユーザーが驚くポイント
・strategy.entry()を呼んでも実際の注文はブローカーに送られない
・strategy.*はTradingView内で損益を計算するだけの仕組み
・実際の売買につなげるにはalert()経由でWebhookを送り
別のボットに代行させる必要がある

つまりPine Script単体は、発注の「シミュレーションと通知」までしか担当しません。

v6で廃止されたwhenパラメータとポジションの数え方の違い

ここでは、見落としやすい2つの変更点・考え方の違いをまとめます。

v5までのwhenパラメータ(v6では使えない)

// v5時代の書き方、v6ではコンパイルエラーになる
strategy.entry("Long", strategy.long, when = longCondition)

v5までは、関数呼び出しの中にwhen引数を入れて条件分岐できましたが、

v6ではstrategy.entry()・strategy.close()から、

whenパラメータが削除されました。

v6での書き方(if文で囲む)

// v6の書き方
if longCondition
    strategy.entry("Long", strategy.long)

v6では、MQLのif文と同じように、呼び出し自体をif文で囲む書き方に統一されています。

古いサンプルコードをコピーして動かないとき、まずこの違いを疑ってください。

ポジションの数え方(ネッティング)の違い

補足
・strategy()は既定でネッティング方式
(同方向の複数回entryは1つに合算)
・積み増しを許可するにはpyramiding
引数で回数を指定する
・MQL4は常にヘッジモード
(反対方向の注文を同時に持てる)
・MQL5は設定でどちらにもなる

Pine Scriptの「ポジション」は、MQL4の「チケット1枚ごと」

とは数え方の前提が違います。

strategy.exit()とfrom_entryによるSL/TPの紐付け

決済用関数の使い方です。

from_entryでエントリーIDと紐付ける

strategy.exit(id = "LongExit", from_entry = "Long", loss = 100, profit = 200)

from_entryに指定したidのエントリーに対して、

loss(ストップロス)・profit(テイクプロフィット)を、

ティック数で設定します。

MQL5はPositionModify()でSL/TPを直接書き換える

trade.PositionModify(_Symbol, sl, tp);

MQL5側は、ポジションのSL/TPの価格そのものを直接書き換える方式で、

idによる紐付けという概念自体がありません。

実際に動くサンプルコード

移動平均線のクロスで発注し、固定ティック数でSL/TPを設定するサンプルです。

//@version=6
strategy("MA Cross Sample", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 10)

fastLen = input.int(10, title = "短期期間", minval = 1)
slowLen = input.int(30, title = "長期期間", minval = 1)

fastMa = ta.sma(close, fastLen)
slowMa = ta.sma(close, slowLen)

longCondition = ta.crossover(fastMa, slowMa)
shortCondition = ta.crossunder(fastMa, slowMa)

if longCondition
    strategy.entry("Long", strategy.long)

if shortCondition
    strategy.entry("Short", strategy.short)

strategy.exit("LongExit", from_entry = "Long", loss = 100, profit = 200)
strategy.exit("ShortExit", from_entry = "Short", loss = 100, profit = 200)

plot(fastMa, color = color.orange)
plot(slowMa, color = color.blue)

ta.crossover/ta.crossunderは、

既刊のクロス判定記事で解説した組込み関数です。

TradingViewでの貼り付け・実行手順

実際にTradingViewで動かすまでの手順です。

  1. TradingViewのチャート画面下部にある「Pineエディタ」タブを開く
  2. 新規スクリプトを作成し、上のコードを貼り付ける
  3. 「保存」してから「チャートに追加」をクリックする
  4. 画面下部に表示される「Strategy Tester」タブで、仮想の損益推移を確認する
  5. 実際の売買に使いたい場合は、別途Webhook連携のボット/サービスと組み合わせる(本記事の対象外)

よくあるエラーと注意点

実装でつまずきやすいポイントをまとめます。

strategy.entry()を使うにはindicator()ではなくstrategy()で宣言する

既刊記事群のカスタムインジケーターはindicator()で宣言していましたが、

strategy.*関数を使う場合は、

スクリプトの先頭をstrategy()で宣言する必要があります。

whenパラメータを使った古いコードがv6でエラーになる

注意
・古いサンプルにはwhen=を使ったコードが多い
・v6ではコンパイルエラーになるためif文に直す
・strategy.close()も同様にwhenが廃止されている

デモアカウントでもブローカーへ注文は飛ばない

TradingViewの画面上で損益が動いているのを見ても、

それは画面内のシミュレーションであり、どのブローカーにも注文は送信されていません。

よくある質問

strategy.entry/close/exitについて、

よく検索される疑問に回答します。

実践アドバイス
・when=を見つけたらif文に書き直す
・個別チケットのように分けたい場合は
pyramiding引数の値を確認する
・実売買に使う前に、必ずStrategy
Testerタブで想定どおりか確認する

strategy.close_all()とstrategy.close()はどう使い分けますか?

strategy.close_all()は保有中の全ポジションを一括決済します。

strategy.close(id)は、指定したidのエントリーだけを決済します。

複数の戦略ロジックを1つのスクリプトに同居させる場合は、

idで個別に決済できるstrategy.close()を使います。

strategy.entry()を同じidで2回呼ぶとどうなりますか?

strategy()宣言のpyramiding引数が0(既定値)のままだと、

2回目の呼び出しは積み増しされず、実質的に無視されます。

積み増しを許可したい場合は、pyramiding引数に1以上の回数を指定します。

MQL5のOrderSend()はPine Scriptのどの関数に近いですか?

処理の役割としてはstrategy.entry()が最も近いですが、

OrderSend()はMqlTradeRequest構造体を、

自分で組み立てて送信する低レベルな関数で、

strategy.entry()は引数を指定するだけで済む高レベルな関数です。

役割の近さではCTrade.Buy()/Sell()の方が、

strategy.entry()に近いといえます。

【Pine Script入門】strategy.entry/close/exitで発注する方法をMQLユーザー向けに解説してみた(CTrade/OrderSendとの比較):まとめ

Pine Scriptのstrategy.entry()/

strategy.close()/strategy.exit()は、

MQL5のCTrade.Buy()/Sell()/PositionModify()と、

役割は近いものの、

実際にブローカーへ注文が送られるかどうかという、

最も大きな前提が異なります。

v6で廃止されたwhenパラメータの書き直し方、

ネッティングによるポジションの数え方の違いも、

MQL4/MQL5のヘッジモデルに慣れた読者が、

まず戸惑うポイントとして押さえておいてください。

関連記事