【MQL4関数】OrderClose関数の使い方!決済注文の出し方とサンプルプログラム

【中級編】MQLプログラムの読み方・書き方
朝日奈りさ
朝日奈りさ

自動売買にポジションを決済させるにはどうしたら良いの?

OrderClose関数とは

条件に当てはまったときに、ポジションを自動的に決済(クローズ)して欲しいですよね!

そこで、OrderClose関数を使います。

 

OrderClose関数とは、ポジションを1つ選択し、決済注文を出す関数です。

実行させることで、FX会社に決済注文を出してくれます。

決済できるポジションの種類は、以下の通りです。

  • 保有ポジション
  • 指値ポジション
  • 逆指値ポジション

 

つまり、注文を出したポジションであれば、どんなポジションでも決済できます。

OrderClose関数をプログラムに組み込んで、自動的にポジションを決済させてみましょう。

 

OrderClose関数の書き方

OrderClose関数の使い方は、基本的な関数と同じです。

関数をマスターしていない方はこちらの記事が参考になります。

 

基本的な書き方

OrderClose関数の基本的な書き方は以下の通りです。

分かりやすいように、引数を省略しています。

bool orderClose = OrderClose( ①, ②, ③, ④, ⑤);

 

このように、返り値は bool型で、引数は5つあります。

まずは返り値から見ていきましょう。

 

返り値(戻り値)

OrderClose関数の返り値は bool型です。

true」または「false」が返ってきます。

数値にすると「1」または「0」です。

true 、false が返ってくる条件は以下の通りです。

  • true : 決済注文がFX会社に受理されたとき
  • false : 決済注文が失敗したとき

 

もし falseが返ってきた場合、ポジションは決済されていないので、再度 OrderClose関数を実行する必要があります。

ですが、99%以上は正常に受理されるので、そこまで気にする必要はありません。

もし決済に失敗していた場合は、手動で決済しましょう。

 

引数

OrderClose関数の引数は5つあります。

まずは、一覧でザッと見てみましょう。

番号データ型引数名内容
intticket決済するポジションのチケット番号
doublelots決済するロット数
doubleprice希望する決済価格
intslippageスリッページの許容量(単位0.1pips)
colorarrow_colorチャート上の決済情報の色を設定

 

それぞれ詳しく見ていきながら、一緒に作っていきましょう。

 

① ticket

ticket には、決済したいポジションのチケット番号を入力します。

チケット番号を直接入力しても良いのですが、OrderSelect関数でポジションを選択している場合、OrderTicket関数を使うことができます。

OrderTicket関数は、選択しているポジションのチケット番号を返す関数です。

チケット番号を覚えておく必要がなくなるため、簡単に書くことができます。

bool orderClose = OrderClose( OrderTicket(), ②, ③, ④, ⑤);

 

② lots

lots には、決済したいポジションのロット数を入力します。

こちらも OrderSelect関数でポジションを選択している場合、OrderLots関数という便利な関数が使えるようになりますので、OrderLots関数を利用すると良いでしょう。

OrderLots関数は、ポジションのロット数を返す関数です。

bool orderClose = OrderClose( OrderTicket(), OrderLots(), ③, ④, ⑤);

 

③ price

price には、決済する価格を入力します。

こちらも同様に、OrderSelect関数でポジションを選択している場合、OrderClosePrice関数が使えますので、OrderClosePrice関数を使いましょう。

OrderClosePrice関数は、現在の価格を返す関数です。

bool orderClose = OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), ④, ⑤);

 

④ slippage

slippage には、スリッページを入力します。

単位は0.1pipisです。

FXでは、希望する決済価格と、実際の決済価格がズレることがあります。

そのときに許容するズレ幅を入力してください。

ここでは、「10」を入力します。

bool orderClose = OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 10, ⑤);

 

⑤ arrow_color

arrow_color には、決済したときにチャート上に表示される矢印の色を設定します。

「矢印が表示されるのが邪魔」という方は、「clrNONE」と入力しましょう。

clrNONE にすることで、矢印が透明になり、チャート上に見えなくなります。

bool orderClose = OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 10, clrNONE);

 

OrderClose関数の具体的な使い方(サンプルあり)

ここまでは、OrderClose関数の基本的な書き方を解説しました。

ここからは、もっと具体的に OrderClose関数の使い方を見ていきましょう。

 

OrderClose関数は、事前にポジションを選択する必要があるため、OrderSelect関数と組み合わせて使われることが多いです。

例えば、以下のようなプログラムです。

//保有ポジションを一つずつチェックしていく
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
   //保有ポジションを一つ選択
   if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
   {
      //選択したポジションが、実行されている通貨ペアと同じかどうかチェック
      if(OrderSymbol() == Symbol())
      {
         //選択したポジションが、この自動売買のマジックナンバーと同じかチェック
         if(OrderMagicNumber() == magicNumber)
         {
            //ポジションを決済
            bool orderClose = OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 10, clrNONE);
         }
      }
   }
}

サンプルプログラムはこちら

 

OrderSelect関数以外にも、注文系の関数をたくさん使っています。

使っている関数の一覧は以下の通りです。

全て OrderClose関数を使うために必要な関数です。

  • OrdersTotal関数
  • OrderSelect関数
  • OrderSymbol関数
  • OrderMagicNumber関数
  • OrderTicket関数
  • OrderLots関数
  • OrderClosePrice関数

 

これらの関数は MT4に標準装備されているので、書くだけで使えます。

ちなみに上記のプログラムを実行すると、全てのポジションが決済されてしまうので、if文で適宜条件を付け加えてください。

 

実践的な応用プログラム例

ここからは、OrderClose関数を使った実践的な応用プログラム例を紹介します。

実際のEA開発でよく使われるパターンですので、ぜひ参考にしてください。

 

応用例①:指定pips以上の利益で利確する

最もよく使われるパターンの一つが、含み益が指定したpips数に達したら自動的に利確するプログラムです。

OrderOpenPrice関数でエントリー価格を取得し、現在の価格との差をpipsに換算して判定しています。

//+------------------------------------------------------------------+
//| 指定pips以上の含み益で自動利確するプログラム例                     |
//+------------------------------------------------------------------+

// 外部パラメータ:利確するpips数を設定
extern int    magicNumber    = 12345;
extern double TakeProfitPips = 30.0;  // 30pipsで利確

void OnTick()
{
   // 保有ポジションを後ろからループ(決済時のインデックスずれを防止)
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      // ポジションを選択
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;

      // 通貨ペアとマジックナンバーが一致するかチェック
      if(OrderSymbol() != Symbol()) continue;
      if(OrderMagicNumber() != magicNumber) continue;

      // 現在の含み益をpipsで計算する
      double profitPips = 0;

      if(OrderType() == OP_BUY)
      {
         // 買いポジションの場合:現在のBid価格 - エントリー価格
         profitPips = (Bid - OrderOpenPrice()) / Point / 10;
      }
      else if(OrderType() == OP_SELL)
      {
         // 売りポジションの場合:エントリー価格 - 現在のAsk価格
         profitPips = (OrderOpenPrice() - Ask) / Point / 10;
      }

      // 含み益が指定pips以上なら決済する
      if(profitPips >= TakeProfitPips)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, clrLime);

         // 決済結果をログに出力(デバッグ用)
         if(result)
            Print("利確成功! チケット:", OrderTicket(), " 利益pips:", profitPips);
         else
            Print("利確失敗… エラーコード:", GetLastError());
      }
   }
}

 

ポイントは、pipsの計算方法です。買いポジションと売りポジションで計算式が逆になるので注意しましょう。

また、Point は通貨ペアの最小価格変動を表す定数で、5桁のブローカーでは「0.00001」になるため、10で割ることでpips単位に変換しています。

 

応用例②:指定pips以上の損失で損切りする

利確の反対に、含み損が指定したpips数に達したら自動的に損切りするプログラムです。

ストップロスをサーバー側に設定しなくても、EA側で損切り制御ができるので便利です。

//+------------------------------------------------------------------+
//| 指定pips以上の含み損で自動損切りするプログラム例                   |
//+------------------------------------------------------------------+

extern int    magicNumber   = 12345;
extern double StopLossPips  = 20.0;  // 20pipsで損切り

void OnTick()
{
   // 保有ポジションを後ろからループ
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() != Symbol()) continue;
      if(OrderMagicNumber() != magicNumber) continue;

      // 含み損をpipsで計算する(マイナス値になる)
      double lossPips = 0;

      if(OrderType() == OP_BUY)
      {
         // 買いポジション:Bid - エントリー価格(含み損ならマイナス)
         lossPips = (Bid - OrderOpenPrice()) / Point / 10;
      }
      else if(OrderType() == OP_SELL)
      {
         // 売りポジション:エントリー価格 - Ask(含み損ならマイナス)
         lossPips = (OrderOpenPrice() - Ask) / Point / 10;
      }

      // 含み損が指定pips以上(マイナス方向)なら損切りする
      if(lossPips <= -StopLossPips)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, clrRed);

         if(result)
            Print("損切り実行! チケット:", OrderTicket(), " 損失pips:", lossPips);
         else
            Print("損切り失敗… エラーコード:", GetLastError());
      }
   }
}

 

ポイントは、損失の判定に「<= -StopLossPips」とマイナスを使っている点です。含み損はマイナスの値になるので、「指定pips以上のマイナスかどうか」で判定しています。

矢印の色を clrRed(赤)にしておくと、チャート上で損切りポイントが一目でわかるので便利です。

 

応用例③:移動平均線のクロスで決済する

テクニカル指標を使った決済条件も、EA開発では非常によく使われます。

ここでは、短期移動平均線と長期移動平均線のクロスをシグナルにして、ポジションを決済するプログラムを紹介します。

//+------------------------------------------------------------------+
//| 移動平均線のクロスで決済するプログラム例                           |
//+------------------------------------------------------------------+

extern int magicNumber = 12345;
extern int ShortMAPeriod = 5;    // 短期移動平均線の期間
extern int LongMAPeriod  = 25;   // 長期移動平均線の期間

void OnTick()
{
   // 現在の足の短期MA・長期MAを取得
   double shortMA_now  = iMA(Symbol(), 0, ShortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
   double longMA_now   = iMA(Symbol(), 0, LongMAPeriod,  0, MODE_SMA, PRICE_CLOSE, 0);

   // 1本前の足の短期MA・長期MAを取得(クロス判定に使用)
   double shortMA_prev = iMA(Symbol(), 0, ShortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
   double longMA_prev  = iMA(Symbol(), 0, LongMAPeriod,  0, MODE_SMA, PRICE_CLOSE, 1);

   // デッドクロス判定:短期MAが長期MAを上から下に抜けた
   bool deadCross  = (shortMA_prev > longMA_prev) && (shortMA_now <= longMA_now);

   // ゴールデンクロス判定:短期MAが長期MAを下から上に抜けた
   bool goldenCross = (shortMA_prev < longMA_prev) && (shortMA_now >= longMA_now);

   // 保有ポジションをチェック
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() != Symbol()) continue;
      if(OrderMagicNumber() != magicNumber) continue;

      // 買いポジションを持っていて、デッドクロスが発生したら決済
      if(OrderType() == OP_BUY && deadCross)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, clrYellow);
         if(result)
            Print("デッドクロスで買いポジション決済! チケット:", OrderTicket());
      }

      // 売りポジションを持っていて、ゴールデンクロスが発生したら決済
      if(OrderType() == OP_SELL && goldenCross)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, clrYellow);
         if(result)
            Print("ゴールデンクロスで売りポジション決済! チケット:", OrderTicket());
      }
   }
}

 

ポイントは、クロスの判定方法です。「1本前の足」と「現在の足」の移動平均線の位置関係を比較することで、クロスが発生した瞬間を検出しています。

買いポジションはデッドクロス(下落シグナル)で決済し、売りポジションはゴールデンクロス(上昇シグナル)で決済するのが基本的な考え方です。

 

OrderClose関数を使うときの注意点

最後に、OrderClose関数を使うときに注意すべきポイントをまとめます。

  • OrderSelect関数でポジションを事前に選択しておくこと(OrderTicket関数やOrderLots関数を使うため)
  • for文のループは後ろから回すこと(決済するとインデックスがずれるため)
  • 通貨ペアとマジックナンバーのチェックを忘れないこと(他のEAのポジションを決済してしまう恐れがあるため)
  • 決済の成功・失敗をログに出力すること(トラブル時の原因特定に役立つため)

 

これらのポイントを押さえておけば、OrderClose関数を安全に使いこなすことができます。

ぜひサンプルプログラムを参考にして、自分だけのオリジナルEAを作ってみてください!