English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5 クックブック:トレードトランザクションイベントの処理

MQL5 クックブック:トレードトランザクションイベントの処理

MetaTrader 5 | 24 12月 2015, 14:52
819 0
Denis Kirichenko
Denis Kirichenko

はじめに

本稿では MQL5 の手段を利用してトレードイベントを管理する方法の一つを提案したいと思います。すでにこのテーマについて述べた記事が数点あることを述べておく必要があると思います。"Processing of trade events in Expert Advisor using the OnTrade() function" はそのうちの一つです。私は他の著者の言うことを繰り返す気はありません。また私は別のハンドラ-OnTradeTransaction()を利用するつもりです。

読者のみなさんには以下のポイントに関心を示していただきたいと思います。現在の MQL5 言語は正式にクライアントターミナルの 14 のイベントハンドラを対象とします。また、プログラマーはEventChartCustom() を用いてカスタムイベントを作成し、OnChartEvent()でそれらを処理することができます。ただし「イベント駆動型プログラミング」(EDP)という言葉はドキュメンテーションでは全く使用されていません。MQL5 のプログラムがどれも EDP 原則にのっとって作成されている事実を踏まえると、それはおかしなことです。たとえば、ユーザーはどんな Expert Advisor でもテンプレートにある「エキスパート用イベントハンドラ」のステップで選択をすることになります。

イベント駆動型プログラミングのメカニズムがいずれにせよ MQL5 で使用されているのは明らかです。この言語には2部で構成されるプログラムブロックがあります。:イベントの選択と処理です。その上、クライアントターミナルのイベントについて語るなら、プログラマーは後者のみ制御します。すなわちイベントハンドラです。公正を期すために申し上げると、イベントによっては例外もあります。タイマーとカスタムイベントはその例外に入ります。こういったイベントの制御は完全にプログラマーに委ねられています。


1. トレードトランザクションイベント

トピックに深く入っていく前に公式情報を参照します。

ドキュメンテーションによると、トレードトランザクションイベントはトレードアカウントの特定処理の結果である。処理それ自体はトランザクションが決定する数多くの段階で構成されています。たとえば、マーケットオーダーでポジションをオープンするというトレードアカウントでのもっともよくおこなわれる処理の一つは次のような段階において実装されます。

  1. トレードリクエストを作成する
  2. トレードリクエストを検証する
  3. サーバーにトレードリクエストを送信する
  4. サーバーでトレードオーダー実行に関する応答を受信する

このシーケンスはコードの文字列に反映されるターミナル-サーバーのペア作業のロジックを示しているだけです。トレードトランザクショントレードイベントの観点からは、マーケットにおけるポジションオープンは以下のように起こります。

  1. MQL5 プログラムが完了したリクエストの結果についてサーバーから通知を受ける。
  2. ユニークチケットを持つオーダーの形式のリクエストはオープンオーダーのリストにインクルードされる。
  3. オーダーは実行後オープンオーダーのリストから削除される。
  4. それからそのオーダーはアカウント履歴に入る。
  5. アカウント履歴はオーダー実行結果のディールに関するデータも持ちます。

よってポジションをオープンするにはOnTradeTransaction() ハンドラを5回呼ぶ必要があります。

プログラムコード詳細については少しあとでお話します。ここでは関数のヘッダを詳しく見ていきます。パラメータは3つです。

void  OnTradeTransaction(
   const MqlTradeTransaction&    trans,        // structure of the trade transaction
   const MqlTradeRequest&        request,      // structure of the request
   const MqlTradeResult&         result        // structure of the response
   );

これらパラメータについてはドキュメンテーションに詳細が述べられています。トレードトランザクションのストラクチャのパラメータは現在呼び出し中にハンドラが受け取る情報のある種のキャストであることをお伝えしておきたいと思います。

またトレードトランザクションのタイプについても少しお話ししておく必要があります。それには頻繁に出くわすためです。

MQL5 では ENUM_TRADE_TRANSACTION_TYPE はトレードトランザクションのタイプに関連する特殊な列挙です。あるトレードトランザクションがどのタイプに属するか見つけるには、MqlTradeTransactionタイプのパラメータ定数を参照する必要があります。

struct MqlTradeTransaction
  {
   ulong                         deal;             // Ticket of the deal
   ulong                         order;            // Ticket of the order
   string                        symbol;           // Trade symbol
   ENUM_TRADE_TRANSACTION_TYPE   type;             // Type of the trade transaction
   ENUM_ORDER_TYPE               order_type;       // Type of the order
   ENUM_ORDER_STATE              order_state;      // Status of the order
   ENUM_DEAL_TYPE                deal_type;        // Type of the deal
   ENUM_ORDER_TYPE_TIME          time_type;        // Order expiration type
   datetime                      time_expiration;  // Order expiration time
   double                        price;            // Price 
   double                        price_trigger;    // Price that triggers the Stop Limit order
   double                        price_sl;         // Level of Stop Loss
   double                        price_tp;         // Level of Take Profit
   double                        volume;           // Volume in lots
  };

ストラクチャの4番目のフィールドはまさにわれわれが探している列挙です。


2. ポジションの処理

事実上、ポジション処理に関するトレード処理はすべてOnTradeTransaction() ハンドラを5回呼び出しを行います。それらは以下です。

  • ポジションのオープン
  • ポジション
  • ポジション反転
  • ポジションへのロット追加
  • ポジションの部分クローズ

ポジション変更は TradeTransaction イベントハンドラを2度呼ぶ唯一のトレード処理です。

特定のトレード処理に対してどのトランザクションタイプが関わっているのかという情報はまったくないため、試行錯誤でそれを見つけていきます。

その前にTradeTransaction イベントハンドラを持つエキスパートのテンプレートを作成する必要があります。私は自分バージョンのテンプレートをTradeProcessor.mq5と名づけました。そしてログのストラクチャフィールドの値に情報を表示できる機能を追加しました。これら値はイベントハンドラのパラメータです。こういったレコードを分析することは時間がかかりますが、最終的にはイベントの全体像を提供することでつじつまがあいます。

MetaTrader 5 ターミナルの任意のチャートでデバッグモードでエキスパートを起動する必要があります。

ポジションをマニュアルでオープンし、そのコードを見ます。最初のハンドラ呼び出しは次のようなものです(図1)。

図1 タイプフィールド TRADE_TRANSACTION_REQUEST

図1 タイプフィールド TRADE_TRANSACTION_REQUEST

ログに以下のエントリが表示されます。

IO      0       17:37:53.233    TradeProcessor (EURUSD,H1)      ---===Transaction===---
NK      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
RR      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
DE      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Ticket of the order: 0
JS      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_STARTED
JN      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY
FD      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Price: 0.0000
FN      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
HF      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
FQ      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
RR      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Trade symbol: 
HD      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
GS      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
DN      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Type of the trade transaction TRADE_TRANSACTION_REQUEST
FK      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Volume in lots: 0.00

このブロックではトランザクションタイプに関するレコードのみが関心事です。にてのとおり、このタイプは(TRADE_TRANSACTION_REQUEST)リクエストに属します。

リクエスト詳細についての情報はブロック "Request(リクエスト)"で取得可能です。

QG      0       17:37:53.233    TradeProcessor (EURUSD,H1)      ---===Request===---
HL      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Type of the trade operation: TRADE_ACTION_DEAL
EE      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Comment to the order: 
JP      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Deviation from the requested price: 0
GS      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Order expiration time: 1970.01.01 00:00
LF      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Magic number of the EA: 0
FM      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535869
EJ      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Price: 1.3137
QR      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Stop Loss level of the order: 0.0000
IJ      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Take Profit level of the order: 0.0000
KK      0       17:37:53.233    TradeProcessor (EURUSD,H1)      StopLimit level of the order: 0.0000
FS      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Trade symbol: EURUSD
RD      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY

リクエスト実行結果に関するデータはブロック "Response(レスポンス)"に行きます。

KG      0       17:37:53.233    TradeProcessor (EURUSD,H1)      ---===Response===---
JR      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Code of the operation result: 10009
GD      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Ticket of the deal: 15258202
NR      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535869
EF      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Volume of the deal: 0.11
MN      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Price of the deal: 1.3137
HJ      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Bid: 1.3135
PM      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Ask: 1.3137
OG      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Comment to the operation: 
RQ      0       17:37:53.233    TradeProcessor (EURUSD,H1)      Request ID: 1

リクエストとリスポンスのようなハンドラのその他のパラメータを分析すると、最初の呼び出しでのリクエストに関する追加情報を取得することができます。

2番目の呼び出しはオープンオーダーリストへオーダーを追加することに関連しています(図2)。

図2 タイプフィールド TRADE_TRANSACTION_ORDER_ADD

図2 タイプフィールド TRADE_TRANSACTION_ORDER_ADD

ブロック"Transaction(トランザクション)" はログでわれわれが唯一必要とするものです。

MJ      0       17:41:12.280    TradeProcessor (EURUSD,H1)      ---===Transaction===---
JN      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
FG      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
LM      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535869
LI      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_STARTED
LP      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY
QN      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Price: 1.3137
PD      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
NL      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
PG      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
DL      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Trade symbol: EURUSD
JK      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
QD      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
IQ      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_ORDER_ADD
PL      0       17:41:12.280    TradeProcessor (EURUSD,H1)      Volume in lots: 0.11

見てのとおり、オーダーはすでにそのチケットとその他パラメータ(シンボル、価格、ボリューム)を受け取り、オープンオーダーのリストにインクルードされています。

3番目のイベントハンドラ呼び出しはオープンオーダーのリストからオーダーを削除することに関連しています(図3)。

図3 タイプフィールド TRADE_TRANSACTION_ORDER_DELETE

図3 タイプフィールド TRADE_TRANSACTION_ORDER_DELETE

ブロック"Transaction(トランザクション)" はログでわれわれが唯一必要とするものです。

PF      0       17:52:36.722    TradeProcessor (EURUSD,H1)      ---===Transaction===---
OE      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
KL      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
EH      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535869
QM      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_STARTED
QK      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY
HS      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Price: 1.3137
MH      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
OP      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
EJ      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
IH      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Trade symbol: EURUSD
KP      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
LO      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
HG      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_ORDER_DELETE
CG      0       17:52:36.722    TradeProcessor (EURUSD,H1)      Volume in lots: 0.11

このブロックにはトランザクションタイプ以外に新しい情報はありません。

履歴に新しい履歴オーダーが入るとハンドラは4度目の呼び出しを受けます(図4)。

図4 タイプフィールド TRADE_TRANSACTION_HISTORY_ADD

図4 タイプフィールド TRADE_TRANSACTION_HISTORY_ADD

関連情報はブロック "Transaction" から取得します。

QO      0       17:57:32.234    TradeProcessor (EURUSD,H1)      ---===Transaction==---
RJ      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
NS      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
DQ      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535869
EH      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_FILLED
RL      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY
KJ      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Price: 1.3137
NO      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
PI      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
FS      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
JS      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Trade symbol: EURUSD
LG      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
KP      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
OL      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_HISTORY_ADD
JH      0       17:57:32.234    TradeProcessor (EURUSD,H1)      Volume in lots: 0.00

この段階では、オーダーは実行ずみなのが判ります。

そしてディールが履歴に追加されるとき、最後の呼び出し(5回目)が行われます(図5)。

図5 タイプフィールド TRADE_TRANSACTION_DEAL_ADD

図5 タイプフィールド TRADE_TRANSACTION_DEAL_ADD

ログでは再びわれわれの関心はブロック"Transaction"だけです。

OE      0       17:59:40.718    TradeProcessor (EURUSD,H1)      ---===Transaction===---
MS      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Ticket of the deal: 15258202
RJ      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
HN      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535869
LK      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_STARTED
LE      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY
MM      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Price: 1.3137
PF      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
NN      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
PI      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
DJ      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Trade symbol: EURUSD
JM      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
QI      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
CK      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_DEAL_ADD
RQ      0       17:59:40.718    TradeProcessor (EURUSD,H1)      Volume in lots: 0.11

このブロックの重要な文字列はディールのティックです。

トランザクションのスキームを提供しようと思います。ポジションに対してスキームは2とおりしかありません。最初のスキームは図6のようなものです。

図6 トランザクションプロセスの第1スキーム

図6 トランザクションプロセスの第1スキーム

ポジション処理に関連するトレード処理はすべてこのスキームに従って行われます。ここでの唯一の例外はポジション変更処理です。最後の処理には以下の2つの処理があります(図7)。

図7 トランザクションプロセスの第2スキーム

図7 トランザクションプロセスの第2スキーム

ポジションの変更はディールとオーダーの履歴では追跡できません。

まさにポジションがすべてなのです。


3. 未決注文の処理

未決注文に関しては、トランザクションはより少ないことに留意します。同時にオーダーを処理する場合にはより多くのトランザクションタイプの組合せがあります。

オーダー変更のためには、ポジション変更同様、ハンドラは2度呼ばれます。発注とオーダー削除には呼び出しは3度行われます。オーダー削除または実行時にはトレードトランザクションイベントは4度発生します。

ここで未決注文を出します。ふたたびMetaTrader 5 ターミナルの任意のチャートでエキスパートをデバッグモードで起動する必要があります。

最初のハンドラ呼び出しはリクエストと連結します(図8)。

図8 タイプフィールド TRADE_TRANSACTION_REQUEST

図8 タイプフィールド TRADE_TRANSACTION_REQUEST

ログには以下のエントリがあります。

IO      0       18:13:33.195    TradeProcessor (EURUSD,H1)      ---===Transaction===---
NK      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
RR      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
DE      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Ticket of the order: 0
JS      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_STARTED
JN      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY
FD      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Price: 0.0000
FN      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
HF      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
FQ      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
RR      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Trade symbol: 
HD      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
GS      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
DN      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_REQUEST
FK      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Volume in lots: 0.00
NS      0       18:13:33.195    TradeProcessor (EURUSD,H1)      

QG      0       18:13:33.195    TradeProcessor (EURUSD,H1)      ---===Request==---
IQ      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Type of the trade operation: TRADE_ACTION_PENDING
OE      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Order comment: 
PQ      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Deviation from the requested price: 0
QS      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Order expiration time: 1970.01.01 00:00
FI      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Magic number of the EA: 0
CM      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535983
PK      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Price: 1.6500
KR      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Stop Loss level of the order: 0.0000
OI      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Take Profit level of the order: 0.0000
QK      0       18:13:33.195    TradeProcessor (EURUSD,H1)      StopLimit level of the order: 0.0000
QQ      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Trade symbol: GBPUSD
RD      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY_LIMIT
LS      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Order execution type: ORDER_FILLING_RETURN
MN      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
IK      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Volume in lots: 0.14
NS      0       18:13:33.195    TradeProcessor (EURUSD,H1)      
CD      0       18:13:33.195    TradeProcessor (EURUSD,H1)      ---===Response===---
RQ      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Code of the operation result: 10009
JI      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
GM      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535983
LF      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Volume of the deal: 0.14
JN      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Price of the deal: 0.0000
MK      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Bid: 0.0000
CM      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Ask: 0.0000
IG      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Comment to the operation: 
DQ      0       18:13:33.195    TradeProcessor (EURUSD,H1)      Request ID: 1

2番目のハンドラ呼び出しはオープンオーダーリストへオーダーを追加します(図9)。

図9 タイプフィールド TRADE_TRANSACTION_ORDER_ADDED

図9 タイプフィールド TRADE_TRANSACTION_ORDER_ADDED

ログではわれわれの関心は"Transaction" ブロックだけです。

HJ      0       18:17:02.886    TradeProcessor (EURUSD,H1)      ---===Transaction===---
GQ      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
CH      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
RL      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535983
II      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_STARTED
OG      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY_LIMIT
GL      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Price: 1.6500
IE      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
CO      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
IF      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
PL      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Trade symbol: GBPUSD
OL      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
HJ      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
LF      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_ORDER_ADD
FR      0       18:17:02.886    TradeProcessor (EURUSD,H1)      Volume in lots: 0.14

3番目のイベントハンドラ呼び出しは出されたオーダーに従いデータを更新します(図10)。

特にオーダーステータスは値 ORDER_STATE_PLACED を受け取ります。

図10 タイプフィールド TRADE_TRANSACTION_ORDER_UPDATE

図10 タイプフィールド TRADE_TRANSACTION_ORDER_UPDATE

ログではわれわれは"Transaction" に対するレコードを確認する必要があります。

HS      0       18:21:27.004    TradeProcessor (EURUSD,H1)      ---===Transaction==---
GF      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Ticket of the deal: 0
CO      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Type of the deal: DEAL_TYPE_BUY
RE      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Ticket of the order: 22535983
KM      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Status of the order: ORDER_STATE_PLACED
QH      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Type of the order: ORDER_TYPE_BUY_LIMIT
EG      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Price: 1.6500
GL      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Level of Stop Loss: 0.0000
ED      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Level of Take Profit: 0.0000
GO      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Price that triggers the Stop Limit order: 0.0000
RE      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Trade symbol: GBPUSD
QS      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Pending order expiration time: 1970.01.01 00:00
JS      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
RD      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_ORDER_UPDATE
JK      0       18:21:27.004    TradeProcessor (EURUSD,H1)      Volume in lots: 0.14

このブロックの重要な文字列はオーダー状態です。

ポジション処理とは異なり、未決注文の処理はスキームによって実装されません。未決注文に関連するトレード処理はすべてトレードトランザクションタイプの観点からはユニークです。

未決注文出しはトランザクションを3個取ります(図11)。

図11 トランザクション-未決注文出しの処理

図11 トランザクション-未決注文出しの処理

未決注文の変更はトランザクションを2つ生成します(図12)。

図12 トランザクション-未決注文変更処理

図12 トランザクション-未決注文変更処理

未決注文が削除される場合、OnTradeTransaction() ハンドラが4回呼ばれます(図13)。

図13 トランザクション-未決注文削除処理

図13 トランザクション-未決注文削除処理

未決注文の削除は次のスキームによって決定されます(図14)。

図14 トランザクション-未決注文削除処理

図14 トランザクション-未決注文削除処理

未決注文が実行されると最終トレード処理が件の異なるトランザクションを引き起こします(図15)。

図15 トランザクション-未決注文アクティブ化処理

図15 トランザクション-未決注文アクティブ化処理

トランザクションの組合せすべてについて長いエントリを表示するつもりはありません。そうしたいと思われる読者の方はコードを実行してエントリを調査することができます。


4. 汎用ハンドラ

エンドユーザーの目で トレードトランザクション イベントを処理するプログラムを見てみます。エンドユーザーはオーダー、ポジション双方と問題なく動作するプログラムを必要とするようです。プログラマーはOnTradeTransaction() に対しをそれが何を処理するにしてもすべてのトランザクションとその組合せを特定するようにコードを作成する必要があります。理想的には、そのプログラムは一連のトランザクション完了時にどの処理が実行されたか示すことができることです。

以下の例ではトランザクションの連続した処理がされています。ですが、MQL5 の開発者は次のように語ります。

ターミナルからまたは関数 OrderSend()/OrderSendAsync() によってマニュアルで送信されるトレードリクエストはトレードサーバー上に複数の連続したトランザクションを生成します。ターミナルに到着するこれらトランザクションの優先順位は保証されません。そのためトレーディングアルゴリズムは、トランザクショングループが次々と到着するという推定に基づくべきではありません 。そればかりか、トランザクションはサーバーからターミナルへ伝達される途中で失われる可能性があります。

理想に近い形で動作するプログラムを書く必要があれば、提案例を改善し、オーダー到着のトランザクション処理を独立させます。

一般的に、ポジションとオーダーはトランザクションの共通タイプです。トランザクションには11タイプあります。その中の4タイプだけがターミナルからのトレードに関連しています。

  • TRADE_TRANSACTION_DEAL_UPDATE;
  • TRADE_TRANSACTION_DEAL_DELETE;
  • TRADE_TRANSACTION_HISTORY_UPDATE;
  • TRADE_TRANSACTION_HISTORY_DELETE.

本稿ではそれについてはお話しません。開発者によれば、これらタイプはトレードサーバー側での機能性を拡張するために作られているとのことです。私はこれまでそういったタイプを処理したことはありませんでした。

ということで、OnTradeTransaction() でもっとも頻繁に処理されるフル機能タイプが11残されています。

ハンドラ本文の現トランザクションタイプを決定するセグメントは重要な役割を果たします。

//--- ========== Types of transaction [START]
   switch(trans_type)
     {
      //--- 1) if it is a request
      case TRADE_TRANSACTION_REQUEST:
        {

         //---
         break;
        }
      //--- 2) if it is an addition of a new open order
      case TRADE_TRANSACTION_ORDER_ADD:
        {

         //---
         break;
        }
      //--- 3) if it is a deletion of an order from the list of open ones
      case TRADE_TRANSACTION_ORDER_DELETE:
        {

         //---     
         break;
        }
      //--- 4) if it is an addition of a new order to the history
      case TRADE_TRANSACTION_HISTORY_ADD:
        {

         //---     
         break;
        }
      //--- 5) if it is an addition of a deal to history
      case TRADE_TRANSACTION_DEAL_ADD:
        {

         //---
         break;
        }
      //--- 6) if it is a modification of a position 
      case TRADE_TRANSACTION_POSITION:
        {

         //---
         break;
        }
      //--- 7) if it is a modification of an open order
      case TRADE_TRANSACTION_ORDER_UPDATE:
        {

         //---
         break;
        }
     }
//--- ========== Types of transactions [END]

現トランザクションタイプによってどのトレード処理を行うのか決定してみます。何を処理するか-ポジションかオーダーか、見つけるためには、リクエストを処理するケースモジュールにトレード処理タイプを記憶してもらいます。

以下がモジュールそのものです。

//--- 1) if it is a request
      case TRADE_TRANSACTION_REQUEST:
        {
         //---
         last_action=request.action;
         string action_str;

         //--- what is the request for?
         switch(last_action)
           {
            //--- а) on market
            case TRADE_ACTION_DEAL:
              {
               action_str="place a market order";
               trade_obj=TRADE_OBJ_POSITION;
               break;
              }
            //--- б) place a pending order
            case TRADE_ACTION_PENDING:
              {
               action_str="place a pending order";
               trade_obj=TRADE_OBJ_ORDER;
               break;
              }
            //--- в) modify position
            case TRADE_ACTION_SLTP:
              {
               trade_obj=TRADE_OBJ_POSITION;
               //---
               StringConcatenate(action_str,request.symbol,": modify the levels of Stop Loss",
                                 " and Take Profit");

               //---
               break;
              }
            //--- г) modify order
            case TRADE_ACTION_MODIFY:
              {
               action_str="modify parameters of the pending order";
               trade_obj=TRADE_OBJ_ORDER;
               break;
              }
            //--- д) delete order
            case TRADE_ACTION_REMOVE:
              {
               action_str="delete pending order";
               trade_obj=TRADE_OBJ_ORDER;
               break;
              }
           }
         //---
         if(InpIsLogging)
            Print("Request received: "+action_str);

         //---
         break;
        }

この場合変数を数個変更するのは難しいことではありません。

static ENUM_TRADE_REQUEST_ACTIONS last_action; // market operation at the first pass

last_action 変数はイベントハンドラがそもそも起動した理由を記憶します。

static ENUM_TRADE_OBJ trade_obj;               // specifies the trade object at the first pass

variable trade_obj は何が処理されたか-ポジションかオーダーか、をメモリに保持します。そのために列挙 ENUM_TRADE_OBJ を作成します。

最後にTRADE_TRANSACTION_ORDER_ADD タイプのトランザクションを処理するモジュールに進みたいと思います。

//--- 2) if it is an addition of a new open order
      case TRADE_TRANSACTION_ORDER_ADD:
        {
         if(InpIsLogging)
           {
            if(trade_obj==TRADE_OBJ_POSITION)
               Print("Open a new market order: "+
                     EnumToString(trans.order_type));
            //---
            else if(trade_obj==TRADE_OBJ_ORDER)
               Print("Place a new pending order: "+
                     EnumToString(trans.order_type));
           }
         //---
         break;
        }

このモジュールはひじょうにシンプルです。ポジションは最初のステップで処理されているため、長いエントリ『新規マーケットオーサーをオープンする』が現ポジションに表示されます。それ以外は『新規未決注文を出してください』となります。このブロックでは情報提供以外の処理はありません。

そこでTRADE_TRANSACTION_ORDER_DELETE タイプを処理する3番目のモジュールの番です。

//--- 3) if it is a deletion of an order from the list of open ones
      case TRADE_TRANSACTION_ORDER_DELETE:
        {
         if(InpIsLogging)
            PrintFormat("Order deleted from the list of open ones: #%d, "+
                        EnumToString(trans.order_type),trans.order);
         //---     
         break;
        }

このモジュールもまた情報提供の役割をするだけです。

4番目のケースモジュールは TRADE_TRANSACTION_HISTORY_ADD タイプを処理します。

//--- 4) if it is an addition of a new order to the history
      case TRADE_TRANSACTION_HISTORY_ADD:
        {
         if(InpIsLogging)
            PrintFormat("Order added to the history: #%d, "+
                        EnumToString(trans.order_type),trans.order);

         //--- if a pending order is being processed
         if(trade_obj==TRADE_OBJ_ORDER)
           {
            //--- if it is the third pass
            if(gTransCnt==2)
              {
               //--- if the order was canceled, check the deals
               datetime now=TimeCurrent();

               //--- request the history of orders and deals
               HistorySelect(now-PeriodSeconds(PERIOD_H1),now);

               //--- attempt to find a deal for the order
               CDealInfo myDealInfo;
               int all_deals=HistoryDealsTotal();
               //---
               bool is_found=false;
               for(int deal_idx=all_deals;deal_idx>=0;deal_idx--)
                  if(myDealInfo.SelectByIndex(deal_idx))
                     if(myDealInfo.Order()==trans.order)
                        is_found=true;

               //--- if the deal was not found
               if(!is_found)
                 {
                  is_to_reset_cnt=true;
                  //---
                  PrintFormat("Order canceled: #%d",trans.order);
                 }
              }
            //--- if it is the fourth pass
            if(gTransCnt==3)
              {
               is_to_reset_cnt=true;
               PrintFormat("Order deleted: #%d",trans.order);
              }
           }
         //---     
         break;
        }

オーダーが履歴に追加されたレコード以外に、このモジュールは最初に未決注文を処理したかどうか確認を行います。処理していたら、ハンドラが持つ現パス番号を見つけ出す必要があります。問題はこのタイプのトランザクションは、未決注文が取り消されていたら、オーダーを処理するときは3番目のパスに入ってくることです。このタイプは未決注文が削除されたとき4番目のパスに現れます。

3番目のパスを確認するモジュールの文字列では、ディール履歴を再度参照する必要があります。現オーダーに対するディールが見つからなけば、そのオーダーが取り消されたとみなします。

5番目のケースモジュールは TRADE_TRANSACTION_DEAL_ADD タイプを処理します。文字列サイズではそれはプログラム最大のブロックです。

ディールはこのブロック内でチェックされます。プロパティにアクセスするにはディールをチケットで選択することが重要です。ディールタイプはポジションがオープンかクローズかなどの情報を提供します。未決注文実行に関する情報もそこで取得可能です。それは未決注文がイベントハンドラTradeTransaction の動作コンテキストでディールを生成する唯一のケースです。

//--- 5) if it is an addition of a deal to history
      case TRADE_TRANSACTION_DEAL_ADD:
        {
         is_to_reset_cnt=true;
         //---
         ulong deal_ticket=trans.deal;
         ENUM_DEAL_TYPE deal_type=trans.deal_type;
         //---
         if(InpIsLogging)
            PrintFormat("Deal added to history: #%d, "+EnumToString(deal_type),deal_ticket);

         if(deal_ticket>0)
           {
            datetime now=TimeCurrent();

            //--- request the history of orders and deals
            HistorySelect(now-PeriodSeconds(PERIOD_H1),now);

            //--- select a deal by the ticket
            if(HistoryDealSelect(deal_ticket))
              {
               //--- check the deal
               CDealInfo myDealInfo;
               myDealInfo.Ticket(deal_ticket);
               long order=myDealInfo.Order();

               //--- parameters of the deal
               ENUM_DEAL_ENTRY  deal_entry=myDealInfo.Entry();
               double deal_vol=0.;
               //---
               if(myDealInfo.InfoDouble(DEAL_VOLUME,deal_vol))
                  if(myDealInfo.InfoString(DEAL_SYMBOL,deal_symbol))
                    {
                     //--- position
                     CPositionInfo myPos;
                     double pos_vol=WRONG_VALUE;
                     //---
                     if(myPos.Select(deal_symbol))
                        pos_vol=myPos.Volume();

                     //--- if the market was entered
                     if(deal_entry==DEAL_ENTRY_IN)
                       {
                        //--- 1) opening of a position
                        if(deal_vol==pos_vol)
                           PrintFormat("\n%s: new position opened",deal_symbol);

                        //--- 2) addition to the open position        
                        else if(deal_vol<pos_vol)
                           PrintFormat("\n%s: addition to the current position",deal_symbol);
                       }

                     //--- if the market was exited
                     else if(deal_entry==DEAL_ENTRY_OUT)
                       {
                        if(deal_vol>0.0)
                          {
                           //--- 1) closure of a position
                           if(pos_vol==WRONG_VALUE)
                              PrintFormat("\n%s: position closed",deal_symbol);

                           //--- 2) partial closure of the open position        
                           else if(pos_vol>0.0)
                              PrintFormat("\n%s: partial closing of the current position",deal_symbol);
                          }
                       }

                     //--- if position was reversed
                     else if(deal_entry==DEAL_ENTRY_INOUT)
                       {
                        if(deal_vol>0.0)
                           if(pos_vol>0.0)
                              PrintFormat("\n%s: position reversal",deal_symbol);
                       }
                    }

               //--- order activation
               if(trade_obj==TRADE_OBJ_ORDER)
                  PrintFormat("Pending order activation: %d",order);
              }
           }

         //---
         break;
        }

トランザクションタイプ TRADE_TRANSACTION_POSITION はユニークでポジションが変更されるときにのみ処理されます。

//--- 6) if it is a modification of a position
      case TRADE_TRANSACTION_POSITION:
        {
         is_to_reset_cnt=true;
         //---
         PrintFormat("Modification of a position: %s",deal_symbol);
         //---
         if(InpIsLogging)
           {
            PrintFormat("New price of stop loss: %0."+
                        IntegerToString(_Digits)+"f",trans.price_sl);
            PrintFormat("New price of take profit: %0."+
                        IntegerToString(_Digits)+"f",trans.price_tp);
           }

         //---
         break;
        }

最後のケースモジュールはTRADE_TRANSACTION_ORDER_UPDATE タイプの処理時有効となります。

このタイプは未決注文処理のときだけ出現します。それは未決注文に関して任意のトレード処理実行で起動しますが、段階はさまざまです。

//--- 7) if it is a modification of an open order
      case TRADE_TRANSACTION_ORDER_UPDATE:
        {

         //--- if it was the first pass
         if(gTransCnt==0)
           {
            trade_obj=TRADE_OBJ_ORDER;
            PrintFormat("Canceling the order: #%d",trans.order);
           }
         //--- if it was the second pass
         if(gTransCnt==1)
           {
            //--- if it is an order modification
            if(last_action==TRADE_ACTION_MODIFY)
              {
               PrintFormat("Pending order modified: #%d",trans.order);
               //--- clear counter
               is_to_reset_cnt=true;
              }
            //--- if it is deletion of the order
            if(last_action==TRADE_ACTION_REMOVE)
              {
               PrintFormat("Delete pending order: #%d",trans.order);

              }
           }
         //--- if it was the third pass
         if(gTransCnt==2)
           {
            PrintFormat("A new pending order was placed: #%d, "+
                        EnumToString(trans.order_type),trans.order);
            //--- clear counter
            is_to_reset_cnt=true;
           }

         //---
         break;
        }

まとめると、OnTradeTransaction() の最初の実行時にこのタイプが出現する場合、オーダーは取り消されたか実行されたかです。

このタイプがイベントハンドラの2度目の起動時に現れると、オーダーは削除されたか変更されたかどちらかです。オーダーがどのような結果になったか正確に知るためには、最終トレード処理に関するデータを持つ静的変数 last_action を参照します。

イベントハンドラの3度目の起動はこのタイプが現れる最後のケースです。3度目の起動は未決注文を出す手続きを完了します。

ブール変数 is_to_reset_cnt がこのコードでも使用されます。それはOnTradeTransaction() ハンドルのパスのカウンターをクリアするフラグの役目です。

それはまさにすべてTradeTransaction イベントの処理次第です。私はハンドラ呼び出し開始時にポーズも追加します。をれはディールまたはオーダーが履歴に入る際の遅延の可能性を最小限に抑えます。


おわりに

本稿でトレード処理がどのように異なって行われるか、またターミナルで起こっている事柄に関する情報をどのように取得できるのか、ということについての説明を試みました。

この方法の最大のメリットはプログラムがトレード処理の段階的な実装に関する情報を入手することができることです。私見ですが、この方法はあるターミナルから別のターミナルへディールをコピーするのにも利用可能です。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1111

添付されたファイル |
tradeprocessor.mq5 (31.35 KB)
MQL5 クックブック:カスタムチャートイベント処理 MQL5 クックブック:カスタムチャートイベント処理
本稿では出人の側面とMQL5 環境におけるカスタムチャートイベントシステムの作成について考察します。イベント分類方法例およびイベントクラスとカスタムイベントハンドラのプログラムコードもここで確認することができます。
第三世代ニューラルネットワーク:深層ネットワーク 第三世代ニューラルネットワーク:深層ネットワーク
本稿ではマシン学習の新しい視点方向-深層学習、より正確には深いニューラルネットワークについてお話します。第二世代のニューラルネットワークについて、その連携のアーキテクチャと主なタイプ、メソッド、学習ルール、主な欠点とそれに続き第三世代の開発とその主要タイプ、特殊性、トレーニング方法について簡単に再検討しています。実データについて集積されたオートエンコーダのウェイトによって開始される深いニューラルネットワークの構築とトレーニングにおける実践的実験を行います。入力データを選択するところから行列偏差までの全段階について詳細にお話します。本稿最終部分は MQL4/R を基にした内蔵インディケータを持つ Expert Advisor での深いニューラルネットワークのソフトウェア実装です。
MetaTrader 4 と MetaTrader 5 の仮想ホスティングが通常の VPS より優れている理由 MetaTrader 4 と MetaTrader 5 の仮想ホスティングが通常の VPS より優れている理由
MetaTrader 4 と MetaTrader 5 用に仮想ホスティングクラウドネットワークが開発され、それはネイティブソリューションのメリットをすべて備えています。無料の24時間ディスカウントの恩恵を受けてください。いますぐ仮想サーバーを試してください。
貨幣価格変動に対するマクロ経済データの影響の回帰分析 貨幣価格変動に対するマクロ経済データの影響の回帰分析
本稿ではマクロ経済統計に対する重回帰分析のアプリケーションについか考察します。また通貨ペア EURUSD の例に基づく為替レートにおけるその統計の影響評価の洞察も提供します。その評価により初心者トレーダーにも利用可能となるファンダメンタル分析の自動化ができます。