【超入門】MQL5 EA講座 第61回「MqlTradeResult構造体について」【EAの作り方】

MQL5でEA作ろう講座

前回は OrderSend関数とMqlTradeRequest構造体 について解説しました。

改めて前回の内容をおさらいをしておくと、

  • MQL4におけるOrderSend関数は、新規にポジションを持つための要求をトレードサーバーにするだけの機能しかなかったが、MQL5OrderSend関数は新規注文・SLTP修正、決済、注文削除等の要求を包括的に「注文」とみなし、トレードーサーバに送信する役割を担っている。

ということをお伝えしました。

今回は MqlTradeResult構造体 についてお話ししたいと思います。

スポンサーリンク
スポンサーリンク

MqlTradeResult構造体とは?→注文内容の結果を受け取るレシートの役割を果たす

MqlTradeResult構造体OrderSend関数の第2引数に設定するために使う、定義済み構造体です。

OrderSend関数が実際にトレードサーバーに送る内容をMqlTradeRequest構造体で、注文内容の詳細を設定する、ということは前回お話ししました。

MqlTradeResult構造体は、トレードサーバーに送られた注文内容の結果がどうなったのかを受け取る役割を担っています。

MqlTradeRequest構造体が注文伝票だとしたら、MqlTradeResult構造体はレシートや納品書にあたるものになります。↓のようなイメージを持ってもらうと良いでしょう。

MqlTradeResult構造体のメンバ構成

公式リファレンスによるMqlTradeResult構造体メンバ構成は以下のようになっています

メンバデータ型の中に、uintulongなどの見慣れないデータ型があるのをみて「これ何?( ゚Д゚)」と思った方は↓の記事をご覧ください

MQL5 EA講座 第11回補講「int以外の整数型」

struct MqlTradeResult 
  { 
   uint    retcode;         // 操作のリターンコード 
  ulong   deal;             // 実行された場合の 約定チケット 
  ulong   order;           // 注文された場合のチケット 
  double   volume;           // ブローカーによって確認された約定ボリューム 
  double   price;           // ブローカーによって確認された約定価格 
  double   bid;             // 現在の売値 
  double   ask;             // 現在の買値 
  string   comment;         // 操作に対するブローカーコメント(デフォルトは取引サーバの返したコードの記述) 
  uint    request_id;       // ディスパッチの際に、端末によって設定されたリクエストID  
   uint    retcode_external; // 外部取引システムのリターンコード 
 };

//出典:MQL5リファレンスより

MqlTradeRequest構造体で注文内容をセット

OrderSend関数でトレードサーバーに発注

その結果を上記のMqlTradeResult構造体メンバが格納することになります。

メンバにアクセスするには、例によってMqlTradeResult構造体インスタンスを生成します。

 MqlTradeRequest request;
   MqlTradeResult  result;

↑ これで、result.retcodeやresult.deal ・・・と言ったように必要なメンバを呼び出せば、発注した結果がどうなったのかを知ることができるという訳です。

もっとも、先ほどMqlTradeResult構造体を「レシートのようなもの」、と例えたように、あくまでMqlTradeRequest構造体OrderSend関数が行った処理の確認でしかない、という言い方もできなくはありません。(買い物でレシートを捨ててしまう人だって結構いますよね?)

従って、極端な話MqlTradeResult構造体メンバに格納されている値を使わずに、EAを作ることも表面上はできなくはありません。

しかしながら、発注が正しく行われたのかを確認しない、もし正しく行われなかったら「こういう処理を行う」という想定のないEA(エキスパートアドバイザー)は、脆弱すぎて使えないですよね?

もしシステムの堅牢姓が担保されていないのであれば、結局EA(エキスパートアドバイザー)の保守点検に日々気を配らなければいけなくなり、それでは裁量取引をやっているのとあまり変わらなくなってしまいます。

そんなわけで、MqlTradeResult構造体は注文が正しく行われたかどうかの確認と、正しく行われなかった場合の回路を組み込むために利用されることが多いです。

メンバ変数 .retcode には注文の成功/失敗(失敗理由)が格納される

メンバ変数 .retcode には注文の成功/失敗(失敗理由)が格納されます

.retcode は発注の成否が格納されているので、一番重要なメンバ変数と言えます。

公式リファレンスの注文結果定数値一覧を見ると、結構な数の定数値が用意されていますが、これを全部覚える必要はもちろんありません。(エラーが出てきたときに、その内容をリファレンスで調べられるようになっていればOKです)

覚えておくべきことは、

コード10008(TRADE_RETCODE_PLACED)と10009(TRADE_RETCODE_DONE)の場合は注文が成功。それ以外のコード値が格納されている場合、何らかの問題があった、ということです。

↑の前提をもとに、.retcode の値によってMT5EAが次はどのような処理を行うか?という記述をしていくことになります。

一番基本的な最初の動作は、注文が成功したのかどうかを何らかの形(MT5のエキスパートタブ、Email、スマホ用MT5へのノーティフィケーション等)で通知させることでしょう。

シンプルなコード例で言うと↓のような感じです。(公式リファレンスの買いポジション発注サンプルコードを拝借して少しいじったものです)

#define EXPERT_MAGIC 123456   // エキスパートアドバイザのMagicNumber


void OnStart()
  {
//--- 結果とリクエストの宣言

      //--- リクエストと結果の宣言と初期化
   MqlTradeRequest request={};
   MqlTradeResult  result={};
//--- リクエストのパラメータ
  request.action   =TRADE_ACTION_DEAL;                     // 取引操作タイプ
  request.symbol   =Symbol();                             // シンボル
  request.volume   =0.1234;                                   // 0.1ロットのボリューム
  request.type     =ORDER_TYPE_BUY;                       // 注文タイプ
  //request.price    =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // 発注価格
  request.deviation=5;                                     // 価格からの許容偏差
  request.magic    =EXPERT_MAGIC;                         // 注文のMagicNumber
  request.type_filling=ORDER_FILLING_IOC;
  
  OrderSend(request,result);

   
   if(result.retcode==TRADE_RETCODE_PLACED ||result.retcode==TRADE_RETCODE_DONE)
   {
      Print("注文が成功しました。 リターンコード= ",result.retcode);
   }
   
   else Print("注文が失敗しました。リターンコード= ",result.retcode);
 
    
    
  }
//+------------------------------------------------------------------+

↑のサンプルコードを実際にMQL5 Program FileにしてMT5デモ口座で実行してみます。↓

注文成功時は10009が、ロットを0.1234と不適切な値にして再コンパイル→再実行した時は、10014(無効なボリューム)というエラーが返ってきて、約定しなかったがのがわかります。

メンバ変数 .deal には約定番号(deal number)が格納される

メンバ変数 .deal には約定番号(deal number)が格納されます。

約定番号(deal number)とは?→注文が実行されたことを証明する番号

約定番号とは、注文が実行されたことを証明する番号です。

MqlTradeResult構造体のブログ記事でオーダー番号ポジション番号は解説しました。

ここで我々はMQL5には注文・約定・ポジションという3つの概念がある、という面妖な事実にぶち当たります。

オーダー番号=「注文」単位に割り振られる番号

ポジション番号=保有しているポジションに対して割り振られる番号

約定番号=注文が実行されたことを証明する番号

というのが一応の辞書的な説明になりますが、言葉遊びのようで全くピンときません(>_<)

要は1つの商品に3つの証明番号が付与されていて、行う処理によって使い分けなければいけない仕様に現状のMQL5ではなっている、という事です。

なにかの商品に関してコールセンターに問い合わせ時、問い合わせ番号的なものをオペレーターさんに訊かれて答えたら「その番号じゃありません(; ・`д・´)」と冷たくされた経験はないでしょうか?

例えば「ドル円145円1.0ロットBuy」という取引をしたとして、その取引に対する情報にアクセスしたい時に、(MQL4経験者の方は特に)オーダー番号さえ使えばいいと思いがちですが、MQL5ではそうもいかない訳です。

オーダー番号は「待機注文の修正」や、「待機注文の削除」などのポジションとして有効化していない注文に対する処理に使われます。

ポジション番号は、「ポジションの決済」「ポジションの注文内容変更」など、既にポジションとして有効化している取引に対する処理に使われます。

約定番号は主に、既にポジションの決済が終了した取引に対する処理に使われます。

↓の動画は、公式リファレンスにある成り行き買い注文のサンプルコードを拝借して、オーダー番号ポジション番号約定番号ログ出力させたものになります。

メンバ変数 .orderにはオーダー番号が格納される

メンバ変数 .orderにはオーダー番号が格納されます。

オーダー番号ポジション番号約定番号の違いに気を配らなくてはいけないのは.deal のところでも書いた通りです。

ただ、成行注文でポジションを持った場合はオーダー番号ポジション番号は同じ番号になります。

じゃあ、待機注文の時はどうなるのか?というと、ポジションが有効化していないうちはポジション番号は0になっています。ポジションが有効化した時点でオーダー番号に付与されていた番号がポジション番号に付与されます。

メンバ変数 .volumeには約定したボリューム(約定ロット)が格納される

メンバ変数 .volumeには約定したボリューム(約定ロット)が格納されます。設定したボリューム(ロット)に対して、約定ボリューム(約定ロット)がどのような結果になるかは設定しているフィルポリシーによっても変わってきます。

フィルポリシーについては→コチラ

メンバ変数 .price には約定価格が格納される

メンバ変数 .price には約定価格が格納されます。

成行注文時に、最終的な約定価格がどのような結果になるのかは、執行方式MqlTradeRequest構造体メンバ変数 .deviationによっても変わってきます。

執行方式について詳しくは→コチラ

メンバ変数 .bid には 現在のマーケット売値(Bid値)が格納される

メンバ変数 .bid には 現在のマーケット売値(Bid値)が格納されます。

メンバ変数 .ask には 現在のマーケット買値(Ask値)が格納される

メンバ変数 .ask には 現在のマーケット買値(Ask値)が格納されます。

メンバ変数 .comment には 操作に対するブローカーコメントが格納される

メンバ変数 .comment には 操作に対するブローカーのコメントが格納されます。

MqlTradeRequest構造体. におけるメンバ変数 .commentに格納されているのが我々エンドユーザーが設定したコメントであるのに対し、

MqlTradeResult構造体におけるメンバ変数 .commentはあくまでもブローカー側のコメントなので違いに注意しましょう。

※あまりブローカのコメントにアクセスすること自体がないかもしれませんが・・・。

一応動画を載せておきます。成行注文が成立した後、MqlTradeRequest構造体. におけるメンバ変数 .comment と MqlTradeResult構造体におけるメンバ変数 .commentを両方ログ出力させたものです。↓

メンバ変数 .request_idにはリクエストIDが格納される

メンバ変数 .request_idには、送信時に端末によって設定されたリクエストIDが格納されます。

リクエストIDはMT5がトレードリクエストを識別するために使用する内部番号です。

実際に、MT5を使用して取引指令を出す際(例えば新しいオーダーを開く、既存のオーダーを変更する、ポジションを閉じるなど)、そのリクエストをサーバーに送信します。

各リクエストは、システム内で処理を追跡しやすくするために、一意(同じものが存在しない)のリクエストIDが割り当てられます。

このIDを使って、サーバーがどのリクエストを処理しているか、特定の注文や取引が成功したかどうか、そしてその他の取引結果を照会することができます。

メンバ変数 .retcode_externalには 外部取引システムのリターンコードが格納される

メンバ変数 .retcode_externalには 外部取引システムのリターンコードが格納されます。

.retcodeMT5内の処理で発生したリターンコードを示すのに対し、.retcode_externalはMT5の外部、つまりブローカーの取引システムで発生したエラーを示します。

これらの識別子を利用することで、トレードリクエストがどのレベルでエラーに遭遇したのか(MT5内部か、それとも外部システムか)、そしてそのエラーの具体的な理由は何だったのかを理解することが可能になります。

まとめ

今回は MqlTradeResult構造体 について解説しました。

今回の記事では以下のことを学びました。

  • MqlTradeResult構造体は、トレードサーバーに送られた注文内容の結果がどうなったのかを受け取る役割を担っている。
  • MqlTradeResult構造体は注文が正しく行われたかどうかの確認と、正しく行われなかった場合の回路を組み込むために主に利用される。
  • メンバ変数 .retcode には注文の成功/失敗(失敗理由)が格納される。
  • メンバ変数 .retcode に格納されている値が、コード10008(TRADE_RETCODE_PLACED)と10009(TRADE_RETCODE_DONE)の場合は注文が成功。それ以外のコード値が格納されている場合、何らかの問題があったことを示す。

今回は以上になります。

最後までお読みいただきありがとうございました<m(__)m>

【超入門】MQL5 EA講座 第60回「OrderSend関数とMqlTradeRequest構造体」

 →【超入門】MQL5 EA講座 第62回「実際に注文を出すコードを書いてみる」【EAの作り方】

コメント

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