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内のシミュレーション
・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で動かすまでの手順です。
- TradingViewのチャート画面下部にある「Pineエディタ」タブを開く
- 新規スクリプトを作成し、上のコードを貼り付ける
- 「保存」してから「チャートに追加」をクリックする
- 画面下部に表示される「Strategy Tester」タブで、仮想の損益推移を確認する
- 実際の売買に使いたい場合は、別途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のヘッジモデルに慣れた読者が、
まず戸惑うポイントとして押さえておいてください。
コメント