前回は OrderSend関数とMqlTradeRequest構造体 について解説しました。
改めて前回の内容をおさらいをしておくと、
- MQL5でEAを作るにあたり、注文を出すには、OrderSend関数を使う。
- MQL4におけるOrderSend関数は、新規にポジションを持つための要求をトレードサーバーにするだけの機能しかなかったが、MQL5のOrderSend関数は新規注文・SLTP修正、決済、注文削除等の要求を包括的に「注文」とみなし、トレードーサーバに送信する役割を担っている。
- MQL5のOrderSend関数の第1引数にはMqlTradeRequest構造体、第2引数にはMqlTradeResult構造体を引数に指定する。
- MqlTradeRequest構造体は、MQL4サーバーへの要求内容を調整・決定しその内容をOrderSend関数に受け渡す役割を担っている。
ということをお伝えしました。
今回は MqlTradeResult構造体 についてお話ししたいと思います。
- MqlTradeResult構造体とは?→注文内容の結果を受け取るレシートの役割を果たす
- MqlTradeResult構造体のメンバ構成
- メンバ変数 .retcode には注文の成功/失敗(失敗理由)が格納される
- メンバ変数 .deal には約定番号(deal number)が格納される
- メンバ変数 .orderにはオーダー番号が格納される
- メンバ変数 .volumeには約定したボリューム(約定ロット)が格納される
- メンバ変数 .price には約定価格が格納される
- メンバ変数 .bid には 現在のマーケット売値(Bid値)が格納される
- メンバ変数 .ask には 現在のマーケット買値(Ask値)が格納される
- メンバ変数 .comment には 操作に対するブローカーコメントが格納される
- メンバ変数 .request_idにはリクエストIDが格納される
- メンバ変数 .retcode_externalには 外部取引システムのリターンコードが格納される
- まとめ
MqlTradeResult構造体とは?→注文内容の結果を受け取るレシートの役割を果たす
MqlTradeResult構造体はOrderSend関数の第2引数に設定するために使う、定義済み構造体です。
OrderSend関数が実際にトレードサーバーに送る内容をMqlTradeRequest構造体で、注文内容の詳細を設定する、ということは前回お話ししました。
MqlTradeResult構造体は、トレードサーバーに送られた注文内容の結果がどうなったのかを受け取る役割を担っています。
MqlTradeRequest構造体が注文伝票だとしたら、MqlTradeResult構造体はレシートや納品書にあたるものになります。↓のようなイメージを持ってもらうと良いでしょう。
MqlTradeResult構造体のメンバ構成
公式リファレンスによるMqlTradeResult構造体のメンバ構成は以下のようになっています
※メンバのデータ型の中に、uint やulongなどの見慣れないデータ型があるのをみて「これ何?( ゚Д゚)」と思った方は↓の記事をご覧ください
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 の値によってMT5用EAが次はどのような処理を行うか?という記述をしていくことになります。
一番基本的な最初の動作は、注文が成功したのかどうかを何らかの形(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にはオーダー番号が格納される
オーダー番号、ポジション番号、約定番号の違いに気を配らなくてはいけないのは.deal のところでも書いた通りです。
ただ、成行注文でポジションを持った場合はオーダー番号とポジション番号は同じ番号になります。
じゃあ、待機注文の時はどうなるのか?というと、ポジションが有効化していないうちはポジション番号は0になっています。ポジションが有効化した時点でオーダー番号に付与されていた番号がポジション番号に付与されます。
メンバ変数 .volumeには約定したボリューム(約定ロット)が格納される
メンバ変数 .volumeには約定したボリューム(約定ロット)が格納されます。設定したボリューム(ロット)に対して、約定ボリューム(約定ロット)がどのような結果になるかは設定しているフィルポリシーによっても変わってきます。
メンバ変数 .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には 外部取引システムのリターンコードが格納されます。
.retcodeはMT5内の処理で発生したリターンコードを示すのに対し、.retcode_externalはMT5の外部、つまりブローカーの取引システムで発生したエラーを示します。
これらの識別子を利用することで、トレードリクエストがどのレベルでエラーに遭遇したのか(MT5内部か、それとも外部システムか)、そしてそのエラーの具体的な理由は何だったのかを理解することが可能になります。
まとめ
今回は MqlTradeResult構造体 について解説しました。
今回の記事では以下のことを学びました。
- MqlTradeResult構造体は、トレードサーバーに送られた注文内容の結果がどうなったのかを受け取る役割を担っている。
- MqlTradeResult構造体は注文が正しく行われたかどうかの確認と、正しく行われなかった場合の回路を組み込むために主に利用される。
- メンバ変数 .retcode には注文の成功/失敗(失敗理由)が格納される。
- メンバ変数 .retcode に格納されている値が、コード10008(TRADE_RETCODE_PLACED)と10009(TRADE_RETCODE_DONE)の場合は注文が成功。それ以外のコード値が格納されている場合、何らかの問題があったことを示す。
今回は以上になります。
最後までお読みいただきありがとうございました<m(__)m>
コメント