
MQL5 クックブック:トレードトランザクションイベントの処理
はじめに
本稿では 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. トレードトランザクションイベント
トピックに深く入っていく前に公式情報を参照します。
ドキュメンテーションによると、トレードトランザクションイベントはトレードアカウントの特定処理の結果である。処理それ自体はトランザクションが決定する数多くの段階で構成されています。たとえば、マーケットオーダーでポジションをオープンするというトレードアカウントでのもっともよくおこなわれる処理の一つは次のような段階において実装されます。
- トレードリクエストを作成する
- トレードリクエストを検証する
- サーバーにトレードリクエストを送信する
- サーバーでトレードオーダー実行に関する応答を受信する
このシーケンスはコードの文字列に反映されるターミナル-サーバーのペア作業のロジックを示しているだけです。トレードトランザクショントレードイベントの観点からは、マーケットにおけるポジションオープンは以下のように起こります。
- MQL5 プログラムが完了したリクエストの結果についてサーバーから通知を受ける。
- ユニークチケットを持つオーダーの形式のリクエストはオープンオーダーのリストにインクルードされる。
- オーダーは実行後オープンオーダーのリストから削除される。
- それからそのオーダーはアカウント履歴に入る。
- アカウント履歴はオーダー実行結果のディールに関するデータも持ちます。
よってポジションをオープンするには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
ログに以下のエントリが表示されます。
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
ブロック"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
ブロック"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
関連情報はブロック "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
ログでは再びわれわれの関心はブロック"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スキーム
ポジション処理に関連するトレード処理はすべてこのスキームに従って行われます。ここでの唯一の例外はポジション変更処理です。最後の処理には以下の2つの処理があります(図7)。
図7 トランザクションプロセスの第2スキーム
ポジションの変更はディールとオーダーの履歴では追跡できません。
まさにポジションがすべてなのです。
3. 未決注文の処理
未決注文に関しては、トランザクションはより少ないことに留意します。同時にオーダーを処理する場合にはより多くのトランザクションタイプの組合せがあります。
オーダー変更のためには、ポジション変更同様、ハンドラは2度呼ばれます。発注とオーダー削除には呼び出しは3度行われます。オーダー削除または実行時にはトレードトランザクションイベントは4度発生します。
ここで未決注文を出します。ふたたびMetaTrader 5 ターミナルの任意のチャートでエキスパートをデバッグモードで起動する必要があります。
最初のハンドラ呼び出しはリクエストと連結します(図8)。
図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
ログではわれわれの関心は"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
ログではわれわれは"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 トランザクション-未決注文出しの処理
未決注文の変更はトランザクションを2つ生成します(図12)。
図12 トランザクション-未決注文変更処理
未決注文が削除される場合、OnTradeTransaction() ハンドラが4回呼ばれます(図13)。
図13 トランザクション-未決注文削除処理
未決注文の削除は次のスキームによって決定されます(図14)。
図14 トランザクション-未決注文削除処理
未決注文が実行されると最終トレード処理が件の異なるトランザクションを引き起こします(図15)。
図15 トランザクション-未決注文アクティブ化処理
トランザクションの組合せすべてについて長いエントリを表示するつもりはありません。そうしたいと思われる読者の方はコードを実行してエントリを調査することができます。
4. 汎用ハンドラ
エンドユーザーの目で トレードトランザクション イベントを処理するプログラムを見てみます。エンドユーザーはオーダー、ポジション双方と問題なく動作するプログラムを必要とするようです。プログラマーはOnTradeTransaction() に対しをそれが何を処理するにしてもすべてのトランザクションとその組合せを特定するようにコードを作成する必要があります。理想的には、そのプログラムは一連のトランザクション完了時にどの処理が実行されたか示すことができることです。
以下の例ではトランザクションの連続した処理がされています。ですが、MQL5 の開発者は次のように語ります。
理想に近い形で動作するプログラムを書く必要があれば、提案例を改善し、オーダー到着のトランザクション処理を独立させます。
一般的に、ポジションとオーダーはトランザクションの共通タイプです。トランザクションには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





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索