【MQL5】OderSendで注文を出す時の準備について【まとめ】

mql5

MQL5の公式に説明がありますが読みづらいので、まとめておこうと思います。
というか関数にして、まとめちゃえばちょっと変更するだけで簡単にOderSendを使えるになるのでは?と思います。

スポンサーリンク

OderSend(request,result)について

マーケットに注文を出す時に使用します。

  • マーケットに注文を出すとは?
    1. 新規注文を出す。
    2. 注文内容の変更を出す。
    3. 保有中のポジションを決済する。


引数のrequestに事前にいろいろ設定してからOderSendで注文を出す。という流れになっています。ちなみに引数のresultについては注文結果が入って帰ってくるだけですので、構造体を渡すだけです。
また、OderSendの返り値は実行結果をBool型で返してきますので、条件分岐と一緒に使うと便利です。

使い方

OderSend(request,result);

上記のように使用しますが、こんな簡単ではないです笑
準備が大変です笑

引数requestの準備について

引数のrequestは構造体へのポインタです。(よくわからなくて大丈夫です。)
以下に一つづつ解説していきます。

requestの準備

MqlTradeRequest request;

これだけです。変数名は自由に変更してもらって大丈夫です。
これからこのrequestにいろいろ設定していきます。
※ この時にresultについても宣言しておくといいです。

MqlTradeRequest request; //取引リクエスト
MqlTradeResult  result; //リクエスト結果受取用

requestのメモリの解放

一回だけ注文だして終わるEAは存在しないと思うので、何回も注文出すと思います。
requestはなんども使うので、間違えて過去の情報が残らないように毎回初期化して、再設定した方がいいです。

ZeroMemory(request);
ZeroMemory(result); //合わせて記述するのがおすすめ

※resultについてもここでメモリの解放をしておくのがおすすめです。

requestに設定する値の一覧

これからrequestにいろいろ設定していきます。
まず、何を設定するかについて説明します。

設定内容変数の型変数名備考
取引の種類ENUM_TRADE_REQUEST_ACTIONSactionリンク先から選べる。
TRADE_ACTION_DEAL
が多いです。
EAのマジックナンバーulongmagicEA番号
注文チケットulongorder未決注文を変更時使用
※ポジション決済時未使用
取引通貨stringsymbol注文変更とポジション決済では不要
ロット数doublevolume
注文価格doubleprice成行注文時必要なし。
注文のストップリミットレベルdoublestoplimit注文が行われる価格
(注文成立とは違うので注意)
逆指値doubleslストップロス、損切を設定する場合
指値doubletp利確、出口を設定する場合
どれだけズレて決済OKかどうか
(成行注文の時)
ulongdeviationポイントで指定する。
注文の種類ENUM_ORDER_TYPEtypeリンク先から選べる。
注文実行の種類ENUM_ORDER_TYPE_FILLINGtype_fillingリンク先から選べる。
注文期限切れの種類ENUM_ORDER_TYPE_TIMEtype_timeリンク先から選べる。
注文期限切れの時刻datetimeexpiration
注文コメントstringcomment
ポジションチケットulongpositionポジションの決済や変更時使用
反対のポジションチケットulongposition_by

上記の設定をします。
必要なところだけを設定すればOKです。

設定要領は

request構造体.変数名 = 設定したい値

になります。

//冒頭で宣言した構造体requestを使用した場合(一例です)
request.action   =TRADE_ACTION_DEAL; //取引の種類
request.position =position_ticket; //決済したいポジションチケット
request.volume   =volume; //決済したいロット数
request.deviation=100; //許容誤差(ポイント)
request.magic    =EA_Magic; //EAのマジックナンバー

具体例1:買い注文(売り注文)

この例は下記の条件で注文を発注します。

  • 成行買い
  • ロット数0.1
  • ±0.5pipが許容値
  • EAのマジックナンバーは「123456」
#define EXPERT_MAGIC 123456   // プログラム冒頭で設定されていると仮定

//--- 買い注文と売り注文の切り分け
  bool BuyOrSell = True; //買い:True 売り:False

//--- リクエストと結果の宣言と初期化(冒頭で説明したやつ)
  MqlTradeRequest request;
  MqlTradeResult  result;

//--- リクエストのパラメータ(売りと買いの共通事項)
  request.action   =TRADE_ACTION_DEAL; // 取引操作タイプ
  request.symbol   =Symbol(); // シンボル
  request.volume   =0.1; // 0.1ロット
  request.deviation=5; // 価格からの許容偏差
  request.magic    =EXPERT_MAGIC; // 注文のMagicNumber

//--- 買い注文と売り注文の判断
  if(BuyOrSell){
    request.type     =ORDER_TYPE_BUY; // 注文タイプ
    request.price    =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // 発注価格
  }else{
    request.type     =ORDER_TYPE_SELL; // 注文タイプ
    request.price    =SymbolInfoDouble(Symbol(),SYMBOL_BID); // 発注価格
  }

//--- リクエストの送信
  if(!OrderSend(request,result))
    PrintFormat("OrderSend error %d",GetLastError());     // 失敗した場合、エラーコードを出力する

具体例2:ポジション決済(全部)

この例は下記の条件で決済します。

  • このEAが注文したポジションで保有しているものをすべて決済
  • PaymentOrderを呼び出すだけで実行される。
#define EXPERT_MAGIC 123456   // プログラム冒頭で設定されていると仮定
void PaymentOrder() {
   //--- 結果とリクエストの宣言
   MqlTradeRequest request;
   MqlTradeResult  result;
   int total=PositionsTotal(); // 保有ポジション数
   //--- 全ての保有ポジションの取捨
   for(int i=total-1; i>=0; i--) {
      //--- 注文のパラメータ
      ulong  position_ticket=PositionGetTicket(i);                                     // ポジションチケット
      string position_symbol=PositionGetString(POSITION_SYMBOL);                       // シンボル
      int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);             // 小数点以下の桁数
      ulong  magic=PositionGetInteger(POSITION_MAGIC);                                 // ポジションのMagicNumber
      double volume=PositionGetDouble(POSITION_VOLUME);                                 // ポジションボリューム
      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);   // ポジションタイプ

      //--- MagicNumberが一致している場合
      if(magic==EXPERT_MAGIC) {
         //--- リクエストと結果の値のゼロ化
         ZeroMemory(request);
         ZeroMemory(result);
         //--- 操作パラメータの設定
         request.action   =TRADE_ACTION_DEAL;       // 取引操作タイプ
         request.position =position_ticket;         // ポジションチケット
         //request.symbol   =position_symbol;         // シンボル
         request.volume   =volume;                   // ポジションボリューム
         request.deviation=100;                       // 価格からの許容偏差
         request.magic    =EA_Magic;             // ポジションのMagicNumber
         //--- ポジションタイプによる注文タイプと価格の設定
         if(type==POSITION_TYPE_BUY) { //買い注文の場合
            request.price=SymbolInfoDouble(position_symbol,SYMBOL_BID);
            request.type =ORDER_TYPE_SELL;
         } else { //売り注文の場合
            request.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK);
            request.type =ORDER_TYPE_BUY;
         }
         //--- 決済情報の出力
         PrintFormat("Close #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
         //--- リクエストの送信
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError()); // リクエストの送信に失敗した場合、エラーコードを出力
         //--- 操作情報
         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
         //---
      }
   }
}

まとめ

難しいことはしていないのですが、設定するものが多いので、めんどくさいですね笑
具体例2のように決済注文を出すのは関数化しておき、1文で呼び出せるようにすれば、可読性が高くなり、かつ、修正箇所が減るかな?と思います。
買い注文と売り注文を別々に記述するだけで変更があると2か所修正しないといけないですが、まとめて、条件分岐しておけば1箇所で修正できます。

参考にしてみてください。
わからないところは公式ドキュメントを読むか、下記のコメントに記載してもらえれば回答できる部分については回答します。

コメント

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