【MQL5】損切り・利食いを自動設定!CTradeを使ったSL/TP注文の正しい書き方

MQL5 開発講座

こんにちは、潤奈です( ゚Д゚)!

前回の記事では、これまでに学んだ「注文」「決済」「インジケーター」の3つの要素を組み合わせて、実際に動く「ゴールデンクロスEA」を作成しました。
EAの基本サイクルができるようになったら、次に絶対に実装すべきなのが「ストップロス(損切り:SL)」「テイクプロフィット(利食い:TP)」の設定です!

自動売買において、損切りを設定しないことは「ブレーキの壊れた車」で高速道路を走るようなものです。急激な相場の逆行から大切な資金を守るためにも、SL/TPの設定方法は必ずマスターしておきましょう。

今回も標準ライブラリの CTrade を使って、新規注文と同時にSL/TPを設定する正しい書き方と、注文が拒否されないための「価格の正規化」について分かりやすく解説します!


1. MQL5のSL/TP設定はなぜ難しい?(MQL4との違い)

まずはMQL4とMQL5の違いを理解しておきましょう。

MQL4では、注文を送信する OrderSend 関数の引数に、直接SLとTPの「価格」を指定することができました。

MQL5でも、標準ライブラリの CTrade を使うことで同様に注文時にSL/TPを指定できますが、以下の「MQL5ならではの注意点」があります。

  • trade.Buy などの注文関数に渡すSL/TPは、pips(ピップス)やポイント数ではなく、「具体的なレート価格(例: 150.50)」で渡さなければならない。
  • 計算した価格を、ブローカーの価格桁数に合わせて「正規化(丸め処理)」しないと、注文が拒否されてエラー(INVALID_STOPS)になる。

特に2つ目の「価格の正規化」は、MQL5で最も注文失敗が発生しやすいバグの原因ですので、正しい書き方をしっかりと身につけましょう。


2. 新規注文時にSL/TPを設定する方法

CTrade ライブラリの BuySell 関数には、引数の渡し方がいくつか用意されています。
これまで使っていた trade.Buy(0.1) などのシンプルな書き方は、SL/TPなどを省略した「省略形」でした。

注文時にSL/TPを指定するには、以下のように引数をしっかり指定するフル形式の関数を使用します。

買い注文でのSL/TP指定方法

  • Lots: ロット数(例: 0.1
  • Symbol: 通貨ペア名(例: _Symbol
  • Price: エントリー価格。成行買いの場合は 0 または現在の買値(Ask)を指定します。(通常は 0 を指定するとブローカー側で最新のAskで成行約定してくれます)
  • SL: 損切り価格(レート)
  • TP: 利食い価格(レート)
  • Comment: 注文コメント(任意の文字列)

⚠️ 超重要:SL/TP価格の計算と「正規化」

例えば、現在のドル円のAskが 150.000 だとして、「15pips(150ポイント)の損切り(SL)」「30pips(300ポイント)の利食い(TP)」を設定したい場合、価格は以下のように計算します。

  • 買い注文
    • SL価格 = Ask - (150 * _Point) 👉 現在地よりに設定
    • TP価格 = Ask + (300 * _Point) 👉 現在地よりに設定
  • 売り注文
    • SL価格 = Bid + (150 * _Point) 👉 現在地よりに設定
    • TP価格 = Bid - (300 * _Point) 👉 現在地よりに設定

そして、この計算した価格をそのまま送信してはいけません。PC内部の計算では浮動小数点数の微小な誤差(例: 150.0000000001 など)が含まれており、そのままブローカーに送ると「無効なストップ価格」として注文が拒否されてしまいます。

そこで、必ず NormalizeDouble() 関数を使って、ブローカーが定義している小数点桁数(_Digits)に端数を丸めます。

この NormalizeDouble(価格, _Digits) は、MQL5プログラミングにおける必須のコーディングルールです!

[!IMPORTANT]
ブローカーの「ストップレベル」に注意!
エラー(INVALID_STOPS)が発生するもう一つの大きな原因が「ストップレベル」です。ブローカーや通貨ペアによっては、「現在価格から最低○ポイント以上離してSL/TPを設定しなければならない」という制限(ストップレベル)が設定されています。あまりに現在地に近い価格を指定すると注文が拒否されるため、スキャルピングEAなどを作る際は注意が必要です。


3. 保有中のポジションのSL/TPを変更する(PositionModify)

エントリー時にはSL/TPを設定せず、後から手動や特定のロジック(トレーリングストップなど)でSL/TPを設定・変更したい場合は、trade.PositionModify() を使用します。

基本コード

  • Ticket: 変更したいポジションのチケット番号(ID)
  • SL: 新しい損切り価格(レート)
  • TP: 新しい利食い価格(レート)

【実践向け】ポジションの存在と選択を明示的にチェックする

すでに決済されて存在しないポジションに対して PositionModify を実行するとエラーになるため、前回のループ処理同様、PositionSelectByTicket() を使ってポジションの存在を確認してから処理を実行するのがベストプラクティスです。


4. コピペで動く!SL/TP設定機能付きサンプルEA

それでは、実際の挙動を確認するためのサンプルコードを紹介します。
このコードは、「EAをチャートにセットした瞬間に、0.1ロットの買い注文を出し、同時に15pips(150ポイント)のSLと30pips(300ポイント)のTPを自動で設定する」というEAテンプレートです。

前回の「新バー判定」を取り入れた、より堅牢な設計になっています(新規注文処理に特化しているため、ポジション選択処理は含めていません)。

このコードを MetaEditor でコンパイルしてチャートにセットすると、即座に発注が行われます。MT5の「取引」ターミナルを確認すると、注文されたポジションにしっかりと赤い破線(SL/TPの価格)が表示されます!


5. まとめ&次のステップ

今回は、MQL5における損切り(SL)と利食い(TP)の自動設定方法を解説しました。

  • 注文時にSL/TPを設定する際は、省略形ではなくフル引数形式の trade.Buy / trade.Sell を使用する。
  • SL/TPはポイント数ではなく具体的なレート価格を計算して渡す。
  • 浮動小数点エラーによる注文拒否を防ぐため、NormalizeDouble(価格, _Digits) による正規化は必須。
  • 後から変更する場合は trade.PositionModify() を使用する。

これで、安全に資金を保護しながら運用できるEAのプログラムが書けるようになりました。

次回は、リスク管理をさらに一歩進め、「口座残高の○%の損失に収まるように、エントリー時のロット数を自動で計算・調整する資金管理ロジック」について解説します。ロット数を固定するのではなく、資金量に合わせて自動変更する本格的な実践向けEA作りに挑戦しましょう!

今回のコードで「ストップエラー(エラーコード 10016)が出て注文が通らない」「pips換算の計算がうまくいかない」などの質問があれば、YouTubeのコメント欄やXでお気軽にご連絡くださいね!

🎥 YouTubeチャンネル: 潤奈【FXチャンネル】
🐦 X (Twitter): @zyuna32246

コメント

タイトルとURLをコピーしました