取引トランザクション:リクエストとレスポンスの構造体、説明、ロギング
内容
- 使用例
- OpenBuyで買いポジションを建てる
- OpenSellで売りポジションを建てる
- ClosePositionで指定したポジションを閉じる
- ClosePositionsAllですべてのポジションを閉じる
- SetPendingで指値注文を出す
- SetBuyStopで買い逆指値注文を設定する
- SetBuyLimitで買い指値注文を設定する
- SetBuyStopLimitでBuyStopLimit注文を設定する
- SetSellStopで売り逆指値注文を設定する
- SetSellLimitで売り指値注文を設定する
- SetSellStopLimitでSellStopLimit注文を設定する
- DeleteOrderで指定した未決注文を削除する
- 準備されたリクエストを送信前に確認するためのMqlTradeCheckResult構造体
- OrderSend()関数によって送信されたリクエストに対するサーバーレスポンスを持つMqlTradeResult構造体
- MqlTradeTransaction構造体と取引トランザクションの説明
- 取引チケット
- 注文チケット
- 取引商品名
- 取引トランザクションタイプ
- 注文タイプ
- 注文状況
- 取引タイプ
- 注文寿命タイプ
- 注文有効期限
- 価格
- 逆指値注文のトリガー価格
- ストップロスレベル
- 利益確定レベル
- ロット数
- ポジションチケット
- 反対側ポジションのチケット
- 使用例
- 取引情報提供EA
- 結論
はじめに
MQL5には、未決注文を出し、ポジションを開き、注文やポジションを変更するためのOrderSend()関数があります。この関数の最初の入力は、MqlTradeRequest取引リクエストの構造体です。構造体のactionフィールドは、実行されるアクションのタイプを示し、残りのフィールドは、actionフィールドで選択されたアクションに応じて入力されます。こうして、取引リクエストに必要なパラメータを関数に渡すことで、サーバーにさまざまなリクエストを送ります。
取引リクエスト構造体(MqlTradeRequest)
発注操作におけるクライアント端末と取引サーバーのやり取りは、取引リクエストを通じておこなわれます。このリクエストは、特別に定義されたMqlTradeRequest構造体によって表現されます。この構造体には取引を実行するために必要なすべてのフィールドが含まれています。
struct MqlTradeRequest { ENUM_TRADE_REQUEST_ACTIONS action; // Type of a performed action ulong magic; // EA stamp (magic number ID) ulong order; // Order ticket string symbol; // Symbol name double volume; // Requested volume of a deal in lots double price; // Price double stoplimit; // StopLimit order level double sl; // Stop Loss order level double tp; // Take Profit order level ulong deviation; // Maximum acceptable deviation from the requested price ENUM_ORDER_TYPE type; // Order type ENUM_ORDER_TYPE_FILLING type_filling; // Order filling type ENUM_ORDER_TYPE_TIME type_time; // Order lifetime type datetime expiration; // Order expiration time (for ORDER_TIME_SPECIFIED type orders) string comment; // Order comment ulong position; // Position ticket ulong position_by; // Opposite position ticket };
最初のactionフィールドは、実行するアクションのタイプを指定します。
これは取引操作タイプで、値はENUM_TRADE_REQUEST_ACTIONS列挙値のいずれかです。
ID | 詳細 |
---|---|
TRADE_ACTION_DEAL | 指定したパラメータで即時取引の注文を出す(成行注文を設定する) |
TRADE_ACTION_PENDING | 指定した条件で取引をおこなうための注文を出す(未決注文) |
TRADE_ACTION_SLTP | ストップロスとテイクプロフィットを変更する |
TRADE_ACTION_MODIFY | 先に発注した取引注文のパラメータを変更する |
TRADE_ACTION_REMOVE | 以前に発注した未決注文を削除する |
TRADE_ACTION_CLOSE_BY | 反対側のポジションでポジションを閉じる |
構造体フィールドは、アクションの種類ごとに個別に入力しなければなりません。
必要事項を入力したら、サーバーに取引注文を送信します。また、OrderCheck()関数を使用して、構造体が正しく入力されているかどうかを最初に確認することもできます。この関数では、確認対象のクエリとMqlTradeCheckResult構造体タイプの変数を送信します。確認の結果は変数に設定されます。
struct MqlTradeCheckResult { uint retcode; // Response code double balance; // Balance after performing a deal double equity; // Equity after performing a deal double profit; // Floating profit double margin; // Margin requirements double margin_free; // Free margin double margin_level; // Margin level string comment; // Comment on the response code (error description) };
注文を確認した結果、資金が不足していたり、パラメータが正しく入力されていなかったりした場合、この関数はfalseを返します。構造体(ポインタ)の基本的な確認が成功した場合、関数はtrueを返しますが、これは、要求された取引操作が正常に実行されることを意味するものではありません 。関数を実行した結果の詳細な説明を得るには、 上に示したresult構造体のフィールドを分析する必要があります。
取引注文構造体のフィールドの完了を正常に確認した後、サーバーに送信することができます。OrderSend()関数の実行が成功しても、注文が実行されたことにはなりません。注文が処理され、サーバーに受け入れられたことがわかるだけです。取引注文をサーバーに送信した結果は、MqlTradeResult構造体のフィールドに入力されたものになります。この構造体には、OrderSend()関数によって送信されたリクエストに対する取引サーバーの応答が含まれています。
取引操作の結果は、MqlTradeResult型の変数に返されます。これは、取引操作をおこなうために、OrderSend()関数の2番目のパラメータとして渡されます。
OrdersSend()およびOrderSendAsync()関数を使用して端末から取引サーバーにリクエストが送信される際、 request_idフィールドにはリクエストIDが設定されます。端末は実行された取引に関するメッセージを取引サーバーから受信し、以下のコンポーネントをパラメータとして含むOnTradeTransaction()関数による処理のために送信します。
- MqlTradeTransaction構造体での取引トランザクションの説明
- OrderSend()またはOrdersSendAsync()関数から送信された取引リクエストの説明(リクエストIDは端末から取引サーバーに送信され、リクエストそのものとそのrequest_idは端末のメモリに保存される)
- このリクエストのIDを含むrequest_idフィールドを持つMqlTradeResult構造体としての取引リクエスト実行結果
OnTradeTransaction()関数は3つの入力パラメータを受け取りますが、最後の2つはTRADE_TRANSACTION_REQUEST型のトランザクションについてのみ分析する必要があります。それ以外の場合、取引リクエストとその約定結果に関するデータは入力されません。パラメータ分析の例は、取引リクエスト構造体セクションに記載されています。
サーバーへの送信時に端末が取引リクエストのrequest_idを設定するようにされたのは、主に OrderSendAsync()非同期関数と連携するためです。この識別子により、実行されたアクション(OrderSendまたはOrderSendAsync関数の呼び出し)とOnTradeTransaction()に送信されたアクションの結果を関連付けることができます。
したがって、OnTradeTransaction()関数の中で、サーバーによる取引注文の受理、取引システムへの配置と約定を制御することができます。今回は、取引注文の構造体への入力から始まり、OnTradeTransaction()のイベント分析まで、取引リクエストに関わるすべての構造体フィールドをログに表示する関数を書いていきます。意図した結果は、すべての取引イベントを操作ログに出力する小さな情報提供EAです。
取引注文の処理は、以下の点に集約されます。
- 取引リクエストの構造体に入力する
- 入力の正しさを確認し、このような注文が可能かどうかを確認する
- 取引注文をサーバーに送信する
- 必要に応じて、サーバーに注文を送信した結果の構造を分析する
- OnTradeTransaction()ハンドラからイベントを受け取り、ログのメッセージを分析する
補助関数
記事の最後に紹介するEAは、キーボードショートカットを押して操作します。CtrlキーとShiftキーの押下を判定する関数を2つ書いてみましょう。
//+------------------------------------------------------------------+ //| Return the state of the Ctrl key | //+------------------------------------------------------------------+ bool IsCtrlKeyPressed(void) { return(::TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL)<0); } //+------------------------------------------------------------------+ //| Return the state of the Shift key | //+------------------------------------------------------------------+ bool IsShiftKeyPressed(void) { return(::TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT)<0); }
これで、キーが押されたことを検出する際に、CtrlキーやShiftキーを押し続けているか、あるいは同時に押し続けているかのフラグを確認し、Ctrlキーと英数字キーの組み合わせに対応できるようになりました。
構造体フィールドの説明を返す場合、取引サーバーのリターンコードを出力する必要があります。サーバーの応答コードの説明を返す関数を作ってみましょう。
//+------------------------------------------------------------------+ //| Return a description of the trade server return code | //+------------------------------------------------------------------+ string RetcodeDescription(const uint retcode,bool ext_descr=false) { switch(retcode) { //--- Done case 0 : return "OK (0)"; //--- Requote case TRADE_RETCODE_REQUOTE : return "10004 REQUOTE"+(ext_descr ? " (Requote)" : ""); //--- Request rejected case TRADE_RETCODE_REJECT : return "10006 REJECT"+(ext_descr ? " (Request rejected)" : ""); //--- Request canceled by trader case TRADE_RETCODE_CANCEL : return "10007 CANCEL"+(ext_descr ? " (Request canceled by trader)" : ""); //--- Order placed case TRADE_RETCODE_PLACED : return "10008 PLACED"+(ext_descr ? " (Order placed)" : ""); //--- Request completed case TRADE_RETCODE_DONE : return "10009 DONE"+(ext_descr ? " (Request completed)" : ""); //--- Request completed partially case TRADE_RETCODE_DONE_PARTIAL : return "10010 DONE_PARTIAL"+(ext_descr ? " (Only part of the request was completed)" : ""); //--- Request processing error case TRADE_RETCODE_ERROR : return "10011 ERROR"+(ext_descr ? " (Request processing error)" : ""); //--- Request canceled by timeout case TRADE_RETCODE_TIMEOUT : return "10012 TIMEOUT"+(ext_descr ? " (Request canceled by timeout)" : ""); //--- Invalid request case TRADE_RETCODE_INVALID : return "10013 INVALID"+(ext_descr ? " (Invalid request)" : ""); //--- Invalid volume in the request case TRADE_RETCODE_INVALID_VOLUME : return "10014 INVALID_VOLUME"+(ext_descr ? " (Invalid volume in the request)" : ""); //--- Invalid price in the request case TRADE_RETCODE_INVALID_PRICE : return "10015 INVALID_PRICE"+(ext_descr ? " (Invalid price in the request)" : ""); //--- Invalid stops in the request case TRADE_RETCODE_INVALID_STOPS : return "10016 INVALID_STOPS"+(ext_descr ? " (Invalid stops in the request)" : ""); //--- Trading disabled case TRADE_RETCODE_TRADE_DISABLED : return "10017 TRADE_DISABLED"+(ext_descr ? " (Trade is disabled)" : ""); //--- Market is closed case TRADE_RETCODE_MARKET_CLOSED : return "10018 MARKET_CLOSED"+(ext_descr ? " (Market is closed)" : ""); //--- There is not enough money to complete the request case TRADE_RETCODE_NO_MONEY : return "10019 NO_MONEY"+(ext_descr ? " (There is not enough money to complete the request)" : ""); //--- Prices changed case TRADE_RETCODE_PRICE_CHANGED : return "10020 PRICE_CHANGED"+(ext_descr ? " (Prices changed)" : ""); //--- There are no quotes to process the request case TRADE_RETCODE_PRICE_OFF : return "10021 PRICE_OFF"+(ext_descr ? " (There are no quotes to process the request)" : ""); //--- Invalid order expiration date in the request case TRADE_RETCODE_INVALID_EXPIRATION : return "10022 INVALID_EXPIRATION"+(ext_descr ? " (Invalid order expiration date in the request)" : ""); //--- Order state changed case TRADE_RETCODE_ORDER_CHANGED : return "10023 ORDER_CHANGED"+(ext_descr ? " (Order state changed)" : ""); //--- Too frequent requests case TRADE_RETCODE_TOO_MANY_REQUESTS : return "10024 TOO_MANY_REQUESTS"+(ext_descr ? " (Too frequent requests)" : ""); //--- No changes in request case TRADE_RETCODE_NO_CHANGES : return "10025 NO_CHANGES"+(ext_descr ? " (No changes in request)" : ""); //--- Autotrading disabled by server case TRADE_RETCODE_SERVER_DISABLES_AT : return "10026 SERVER_DISABLES_AT"+(ext_descr ? " (Autotrading disabled by server)" : ""); //--- Autotrading disabled by client terminal case TRADE_RETCODE_CLIENT_DISABLES_AT : return "10027 CLIENT_DISABLES_AT"+(ext_descr ? " (Autotrading disabled by client terminal)" : ""); //--- Request locked for processing case TRADE_RETCODE_LOCKED : return "10028 LOCKED"+(ext_descr ? " (Request locked for processing)" : ""); //--- Order or position frozen case TRADE_RETCODE_FROZEN : return "10029 FROZEN"+(ext_descr ? " (Order or position frozen)" : ""); //--- Invalid order filling type case TRADE_RETCODE_INVALID_FILL : return "10030 INVALID_FILL"+(ext_descr ? " (Invalid order filling type)" : ""); //--- No connection with the trade server case TRADE_RETCODE_CONNECTION : return "10031 CONNECTION"+(ext_descr ? " (No connection with the trade server)" : ""); //--- Operation allowed only for live accounts case TRADE_RETCODE_ONLY_REAL : return "10032 ONLY_REAL"+(ext_descr ? " (Operation is allowed only for live accounts)" : ""); //--- Number of pending orders reached the limit case TRADE_RETCODE_LIMIT_ORDERS : return "10033 LIMIT_ORDERS"+(ext_descr ? " (The number of pending orders has reached the limit)" : ""); //--- Volume of orders and positions for the symbol reached the limit case TRADE_RETCODE_LIMIT_VOLUME : return "10034 LIMIT_VOLUME"+(ext_descr ? " (The volume of orders and positions for the symbol has reached the limit)" : ""); //--- Incorrect or prohibited order type case TRADE_RETCODE_INVALID_ORDER : return "10035 INVALID_ORDER"+(ext_descr ? " (Incorrect or prohibited order type)" : ""); //--- Position with specified POSITION_IDENTIFIER already closed case TRADE_RETCODE_POSITION_CLOSED : return "10036 POSITION_CLOSED"+(ext_descr ? " (Position with the specified POSITION_IDENTIFIER has already been closed)" : ""); //--- Close volume exceeds the current position volume case TRADE_RETCODE_INVALID_CLOSE_VOLUME: return "10038 INVALID_CLOSE_VOLUME"+(ext_descr ? " (A close volume exceeds the current position volume)" : ""); //--- Close order already exists for specified position case TRADE_RETCODE_CLOSE_ORDER_EXIST : return "10039 CLOSE_ORDER_EXIST"+(ext_descr ? " (A close order already exists for a specified position)" : ""); //--- Number of positions reached the limit case TRADE_RETCODE_LIMIT_POSITIONS : return "10040 LIMIT_POSITIONS"+(ext_descr ? " (The number of positions has reached the limit)" : ""); //--- Pending order activation request is rejected, order is canceled case TRADE_RETCODE_REJECT_CANCEL : return "10041 REJECT_CANCEL"+(ext_descr ? " (The pending order activation request is rejected, the order is canceled)" : ""); //--- Request rejected, only long positions are allowed on symbol case TRADE_RETCODE_LONG_ONLY : return "10042 LONG_ONLY"+(ext_descr ? " (Only long positions are allowed)" : ""); //--- Request rejected, only short positions are allowed on symbol case TRADE_RETCODE_SHORT_ONLY : return "10043 SHORT_ONLY"+(ext_descr ? " (Only short positions are allowed)" : ""); //--- Request rejected, only position closing is allowed on symbol case TRADE_RETCODE_CLOSE_ONLY : return "10044 CLOSE_ONLY"+(ext_descr ? " (Only position closing is allowed)" : ""); //--- Request rejected, position closing for trading account is allowed only by FIFO rule case TRADE_RETCODE_FIFO_CLOSE : return "10045 FIFO_CLOSE"+(ext_descr ? " (Position closing is allowed only by FIFO rule)" : ""); //--- Request rejected, opposite positions on a single symbol are disabled for trading account case TRADE_RETCODE_HEDGE_PROHIBITED : return "10046 HEDGE_PROHIBITED"+(ext_descr ? " (Opposite positions on a single symbol are disabled)" : ""); //--- Unknown return code default : return "Undefined ("+(string)retcode+")"; } }
この関数は、サーバーの応答コードと、拡張説明を返す必要性を示すフラグを受け取ります。この関数は、定数記述のデジタルコード
10034 LIMIT_VOLUME
またはサーバーの応答コードの詳細な説明のいずれかを返します。
10034 LIMIT_VOLUME (The volume of orders and positions for the symbol has reached the limit)
以下は、注文タイプの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return the order type description | //+------------------------------------------------------------------+ string OrderTypeDescription(const ENUM_ORDER_TYPE type,const bool ext_descr=false) { //--- "Cut out" the order type from the string obtained from enum string res=StringSubstr(EnumToString(type),11); //--- Convert all received characters to lowercase and if(res.Lower()) { //--- replace the first letter from small to capital res.SetChar(0,ushort(res.GetChar(0)-0x20)); int total=(int)res.Length(); // Text length int index=0; // index to start searching for "_" in a text //--- Search for underscores in a loop through all characters for(int i=0;i<total;i++) { int pos=StringFind(res,"_",index); //--- If an underscore is found, if(pos>0) { //--- replace it with space and convert the next letter to uppercase res.SetChar(pos,' '); res.SetChar(pos+1,ushort(res.GetChar(pos+1)-0x20)); //--- Set a new index for starting the search for "_" index=pos; } } } string descr=""; switch(type) { case ORDER_TYPE_BUY : descr=" (Market Buy order)"; break; case ORDER_TYPE_SELL : descr=" (Market Sell order)"; break; case ORDER_TYPE_BUY_LIMIT : descr=" (Buy Limit pending order)"; break; case ORDER_TYPE_SELL_LIMIT : descr=" (Sell Limit pending order)"; break; case ORDER_TYPE_BUY_STOP : descr=" (Buy Stop pending order)"; break; case ORDER_TYPE_SELL_STOP : descr=" (Sell Stop pending order)"; break; case ORDER_TYPE_BUY_STOP_LIMIT : descr=" (Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price)"; break; case ORDER_TYPE_SELL_STOP_LIMIT : descr=" (Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price)";break; case ORDER_TYPE_CLOSE_BY : descr=" (Order to close a position by an opposite one)"; break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Sell Limit (Sell Limit pending order) */ }
OrderSend()関数を使用して取引リクエストを送信する際、いくつかの操作では注文タイプを指定する必要があります。注文タイプはMqlTradeRequest構造体のtypeフィールドで指定され、 ENUM_ORDER_TYPE列挙から値を取ることができます。
ID | 詳細 |
---|---|
ORDER_TYPE_BUY | 成行買い注文 |
ORDER_TYPE_SELL | 成行売り注文 |
ORDER_TYPE_BUY_LIMIT | 買い指値注文 |
ORDER_TYPE_SELL_LIMIT | 売り指値注文 |
ORDER_TYPE_BUY_STOP | 買い逆指値注文 |
ORDER_TYPE_SELL_STOP | 売り逆指値注文 |
ORDER_TYPE_BUY_STOP_LIMIT | 注文価格に達すると、買い指値注文が逆指値で出される |
ORDER_TYPE_SELL_STOP_LIMIT | 注文価格に達すると、売り指値注文が逆指値で出される |
ORDER_TYPE_CLOSE_BY | 反対ポジションによる決済の注文 |
以下は、実行による注文タイプの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return the order type description by execution | //+------------------------------------------------------------------+ string OrderTypeFillingDescription(const ENUM_ORDER_TYPE_FILLING type_filling,const bool ext_descr=false) { string res=StringSubstr(EnumToString(type_filling),14); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital (for ORDER_FILLING_RETURN) if(type_filling==ORDER_FILLING_RETURN && res.Lower()) res.SetChar(0,ushort(res.GetChar(0)-0x20)); string descr=""; switch(type_filling) { case ORDER_FILLING_FOK : descr=" (Fill or Kill. An order can be executed in the specified volume only)"; break; case ORDER_FILLING_IOC : descr=" (Immediate or Cancel. A deal with the volume maximally available in the market within that indicated in the order)"; break; case ORDER_FILLING_BOC : descr=" (Passive (Book or Cancel). The order can only be placed in the Depth of Market and cannot be immediately executed)"; break; case ORDER_FILLING_RETURN : descr=" (In case of partial filling, an order with remaining volume is not canceled but processed further)"; break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further) */ }OrderSend()関数を使用して取引リクエストを送信する際、必要な出来高執行方策は、特別なMqlTradeRequest構造体のtype_fillingフィールドで設定できます。ENUM_ORDER_TYPE_FILLING列挙体の値が使用できます。特定の有効/完了注文のプロパティ値を取得するには、OrderGetInteger()またはHistoryOrderGetInteger()関数をORDER_TYPE_FILLING修飾子と共に使用します。
ORDER_TYPE_FILLING値(出来高による執行タイプ)を正しく設定するために、現在時刻に執行する注文を送信する前に、各金融商品のSymbolInfoInteger()関数を使用してSYMBOL_FILLING_MODEプロパティの値を取得することができます。これは、この銘柄に許可されるボリューム処理タイプをフラグの組み合わせとして示しています。ORDER_FILLING_RETURN処理タイプは、「市場執行」モード(SYMBOL_TRADE_EXECUTION_MARKET)を除き、常に有効です。
以下は、取引トランザクションタイプの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return a description of the trade transaction type | //+------------------------------------------------------------------+ string TradeTransactionTypeDescription(const ENUM_TRADE_TRANSACTION_TYPE transaction,const bool ext_descr=false) { //--- "Cut out" the transaction type from the string obtained from enum string res=StringSubstr(EnumToString(transaction),18); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital if(res.Lower()) res.SetChar(0,ushort(res.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(res,"_"," "); string descr=""; switch(transaction) { case TRADE_TRANSACTION_ORDER_ADD : descr=" (Adding a new open order)"; break; case TRADE_TRANSACTION_ORDER_UPDATE : descr=" (Updating an open order)"; break; case TRADE_TRANSACTION_ORDER_DELETE : descr=" (Removing an order from the list of the open ones)"; break; case TRADE_TRANSACTION_DEAL_ADD : descr=" (Adding a deal to the history)"; break; case TRADE_TRANSACTION_DEAL_UPDATE : descr=" (Updating a deal in the history)"; break; case TRADE_TRANSACTION_DEAL_DELETE : descr=" (Deleting a deal from the history)"; break; case TRADE_TRANSACTION_HISTORY_ADD : descr=" (Adding an order to the history as a result of execution or cancellation)"; break; case TRADE_TRANSACTION_HISTORY_UPDATE : descr=" (Changing an order located in the orders history)"; break; case TRADE_TRANSACTION_HISTORY_DELETE : descr=" (Deleting an order from the orders history)"; break; case TRADE_TRANSACTION_POSITION : descr=" (Changing a position not related to a deal execution)"; break; case TRADE_TRANSACTION_REQUEST : descr=" (The trade request has been processed by a server and processing result has been received)"; break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Order add (Adding a new open order) */ }
この関数は、口座で実行された取引トランザクションタイプの説明を返します。
以下は、注文ステータスの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return an order state description | //+------------------------------------------------------------------+ string OrderStateDescription(const ENUM_ORDER_STATE state,const bool ext_descr=false) { //--- "Cut out" the order status from the string obtained from enum string res=StringSubstr(EnumToString(state),12); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital if(res.Lower()) res.SetChar(0,ushort(res.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(res,"_"," "); string descr=""; switch(state) { case ORDER_STATE_STARTED : descr=" (Order checked, but not yet accepted by broker)"; break; case ORDER_STATE_PLACED : descr=" (Order accepted)"; break; case ORDER_STATE_CANCELED : descr=" (Order canceled by client)"; break; case ORDER_STATE_PARTIAL : descr=" (Order partially executed)"; break; case ORDER_STATE_FILLED : descr=" (Order fully executed)"; break; case ORDER_STATE_REJECTED : descr=" (Order rejected)"; break; case ORDER_STATE_EXPIRED : descr=" (Order expired)"; break; case ORDER_STATE_REQUEST_ADD : descr=" (Order is being registered (placing to the trading system))";break; case ORDER_STATE_REQUEST_MODIFY : descr=" (Order is being modified (changing its parameters))"; break; case ORDER_STATE_REQUEST_CANCEL : descr=" (Order is being deleted (deleting from the trading system))";break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Placed (Order accepted) */ }
各注文には、その状態を表すステータスがあります。情報を取得するには、OrderGetInteger()またはHistoryOrderGetInteger()関数をORDER_STATE修飾子と共に使用します。有効な値はENUM_ORDER_STATE列挙体に格納されています。サーバーに取引リクエストを送信すると、注文のステータスが徐々に変化します。まず、サーバーによって確認され、次に取引システムに置かれ、そしてトリガーされ、取引が発生するか、キャンセルされます。このリストには、可能なすべての注文状態が含まれており、取引注文を扱う際には、それらを考慮する必要があります。
以下は、トランザクションタイプの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return the deal type description | //+------------------------------------------------------------------+ string DealTypeDescription(const ENUM_DEAL_TYPE type,const bool ext_descr=false) { //--- "Cut out" the deal type from the string obtained from enum string res=StringSubstr(EnumToString(type),(type==DEAL_DIVIDEND || type==DEAL_DIVIDEND_FRANKED || type==DEAL_TAX ? 5 : 10)); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital if(res.Lower()) res.SetChar(0,ushort(res.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(res,"_"," "); string descr=""; //--- Extended descriptions are added only to the deals whose description obtained from enum does not match the extended one switch(type) { case DEAL_TYPE_CHARGE : descr=" (Additional charge)"; break; case DEAL_TYPE_COMMISSION : descr=" (Additional commission)"; break; case DEAL_TYPE_COMMISSION_DAILY : descr=" (Daily commission)"; break; case DEAL_TYPE_COMMISSION_MONTHLY : descr=" (Monthly commission)"; break; case DEAL_TYPE_COMMISSION_AGENT_DAILY : descr=" (Daily agent commission)"; break; case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: descr=" (Monthly agent commission)"; break; case DEAL_TYPE_INTEREST : descr=" (Interest rate)"; break; case DEAL_TYPE_BUY_CANCELED : descr=" (Canceled buy deal)"; break; case DEAL_TYPE_SELL_CANCELED : descr=" (Canceled sell deal)"; break; case DEAL_DIVIDEND : descr=" (Dividend operations)"; break; case DEAL_DIVIDEND_FRANKED : descr=" (Franked (non-taxable) dividend operations)"; break; case DEAL_TAX : descr=" (Tax charges)"; break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Comission (Additional commission) */ }
各取引にはタイプがあります。取り得る値はENUM_DEAL_TYPEに記載されています。取引タイプに関するデータを取得するには、HistoryDealGetInteger()関数をDEAL_TYPE修飾子と共に使用します。
以下は、有効期限による注文タイプの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return an order type description by expiration | //+------------------------------------------------------------------+ string OrderTypeTimeDescription(const ENUM_ORDER_TYPE_TIME type_time,const bool ext_descr=false) { //--- "Cut out" the order type by expiration from the string obtained from enum string res=StringSubstr(EnumToString(type_time),6); //--- If the type by expiration is ORDER_TIME_GTC, add "Time GTC" to res if(type_time==ORDER_TIME_GTC) res="Time GTC"; //--- Otherwise, convert all obtained symbols to lower case and replace the first letter from small to capital else { if(res.Lower()) res.SetChar(0,ushort(res.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(res,"_"," "); } string descr=""; switch(type_time) { case ORDER_TIME_GTC : descr=" (Good till cancel order)"; break; case ORDER_TIME_DAY : descr=" (Good till current trade day order)"; break; case ORDER_TIME_SPECIFIED : descr=" (Good till expired order)"; break; case ORDER_TIME_SPECIFIED_DAY : descr=" (The order will be effective till 23:59:59 of the specified day)"; break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Time GTC (Good till cancel order) */ }
注文の有効期限は 、OrderSend()関数を使用して取引リクエストを送信する際に、MqlTradeRequest構造体のtype_timeフィールドに設定することができます。ENUM_ORDER_TYPE_TIME列挙体の値が有効です。プロパティ値を取得するには、OrderGetInteger()またはHistoryOrderGetInteger()関数をORDER_TYPE_TIME修飾子とともに使用します。
取引トランザクションは、注文、取引、ポジションによって発生します。このようなトランザクションの各カテゴリには、追加、変更、削除という異なるタイプがあり得ます。ただし、注文、取引、ポジションなど、詳細を特定することなく、どのようなトランザクションがおこなわれたのかだけを知りたい場合もあります。これを実現するために、トランザクションの所属を返す関数を作ってみましょう。
//+------------------------------------------------------------------+ //| Define and set transaction affiliation values | //+------------------------------------------------------------------+ void SetTransactionBelong(const ENUM_TRADE_TRANSACTION_TYPE type,bool &request_flag,bool &order_flag,bool &deal_flag,bool &position_flag) { switch(type) { //--- Request case TRADE_TRANSACTION_REQUEST : request_flag=true; order_flag=false; deal_flag=false; position_flag=false; break; //--- Order case TRADE_TRANSACTION_ORDER_ADD : case TRADE_TRANSACTION_ORDER_UPDATE : case TRADE_TRANSACTION_ORDER_DELETE : case TRADE_TRANSACTION_HISTORY_ADD : case TRADE_TRANSACTION_HISTORY_UPDATE : case TRADE_TRANSACTION_HISTORY_DELETE : request_flag=false; order_flag=true; deal_flag=false; position_flag=false; break; //--- Deal case TRADE_TRANSACTION_DEAL_ADD : case TRADE_TRANSACTION_DEAL_UPDATE : case TRADE_TRANSACTION_DEAL_DELETE : request_flag=false; order_flag=false; deal_flag=true; position_flag=false; break; //--- Position case TRADE_TRANSACTION_POSITION : request_flag=false; order_flag=false; deal_flag=false; position_flag=true; break; //--- default: break; } }
この関数はトランザクションタイプを受け取り、参照により3つのフラグ変数を受け取ります。これらの変数は、トランザクションが正確に実行された内容に応じてセット/リセットされます。
以下は、取引リクエストタイプの説明を返す関数です。
//+------------------------------------------------------------------+ //| Return the trade request type description | //+------------------------------------------------------------------+ string TradeActionDescription(const ENUM_TRADE_REQUEST_ACTIONS action,const bool ext_descr=false) { //--- "Cut out" the operation type from the string obtained from enum string res=StringSubstr(EnumToString(action),13); //--- Convert all obtained symbols to lower case and replace the first letter from small to capital (except for TRADE_ACTION_SLTP) if(action!=TRADE_ACTION_SLTP && res.Lower()) res.SetChar(0,ushort(res.GetChar(0)-0x20)); string descr=""; switch(action) { case TRADE_ACTION_DEAL : descr=" (Place a trade order for an immediate execution with the specified parameters (market order))";break; case TRADE_ACTION_PENDING : descr=" (Place a trade order for the execution under specified conditions (pending order))"; break; case TRADE_ACTION_SLTP : descr=" (Modify Stop Loss and Take Profit values of an opened position)"; break; case TRADE_ACTION_MODIFY : descr=" (Modify the parameters of the order placed previously)"; break; case TRADE_ACTION_REMOVE : descr=" (Delete the pending order placed previously)"; break; case TRADE_ACTION_CLOSE_BY : descr=" (Close a position by an opposite one)"; break; default: break; } return res+(!ext_descr ? "" : descr); /* Sample output: Pending (Place a trade order for the execution under specified conditions (pending order)): */ }
取引リクエストの構造体、そのフィールドの説明の出力を見て、この構造体でどのように動作するかを説明するいくつかの取引関数を作成しましょう。
取引操作の際にリクエストを作成するためのMqlTradeRequest構造体
発注操作におけるクライアント端末と取引サーバーのやり取りは、取引リクエストを通じておこなわれます。このリクエストは、特別に定義されたMqlTradeRequest構造体によって表現されます。この構造体には取引を実行するために必要なすべてのフィールドが含まれています。
struct MqlTradeRequest { ENUM_TRADE_REQUEST_ACTIONS action; // Type of a performed action ulong magic; // EA stamp (magic number ID) ulong order; // Order ticket string symbol; // Symbol name double volume; // Requested volume of a deal in lots double price; // Price double stoplimit; // StopLimit order level double sl; // Stop Loss order level double tp; // Take Profit order level ulong deviation; // Maximum acceptable deviation from the requested price ENUM_ORDER_TYPE type; // Order type ENUM_ORDER_TYPE_FILLING type_filling; // Order filling type ENUM_ORDER_TYPE_TIME type_time; // Order lifetime type datetime expiration; // Order expiration time (for ORDER_TIME_SPECIFIED type orders) string comment; // Order comment ulong position; // Position ticket ulong position_by; // Opposite position ticket };
取引注文をサーバーに送信するには、注文に適した方法で構造体フィールドに入力される必要があります。actionフィールドは入力されるべきです。このフィールドにどのようなアクションが書かれるかによって、そのアクションに必要な構造の他のフィールドも入力されます。従って、未使用のフィールドはゼロを含みます(ただし、構造体のフィールドは、入力前にゼロにリセットされます)。構造体フィールドの説明を表示する際、いくつかのフィールドは使用されておらず、ゼロが含まれています。これは、未使用のフィールドをログに送信するときに表示されるべきです。例えば、値(1.12345)の小数点以下の桁数を使用する代わりに、1つだけ(0.0)を使用します。これにより、このフィールドが単に入力されていないことが明確になります。
最終的にログに構造体を出力する際には、トランザクションに応じて未使用のフィールドを考慮し、単に表示しないようにします。
実行されたアクションのタイプ
これは取引操作タイプで、値は、ENUM_TRADE_REQUEST_ACTIONS列挙値のいずれかです。
//+------------------------------------------------------------------+ //| Return the type of a performed action as a string | //+------------------------------------------------------------------+ string MqlTradeRequestAction(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Action:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,TradeActionDescription(req.action,ext_descr)); /* Sample output: Action: Pending (Place a trade order for the execution under specified conditions (pending order)): */ }
エキスパートアドバイザー(EA)のスタンプ(マジックナンバー識別子)
これはEAのIDで、取引注文を分析的に処理できるようにします。各EAは、取引リクエストを送信する際に一意のIDを設定することができます 。//+------------------------------------------------------------------+ //| Return the EA stamp (magic number) as a string | //+------------------------------------------------------------------+ string MqlTradeRequestMagic(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Magic:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.magic); /* Sample output: Magic: 1024 */ }
注文チケット
これは注文チケットで、未決注文の修正に必要です。
//+------------------------------------------------------------------+ //| Return the order ticket as a string | //+------------------------------------------------------------------+ string MqlTradeRequestOrder(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Order:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.order); /* Sample output: Order: 1835982676 */ }
取引商品名
これは注文の対象となる取引商品名ですが、注文の変更およびポジションの決済時には不要です。
//+------------------------------------------------------------------+ //| Return a trading instrument name | //+------------------------------------------------------------------+ string MqlTradeRequestSymbol(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Symbol:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,req.symbol); /* Sample output: Symbol: EURUSD */ }
ロット単位での取引希望数量
リクエストされたロット単位の取引量です。取引をおこなう際の実際の出来高は、注文執行タイプに依存します。
//+------------------------------------------------------------------+ //| Return the requested volume of a deal in lots as a string | //+------------------------------------------------------------------+ string MqlTradeRequestVolume(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places in the lot value. If the character is not specified, use 1 int dg=(int)ceil(fabs(log10(SymbolInfoDouble(req.symbol,SYMBOL_VOLUME_STEP)))); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.volume); /* Sample output: Volume: 0.10 */ }
価格
注文を執行する価格です。TRADE_ACTION_DEAL型を持つ「成行執行」(SYMBOL_TRADE_EXECUTION_MARKET)型の商品の成行注文の場合、価格は設定されません。
//+------------------------------------------------------------------+ //| Return the price as a string | //+------------------------------------------------------------------+ string MqlTradeRequestPrice(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(req.price!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.price); /* Sample output: Price: 1.09586 */ }
ストップリミット注文レベル
BuyStopLimitとSellStopLimitの未決注文用です。価格がprice値に達したときに、指値注文が発注される価格(この条件は必須)です。指値注文は、その瞬間まで取引システムに渡されません 。
//+------------------------------------------------------------------+ //| Return the StopLimit order level as a string | //+------------------------------------------------------------------+ string MqlTradeRequestStopLimit(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="StopLimit:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(req.stoplimit!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.stoplimit); /* Sample output: StopLimit: 0.0 */ }
ストップロス注文レベル
ストップロス注文は、価格が不利な方向に動いたときに発動される価格です。
//+------------------------------------------------------------------+ //| Return the Stop Loss order level as a string | //+------------------------------------------------------------------+ string MqlTradeRequestStopLoss(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="SL:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(req.sl!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.sl); /* Sample output: SL: 0.0 */ }
テイクプロフィット注文レベル
価格が有利な方向に動いたときに、利食い注文が有効になる価格です。
//+------------------------------------------------------------------+ //| Return the Take Profit order level as a string | //+------------------------------------------------------------------+ string MqlTradeRequestTakeProfit(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="TP:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(req.tp!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.tp); /* Sample output: TP: 0.0 */ }
リクエスト価格との乖離
ポイント単位で指定される、リクエスト価格からの許容可能な最大偏差です。
//+------------------------------------------------------------------+ //| Return the maximum acceptable | //| deviation from the requested price | //+------------------------------------------------------------------+ string MqlTradeRequestDeviation(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Deviation:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.deviation); /* Sample output: Deviation: 5 */ }
注文タイプ
注文の種類です。値は、ENUM_ORDER_TYPE列挙値のいずれかです。
//+------------------------------------------------------------------+ //| Return the order type as a string | //+------------------------------------------------------------------+ string MqlTradeRequestType(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Type:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeDescription(req.type,ext_descr)); /* Sample output: Type: Buy Limit (Buy Limit pending order) */ }
注文処理タイプ
これは注文処理のタイプで、値はENUM_ORDER_TYPE_FILLING値のいずれかです。
//+------------------------------------------------------------------+ //| Return the order type by execution as a string | //+------------------------------------------------------------------+ string MqlTradeRequestTypeFilling(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Type filling:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeFillingDescription(req.type_filling,ext_descr)); /* Sample output: Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further) */ }
注文寿命タイプ
有効期限別の注文タイプで、値は、ENUM_ORDER_TYPE_TIME値のいずれかです。
//+------------------------------------------------------------------+ //| Return the order type by expiration time as a string | //+------------------------------------------------------------------+ string MqlTradeRequestTypeTime(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Type time:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeTimeDescription(req.type_time,ext_descr)); /* Sample output: Type time: Time GTC (Good till cancel order) */ }
注文有効期限
未決注文の有効期限 (ORDER_TIME_SPECIFIED型の注文用)。
//+------------------------------------------------------------------+ //| Return the order expiration time as a string | //+------------------------------------------------------------------+ string MqlTradeRequestExpiration(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Expiration:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(req.type_time==ORDER_TIME_SPECIFIED || req.type_time==ORDER_TIME_SPECIFIED_DAY ? (string)req.expiration : "0")); /* Sample output: Expiration: 0 */ }
注文へのコメント
//+------------------------------------------------------------------+ //| Return the order comment | //+------------------------------------------------------------------+ string MqlTradeRequestComment(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Comment:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,req.comment); /* Sample output: Comment: TestMqlTradeTransaction */ }
ポジションチケット
ポジションチケットです。ポジションを変更したり、閉じたりする際に入力され、明確に識別できるようにします。通常、ポジションを開いた注文のチケットと同じです。
//+------------------------------------------------------------------+ //| Return the position ticket as a string | //+------------------------------------------------------------------+ string MqlTradeRequestPosition(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Position:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.position); /* Sample output: Position: 1835982676 */ }
反対側ポジションのチケット
反対側のポジションのチケットです。ポジションを反対方向(同じ銘柄で建てたが反対方向)に決済するときに使用します。
//+------------------------------------------------------------------+ //| Return the opposite position ticket as a string | //+------------------------------------------------------------------+ string MqlTradeRequestPositionBy(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Position by:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.position_by); /* Sample output: Position by: 1835987626 */ }
使用例
異なるタイプの取引注文の場合、構造体フィールドは注文に応じて個別に入力されます。実行されるアクションに応じて構造体フィールドの説明をログに記録する関数と、ポジションの開閉や未決注文の設定/削除をおこなう取引関数を作成します。
次は、取引リクエスト明細を操作ログに表示する関数です。
//+------------------------------------------------------------------+ //| Display the trading request description in the journal | //+------------------------------------------------------------------+ void TradeRequestPrint(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false) { //--- Get execution type by symbol ENUM_SYMBOL_TRADE_EXECUTION exemode=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(req.symbol,SYMBOL_TRADE_EXEMODE); //--- Header PrintFormat("Request %s:",TradeActionDescription(req.action,ext_descr)); //--- Place an order for an instant deal with the specified parameters (set a market order) if(req.action==TRADE_ACTION_DEAL) { //--- Depending on the transaction mode switch(exemode) { //--- Trade order to open a position in the Request Execution mode //--- Trade order to open a position in the Instant Execution mode case SYMBOL_TRADE_EXECUTION_REQUEST : case SYMBOL_TRADE_EXECUTION_INSTANT : Print(MqlTradeRequestSymbol(req,header_width,indent)); Print(MqlTradeRequestVolume(req,header_width,indent)); Print(MqlTradeRequestPrice(req,header_width,indent)); if(req.position==0) // Only for opening a position Print(MqlTradeRequestStopLoss(req,header_width,indent)); if(req.position==0) // Only for opening a position Print(MqlTradeRequestTakeProfit(req,header_width,indent)); Print(MqlTradeRequestDeviation(req,header_width,indent)); Print(MqlTradeRequestType(req,header_width,indent,ext_descr)); Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr)); Print(MqlTradeRequestMagic(req,header_width,indent)); if(req.position==0) // Only for opening a position Print(MqlTradeRequestComment(req,header_width,indent)); //--- Closing if(req.position!=0) Print(MqlTradeRequestPosition(req,header_width,indent)); break; //--- Trade order to open a position in the Market Execution mode //--- Trade order to open a position in the Exchange Execution mode case SYMBOL_TRADE_EXECUTION_MARKET : case SYMBOL_TRADE_EXECUTION_EXCHANGE : Print(MqlTradeRequestSymbol(req,header_width,indent)); Print(MqlTradeRequestVolume(req,header_width,indent)); Print(MqlTradeRequestType(req,header_width,indent,ext_descr)); Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr)); Print(MqlTradeRequestMagic(req,header_width,indent)); if(req.position==0) // Only for opening a position Print(MqlTradeRequestComment(req,header_width,indent)); //--- Closing if(req.position!=0) Print(MqlTradeRequestPosition(req,header_width,indent)); break; default: break; } } //--- Trading order to close a position by an opposite one if(req.action==TRADE_ACTION_CLOSE_BY) { Print(MqlTradeRequestSymbol(req,header_width,indent)); Print(MqlTradeRequestPosition(req,header_width,indent)); Print(MqlTradeRequestMagic(req,header_width,indent)); Print(MqlTradeRequestComment(req,header_width,indent)); Print(MqlTradeRequestPositionBy(req,header_width,indent)); } //--- Trading order to modify StopLoss and/or TakeProfit levels if(req.action==TRADE_ACTION_SLTP) { Print(MqlTradeRequestSymbol(req,header_width,indent)); Print(MqlTradeRequestStopLoss(req,header_width,indent)); Print(MqlTradeRequestTakeProfit(req,header_width,indent)); Print(MqlTradeRequestPosition(req,header_width,indent)); } //--- Trading order to place a pending order if(req.action==TRADE_ACTION_PENDING) { Print(MqlTradeRequestSymbol(req,header_width,indent)); Print(MqlTradeRequestVolume(req,header_width,indent)); Print(MqlTradeRequestPrice(req,header_width,indent)); if(req.type==ORDER_TYPE_BUY_STOP_LIMIT || req.type==ORDER_TYPE_SELL_STOP_LIMIT) Print(MqlTradeRequestStopLimit(req,header_width,indent)); Print(MqlTradeRequestStopLoss(req,header_width,indent)); Print(MqlTradeRequestTakeProfit(req,header_width,indent)); Print(MqlTradeRequestType(req,header_width,indent,ext_descr)); Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr)); Print(MqlTradeRequestTypeTime(req,header_width,indent,ext_descr)); Print(MqlTradeRequestExpiration(req,header_width,indent)); Print(MqlTradeRequestMagic(req,header_width,indent)); Print(MqlTradeRequestComment(req,header_width,indent)); } //--- Trading order to modify the price levels of a pending order if(req.action==TRADE_ACTION_MODIFY) { Print(MqlTradeRequestOrder(req,header_width,indent)); Print(MqlTradeRequestPrice(req,header_width,indent)); if(req.stoplimit!=0) Print(MqlTradeRequestStopLimit(req,header_width,indent)); Print(MqlTradeRequestStopLoss(req,header_width,indent)); Print(MqlTradeRequestTakeProfit(req,header_width,indent)); Print(MqlTradeRequestTypeTime(req,header_width,indent,ext_descr)); Print(MqlTradeRequestExpiration(req,header_width,indent)); } //--- Trading order to remove a pending order if(req.action==TRADE_ACTION_REMOVE) { Print(MqlTradeRequestOrder(req,header_width,indent)); } /* Sample output: Request Pending (Place a trade order for the execution under specified conditions (pending order)): Symbol: EURUSD Volume: 0.10 Price: 1.09586 SL: 0.0 TP: 0.0 Type: Buy Limit (Buy Limit pending order) Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further) Type time: Time GTC (Good till cancel order) Expiration: 0 Magic: 1024 Comment: TestMqlTradeTransaction */ }
OpenBuyで買いポジションを建てる
//+------------------------------------------------------------------+ //| Open Buy position | //+------------------------------------------------------------------+ bool OpenBuy(const string symbol,const double lots,const uint magic,const ulong deviation=5,const string comment="") { //--- Set a symbol for a request string symbol_name=(symbol==NULL ? Symbol() : symbol); //--- Declare and initialize the request and result structures MqlTradeRequest request={}; MqlTradeResult result={}; //--- Get the normalized price double price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK),(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS)); //--- request parameters request.action = TRADE_ACTION_DEAL; // trading operation type request.symbol = symbol_name; // symbol request.volume = lots; // position volume request.type = ORDER_TYPE_BUY; // order type request.price = price; // open price request.deviation = deviation; // allowed deviation from the price request.magic = magic; // order MagicNumber request.comment = comment; // Order comment //--- If failed to send a request, inform of that and return 'false' if(!OrderSend(request,result)) { PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__, TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true) ); return false; } //--- OrderSend OK, return 'true' return true; }
OpenSellで売りポジションを建てる
//+------------------------------------------------------------------+ //| Open a Sell position | //+------------------------------------------------------------------+ bool OpenSell(const string symbol,const double lots,const uint magic,const ulong deviation=5,const string comment="") { //--- Set a symbol for a request string symbol_name=(symbol==NULL ? Symbol() : symbol); //--- Declare and initialize the request and result structures MqlTradeRequest request={}; MqlTradeResult result={}; //--- Get the normalized price double price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID),(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS)); //--- request parameters request.action = TRADE_ACTION_DEAL; // trading operation type request.symbol = symbol_name; // symbol request.volume = lots; // position volume request.type = ORDER_TYPE_SELL; // order type request.price = price; // open price request.deviation = deviation; // allowed deviation from the price request.magic = magic; // order MagicNumber request.comment = comment; // Order comment //--- If failed to send a request, inform of that and return 'false' if(!OrderSend(request,result)) { PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__, TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true) ); return false; } //--- OrderSend OK, return 'true' return true; }
ClosePositionで指定したポジションを閉じる
//+------------------------------------------------------------------+ //| Close position by ticket | //+------------------------------------------------------------------+ bool ClosePosition(const ulong ticket,const ulong deviation=5) { //--- Declare request and result structures MqlTradeRequest request; MqlTradeResult result; //--- If failed to select a position by ticket, inform of the error and leave ResetLastError(); if(!PositionSelectByTicket(ticket)) { Print("PositionSelectByTicket failed, error: ",(string)GetLastError()); return false; } //--- Get the data on the closed position string position_symbol=PositionGetString(POSITION_SYMBOL); // symbol int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal places double volume=PositionGetDouble(POSITION_VOLUME); // position volume ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // position type ulong magic=PositionGetInteger(POSITION_MAGIC); // position MagicNumber //--- Set request and result values to zero ZeroMemory(request); ZeroMemory(result); //--- Set operation parameters request.action = TRADE_ACTION_DEAL; // trading operation type request.position = ticket; // position ticket request.symbol = position_symbol; // symbol request.volume = volume; // position volume request.deviation = deviation; // allowed deviation from the price request.magic = magic; // position MagicNumber //--- Set order price and type depending on the position type if(type==POSITION_TYPE_BUY) { request.price=NormalizeDouble(SymbolInfoDouble(position_symbol,SYMBOL_BID),digits); request.type =ORDER_TYPE_SELL; } else { request.price=NormalizeDouble(SymbolInfoDouble(position_symbol,SYMBOL_ASK),digits); request.type =ORDER_TYPE_BUY; } //--- If failed to send a request, inform of that and return 'false' if(!OrderSend(request,result)) { PrintFormat("%s: OrderSend for %s %s #%llu error: %s",__FUNCTION__, TradeActionDescription(request.action),OrderTypeDescription(request.type),ticket,RetcodeDescription(result.retcode,true) ); return false; } //--- OrderSend OK, return 'true' return true; }
ClosePositionsAllですべてのポジションを閉じる
//+------------------------------------------------------------------+ //| Close all positions on a symbol | //+------------------------------------------------------------------+ uint ClosePositionsAll(const string symbol,const ulong magic=0) { //--- Declare the variable for storing the result and the number of closed positions bool res=true; uint num=0; //--- iterate over open positions int total=PositionsTotal(); // number of open positions for(int i=total-1; i>=0; i--) { ulong position_ticket=PositionGetTicket(i); // position ticket if(position_ticket==0) continue; if(PositionGetInteger(POSITION_MAGIC)!=magic) continue; //--- If MagicNumber is not specified (zero) or position magic number matches the specified one if(magic==0 || PositionGetInteger(POSITION_MAGIC)==magic) { //--- if the position symbol matches the one passed or NULL is passed, close the position on the ticket if(symbol==NULL || PositionGetString(POSITION_SYMBOL)==symbol) { //--- Get the result of closing a position on a ticket and increase the counter of closed positions if successful res &=ClosePosition(position_ticket); if(res) num++; } } } if(!res) PrintFormat("%s: Not all positions were able to close without errors",__FUNCTION__); return num; }
SetPendingで指値注文を出す
//+------------------------------------------------------------------+ //| Place a specified pending order | //+------------------------------------------------------------------+ bool SetPending(const string symbol,const ENUM_ORDER_TYPE order_type,const double lots,const uint magic,const int distance,const int stoplimit=0,const string comment="") { //--- Set a symbol for a request string symbol_name=(symbol==NULL ? Symbol() : symbol); //--- Declare and initialize the request and result structures MqlTradeRequest request={}; MqlTradeResult result={}; //--- Set operation parameters request.action = TRADE_ACTION_PENDING; // trading operation type request.type = order_type; // order type request.symbol = symbol_name; // symbol request.volume = lots; // volume request.magic = magic; // order MagicNumber request.comment = comment; // Order comment //--- Get Point and Digits double point=SymbolInfoDouble(symbol_name,SYMBOL_POINT); int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS); //--- Calculate the distance from the price depending on the order type //--- Buy order if(order_type==ORDER_TYPE_BUY_STOP) request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)+distance*point,digits); // normalized setting price if(order_type==ORDER_TYPE_BUY_LIMIT) request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)-distance*point,digits); // normalized setting price if(order_type==ORDER_TYPE_BUY_STOP_LIMIT) { request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)+distance*point,digits); // normalized Stop order trigger price request.stoplimit=NormalizeDouble(request.price-stoplimit*point,digits); // normalized Limit order setting price } //--- Sell order if(order_type==ORDER_TYPE_SELL_STOP) request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)-distance*point,digits); // normalized setting price if(order_type==ORDER_TYPE_SELL_LIMIT) request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)+distance*point,digits); // normalized setting price if(order_type==ORDER_TYPE_SELL_STOP_LIMIT) { request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)-distance*point,digits); // normalized Stop order trigger price request.stoplimit=NormalizeDouble(request.price+stoplimit*point,digits); // normalized Limit order setting price } //--- If failed to send a request, inform of that and return 'false' if(!OrderSend(request,result)) { PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__, TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true) ); return false; } //--- OrderSend OK, return 'true' return true; }
上記で紹介した関数を基に、未決注文の特定のタイプを設定する関数を作成することができます。
SetBuyStopで買い注文を設定する
//+------------------------------------------------------------------+ //| Place BuyStop pending order | //+------------------------------------------------------------------+ bool SetBuyStop(const string symbol,const double lots,const uint magic,const int distance,const string comment="") { //--- Call the SetPending function with BuyStop parameters return SetPending(symbol,ORDER_TYPE_BUY_STOP,lots,magic,distance,0,comment); }
SetBuyLimitで買い指値注文を設定する
//+------------------------------------------------------------------+ //| Place BuyLimit pending order | //+------------------------------------------------------------------+ bool SetBuyLimit(const string symbol,const double lots,const uint magic,const int distance,const string comment="") { //--- Call the SetPending function with BuyLimit parameters return SetPending(symbol,ORDER_TYPE_BUY_LIMIT,lots,magic,distance,0,comment); }
SetBuyStopLimitでBuyStopLimit注文を設定する
//+------------------------------------------------------------------+ //| Place BuyStopLimit pending order | //+------------------------------------------------------------------+ bool SetBuyStopLimit(const string symbol,const double lots,const uint magic,const int distance,const int stoplimit,const string comment="") { //--- Call the SetPending function with BuyStopLimit parameters return SetPending(symbol,ORDER_TYPE_BUY_STOP_LIMIT,lots,magic,distance,stoplimit,comment); }
SetSellStopで売り逆指値注文を設定する
//+------------------------------------------------------------------+ //| Place SellStop pending order | //+------------------------------------------------------------------+ bool SetSellSellStop(const string symbol,const double lots,const uint magic,const int distance,const string comment="") { //--- Call the SetPending function with SellStop parameters return SetPending(symbol,ORDER_TYPE_SELL_STOP,lots,magic,distance,0,comment); }
SetSellLimitで売り指値注文を設定する
//+------------------------------------------------------------------+ //| Place SellLimit pending order | //+------------------------------------------------------------------+ bool SetSellLimit(const string symbol,const double lots,const uint magic,const int distance,const string comment="") { //--- Call the SetPending function with SellLimit parameters return SetPending(symbol,ORDER_TYPE_SELL_LIMIT,lots,magic,distance,0,comment); }
SetSellStopLimitでSellStopLimit注文を設定する
//+------------------------------------------------------------------+ //| Place SellStopLimit pending order | //+------------------------------------------------------------------+ bool SetSellStopLimit(const string symbol,const double lots,const uint magic,const int distance,const int stoplimit,const string comment="") { //--- Call the SetPending function with SellStopLimit parameters return SetPending(symbol,ORDER_TYPE_SELL_STOP_LIMIT,lots,magic,distance,stoplimit,comment); }
DeleteOrderで指定した未決注文を削除する
//+------------------------------------------------------------------+ //| Delete a pending order by ticket | //+------------------------------------------------------------------+ bool DeleteOrder(const ulong ticket) { //--- declare and initialize the trade request and result MqlTradeRequest request={}; MqlTradeResult result={}; ResetLastError(); //--- If failed to select an order by ticket, inform of the error and leave if(!OrderSelect(ticket)) { PrintFormat("%s: OrderSelect failed, error: %d",__FUNCTION__,GetLastError()); return false; } //--- Set request and result values to zero ZeroMemory(request); ZeroMemory(result); //--- Set operation parameters request.action=TRADE_ACTION_REMOVE; // trading operation type request.order = ticket; // order ticket //--- If failed to send a request, inform of that and return 'false' if(!OrderSend(request,result)) { PrintFormat("%s: OrderSend for %s %s #%llu error: %s",__FUNCTION__, TradeActionDescription(request.action),OrderTypeDescription((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE)),ticket,RetcodeDescription(result.retcode,true) ); return false; } //--- OrderSend OK, return 'true' return true; }
DeleteOrdersAllで未決注文をすべて削除する
//+------------------------------------------------------------------+ //| Delete all pending orders by symbol | //+------------------------------------------------------------------+ uint DeleteOrdersAll(const string symbol,const long magic=WRONG_VALUE) { //--- Declare the variable for storing the result and the number of removed orders bool res=true; uint num=0; //--- iterate over all placed pending orders int total=OrdersTotal(); // number of pending orders for(int i=total-1; i>=0; i--) { ulong order_ticket=OrderGetTicket(i); // order ticket if(order_ticket==0) continue; //--- If MagicNumber is not specified (zero) or order magic number matches the specified one if(magic==WRONG_VALUE || OrderGetInteger(ORDER_MAGIC)==magic) { //--- if the order symbol matches the one passed or NULL is passed, remove order by ticket if(symbol==NULL || OrderGetString(ORDER_SYMBOL)==symbol) { res &=DeleteOrder(order_ticket); if(res) num++; } } } if(!res) PrintFormat("%s: Not all orders were able to close without errors",__FUNCTION__); return num; }
上記で紹介した取引関数はすべて単純な例関数です。エラーコードやサーバーのリターンコードによってエラーを処理したり修正したりすることはありません。これらに基づいてこのような関数を実装することもできますが、この記事の範囲外です。
取引注文の構造体に入力した後、その有効性を確認することができます。これは、OrderCheck()関数を使用しておこなうことができます。この関数は、必要な取引操作を完了するのに十分な資金を確認します。
資金が不足していたり、パラメータが正しく入力されていなかったりした場合、この関数はfalseを返します。構造体(ポインタ)の基本的な確認が成功した場合はtrueを返しますが、これは、要求された取引操作が正常に実行されることを意味するものではありません 。関数実行結果の詳細な説明を得るためには、結果 構造体フィールドを分析する必要があります。
確認結果はMqlTradeCheckResult構造体のフィールドに配置されます。構造体フィールドの説明を表示するために必要な関数を実装しましょう。
準備されたリクエストを送信前に確認するためのMqlTradeCheckResult構造体
取引サーバーにリクエストを送る前に、取引操作を確認することをお勧めします。確認は、確認されるリクエストとMqlTradeCheckResult構造型の変数を受け取るOrderCheck()関数によって実行されます。確認の結果は変数に設定されます。
struct MqlTradeCheckResult { uint retcode; // Response code double balance; // Balance after performing a deal double equity; // Equity after performing a deal double profit; // Floating profit double margin; // Margin requirements double margin_free; // Free margin double margin_level; // Margin level string comment; // Comment on the response code (error description) };
応答コード
リターンコード 取引操作を実行するすべての注文は、OrderSend()関数を使用してMqlTradeRequest取引リクエスト構造体として送信されます。関数の実行結果はMqlTradeResult構造体に格納されます。retcode フィールドには取引サーバーのリターンコードが含まれています。取引注文を確認した後、応答コードをMqlTradeCheckResult構造体のretcodeフィールドで読み取ることができます。
//+------------------------------------------------------------------+ //| Return the response code as a string | //+------------------------------------------------------------------+ string MqlTradeCheckResultRetcode(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Retcode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,RetcodeDescription(result.retcode,ext_descr)); /* Sample output: Retcode: OK (0) */ }
取引実行後の残高
取引操作を実行した後の残高です。
//+----------------------------------------------------------------------+ //| Returns the balance as a string after a trade operation is performed | //+----------------------------------------------------------------------+ string MqlTradeCheckResultBalance(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Balance:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the account currency string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Get the number of decimal places int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.balance,currency); /* Sample output: Balance: 10016.80 USD */ }
取引実行後のエクイティ
取引操作を実行した後の株式価値です。
//+--------------------------------------------------------------------+ //| Return the equity as a string after a trade operation is performed | //+--------------------------------------------------------------------+ string MqlTradeCheckResultEquity(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Equity:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the account currency string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Get the number of decimal places int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.equity,currency); /* Sample output: Equity: 10016.80 USD */ }
浮動利益
取引操作を実行した後の浮動利益です。
//+---------------------------------------------------------------------------+ //|Return the floating profit as a string after a trade operation is performed| //+---------------------------------------------------------------------------+ string MqlTradeCheckResultProfit(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Profit:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the account currency string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Get the number of decimal places int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.profit,currency); /* Sample output: Profit: 0.00 USD */ }
必要証拠金
必要な取引操作に必要な証拠金の額.です。
//+------------------------------------------------------------------+ //| Return the margin, | //| required for the necessary trading operation, as a string | //+------------------------------------------------------------------+ string MqlTradeCheckResultMargin(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the account currency string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Get the number of decimal places int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.margin,currency); /* Sample output: Margin: 128.66 USD */ }
余剰証拠金
取引をおこなった後に残る資本の価値です。
//+------------------------------------------------------------------+ //| Return the value of equity | //| to be left after conducting a trading operation as a string | //+------------------------------------------------------------------+ string MqlTradeCheckResultMarginFree(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin free:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the account currency string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Get the number of decimal places int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.margin_free,currency); /* Sample output: Margin free: 9888.14 USD */ }
証拠金レベル
必要な取引操作を完了した後に設定される証拠金レベルです。
//+-----------------------------------------------------------------------+ //| Return the margin level | //| to be set after completing the required trading operation as a string | //+-----------------------------------------------------------------------+ string MqlTradeCheckResultMarginLevel(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin level:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.2f %%",indent,"",w,header,result.margin_level); /* Sample output: Margin level: 7785.48 % */ }
応答コードへのコメント
応答コード、エラーの説明についてのコメントです。
//+------------------------------------------------------------------+ //| Return comment on the response code, error description | //+------------------------------------------------------------------+ string MqlTradeCheckResultComment(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Comment:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,result.comment); /* Sample output: Comment: Done */ }
使用例
以下は、操作ログ内のすべての MqlTradeCheckResult構造体フィールドを表示する関数です。
//+------------------------------------------------------------------+ //| Display the MqlTradeCheckResult structure fields in the journal | //| as a result of OrderCheck | //+------------------------------------------------------------------+ void OrderCheckResultPrint(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0,bool ext_descr=false) { Print("OrderCheck result:"); Print(MqlTradeCheckResultRetcode(result,header_width,indent,ext_descr)); Print(MqlTradeCheckResultBalance(result,header_width,indent)); Print(MqlTradeCheckResultEquity(result,header_width,indent)); Print(MqlTradeCheckResultProfit(result,header_width,indent)); Print(MqlTradeCheckResultMargin(result,header_width,indent)); Print(MqlTradeCheckResultMarginFree(result,header_width,indent)); Print(MqlTradeCheckResultMarginLevel(result,header_width,indent)); Print(MqlTradeCheckResultComment(result,header_width,indent)); /* Sample output: OrderCheck result: Retcode: Undefined (0) Balance: 10016.80 USD Equity: 10016.80 USD Profit: 0.00 USD Margin: 128.66 USD Margin free: 9888.14 USD Margin level: 7785.48 % Comment: Done */ }
完了した取引注文を確認し、エラーを受信した場合は、完了したMqlTradeCheckResult構造体を操作ログに送信してエラーを分析できます。
OrderSend()関数によって送信されたリクエストに対するサーバーの応答を持つMqlTradeResult構造体
取引システムに注文を出すための取引リクエストに応答して、取引サーバーは、特別なMqlTradeResult構造体の形で取引リクエストの処理結果に関する情報を含むデータを返します。
struct MqlTradeResult { uint retcode; // Operation result code ulong deal; // Deal ticket if executed ulong order; // Order ticket if placed double volume; // Deal volume confirmed by a broker double price; // Deal price confirmed by a broker double bid; // The current market Bid price (requote price) double ask; // The current market Ask price (requote price) string comment; // Broker comment to operation (by default, it is filled by the trade server return code description) uint request_id; // Request ID set by the terminal when sending int retcode_external; // Response code of an external trading system };
取引操作の結果は、MqlTradeResult型の変数に返され、これは、取引操作をおこなうためのOrderSend()関数の2番目のパラメータとして渡されます。
構造体フィールドの説明を表示するために、以下の関数を実装します。
動作結果コード
//+------------------------------------------------------------------+ //| Return the operation result code as a string | //+------------------------------------------------------------------+ string MqlTradeResultRetcode(const MqlTradeResult &result,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Retcode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,RetcodeDescription(result.retcode,ext_descr)); /* Sample output: Retcode: 10009 DONE (Request completed) */ }
取引チケット
//+------------------------------------------------------------------+ //| Return the deal ticket if it is completed | //+------------------------------------------------------------------+ string MqlTradeResultDeal(const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Deal:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,result.deal); /* Sample output: Deal: 0 */ }
注文チケット
//+------------------------------------------------------------------+ //| Return the order ticket as a string if the order is set | //+------------------------------------------------------------------+ string MqlTradeResultOrder(const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Order:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,result.order); /* Sample output: Order: 1821552382 */ }
取引量
//+------------------------------------------------------------------+ //| Return the deal volume confirmed by a broker as a string | //+------------------------------------------------------------------+ string MqlTradeResultVolume(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places in the lot value int dg=(int)ceil(fabs(log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP)))); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.volume); /* Sample output: Volume: 0.10 */ }
取引価格
//+------------------------------------------------------------------+ //| Return a deal price, confirmed by a broker, as a string | //+------------------------------------------------------------------+ string MqlTradeResultPrice(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(result.price!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.price); /* Sample output: Price: 0.0 */ }
現在のBid市場価格
//+------------------------------------------------------------------+ //| Return the current market Bid price as a string | //+------------------------------------------------------------------+ string MqlTradeResultBid(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Bid:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(result.bid!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.bid); /* Sample output: Bid: 0.0 */ }
現在のAsk市場価格
//+------------------------------------------------------------------+ //| Return the current market Ask price as a string | //+------------------------------------------------------------------+ string MqlTradeResultAsk(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Ask:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places int dg=(result.ask!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.ask); /* Sample output: Ask: 0.0 */ }
未決済注文を発注する際、構造内のBidとAskの価格は空のままです。注文がリクオートによって受理されなかった場合、注文が発注を拒否された時点の価格をBidとAskのフィールドで見ることができます。
ブローカーの取引コメント
//+------------------------------------------------------------------+ //| Return broker's comment on a deal | //+------------------------------------------------------------------+ string MqlTradeResultComment(const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Comment:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,result.comment); /* Sample output: Comment: Request executed */ }
リクエストID
//+------------------------------------------------------------------+ //| Return request ID as a string | //+------------------------------------------------------------------+ string MqlTradeResultRequestID(const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Request ID:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-lu",indent,"",w,header,result.request_id); /* Sample output: Request ID: 3768213261 */ }
サーバーへの送信時に取引端末がrequest_id を設定するのは、主にOrderSendAsync()非同期関数と連携するためです。この識別子により、実行されたアクション(OrderSendまたはOrderSendAsync関数の呼び出し)とOnTradeTransaction()に送信されたアクションの結果を関連付けることができます。
外部取引システム応答コード
//+-------------------------------------------------------------------+ //| Return the response code of an external trading system as a string| //+-------------------------------------------------------------------+ string MqlTradeResultRetcodeExternal(const MqlTradeResult &result,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Retcode External:"; uint w=(header_width==0 ? header.Length()+1 : header_width-1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%- ld",indent,"",w,header,result.retcode_external); /* Sample output: Retcode External: 0 */ }
使用例
以下は、取引リクエスト結果構造のすべてのフィールドを操作ログに表示する関数です。
//+------------------------------------------------------------------+ //| Display MqlTradeResult structure fields in the journal | //| as a result of a trade request | //+------------------------------------------------------------------+ void TradeResultPrint(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0,bool ext_descr=false) { string symbol_name=(symbol==NULL ? Symbol() : symbol); Print("OrderSend result:"); Print(MqlTradeResultRetcode(result,header_width,indent,ext_descr)); Print(MqlTradeResultDeal(result,header_width,indent)); Print(MqlTradeResultOrder(result,header_width,indent)); Print(MqlTradeResultVolume(symbol_name,result,header_width,indent)); Print(MqlTradeResultPrice(symbol_name,result,header_width,indent)); Print(MqlTradeResultBid(symbol_name,result,header_width,indent)); Print(MqlTradeResultAsk(symbol_name,result,header_width,indent)); Print(MqlTradeResultComment(result,header_width,indent)); Print(MqlTradeResultRequestID(result,header_width,indent)); Print(MqlTradeResultRetcodeExternal(result,header_width,indent)); /* Sample output: OrderSend result: Retcode: 10009 DONE (Request completed) Deal: 0 Order: 1821671230 Volume: 0.10 Price: 0.0 Bid: 0.0 Ask: 0.0 Comment: Request executed Request ID: 3768213265 Retcode External: 0 */ }
MqlTradeTransaction構造体と取引トランザクションの説明
取引口座で特定のアクションを実行した結果、その状態が変化します。これらのアクションには以下が含まれます。
- OrderSend関数およびOrderSendAsync関数を使用した、クライアント端末の任意のMQL5アプリケーションによる取引リクエストの送信とその後の実行
- 端末のグラフィカルインターフェースを通じた取引リクエストの送信とその後の実行
- サーバー上での未決注文と逆指値注文のトリガー
- 取引サーバー側での操作の実行
これらの行動の結果、口座に対して以下の取引トランザクションがおこなわれます。
- 取引リクエストの処理
- 未決済注文の変更
- 注文履歴の変更
- 取引履歴の変更
- ポジションの変更
例えば、成行買い注文を送信すると、それが処理され、対応する買い注文が口座に作成され、注文が執行され、未決済の注文リストから削除され、注文履歴に追加されます。その後、対応する取引が履歴に追加され、新しいポジションが作成されます。これらの行為はすべて取引トランザクションです。
MQL5は、口座に適用された取引トランザクションを受信するOnTradeTransaction()ハンドラを備えています。このハンドラの最初のパラメータは、取引トランザクションを記述するMqlTradeTransaction構造体を受け取ります。
struct MqlTradeTransaction { ulong deal; // Deal ticket ulong order; // Order ticket string symbol; // Symbol name ENUM_TRADE_TRANSACTION_TYPE type; // Trading transaction type ENUM_ORDER_TYPE order_type; // Order type ENUM_ORDER_STATE order_state; // Order state ENUM_DEAL_TYPE deal_type; // Deal type ENUM_ORDER_TYPE_TIME time_type; // Order lifetime type datetime time_expiration; // Order expiration time double price; // Price double price_trigger; // Stop limit order trigger price double price_sl; // Stop Loss level double price_tp; // Take Profit level double volume; // Volume in lots ulong position; // Position ticket ulong position_by; // Opposite position ticket };
すべての構造体フィールドの説明を返すために、以下の関数を実装してみましょう。
取引チケット
//+------------------------------------------------------------------+ //| Return the deal ticket as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionDeal(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Deal:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.deal); /* Sample output: Deal: 0 */ }
注文チケット
//+------------------------------------------------------------------+ //| Return the order ticket as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionOrder(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Order:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.order); /* Sample output: Order: 1825990224 */ }
取引商品名
取引が実行された取引銘柄の名前です。
//+------------------------------------------------------------------+ //| Return an order symbol as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionSymbol(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Symbol:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,trans.symbol); /* Sample output: Symbol: EURUSD */ }
取引トランザクションタイプ
取引トランザクションの種類です。値はENUM_TRADE_TRANSACTION_TYPE列挙値のいずれかです。
//+------------------------------------------------------------------+ //| Return the trading transaction type as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Type:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,TradeTransactionTypeDescription(trans.type,ext_descr)); /* Sample output: Type: Order delete (Removing an order from the list of the open ones) */ }
注文タイプ
取引注文の種類です。値は、ENUM_ORDER_TYPE列挙値の1つです。
//+------------------------------------------------------------------+ //| Return the order type as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionOrderType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Declare variables to indicate transaction affiliation bool trans_req=false; // Request bool trans_order=false; // Order bool trans_deal=false; // Deal bool trans_pos=false; // Position //--- Set transaction affiliation SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Order type:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderTypeDescription(trans.order_type,ext_descr) : "0")); /* Sample output: Order type: Sell Limit (Sell Limit pending order) */ }
この関数は、取引トランザクションの所属を決定します。トランザクションが注文で実行された場合は、そのタイプが返され、そうでない場合は0が返されます。
注文状況
取引注文の状況です。値はENUM_ORDER_STATE列挙値のいずれかです。
//+------------------------------------------------------------------+ //| Return the order status as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionOrderState(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Declare variables to indicate transaction affiliation bool trans_req=false; // Request bool trans_order=false; // Order bool trans_deal=false; // Deal bool trans_pos=false; // Position //--- Set transaction affiliation SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Order state:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderStateDescription(trans.order_state,ext_descr) : "0")); /* Sample output: Order state: Started (Order checked, but not yet accepted by broker) */ }
この関数は、取引トランザクションの所属を決定します。トランザクションが注文で実行された場合は、そのステータスが返され、そうでない場合は0が返されます。
取引タイプ
取引の種類です。値はENUM_DEAL_TYPE列挙値のいずれかです。
//+------------------------------------------------------------------+ //| Return the deal type as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionDealType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Declare variables to indicate transaction affiliation bool trans_req=false; // Request bool trans_order=false; // Order bool trans_deal=false; // Deal bool trans_pos=false; // Position //--- Set transaction affiliation SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Deal type:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_deal || trans_pos ? DealTypeDescription(trans.deal_type,ext_descr) : "0")); /* Sample output: Deal type: Buy */ }
この関数は、取引トランザクションの所属を決定します。トランザクションが取引で実行された場合はそのタイプが返され、そうでない場合は0が返されます。
注文寿命タイプ
執行による注文の種類です。値は、ENUM_ORDER_TYPE_TIME値のいずれかです。
//+------------------------------------------------------------------+ //| Return the order type by expiration time as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionTimeType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Declare variables to indicate transaction affiliation bool trans_req=false; // Request bool trans_order=false; // Order bool trans_deal=false; // Deal bool trans_pos=false; // Position //--- Set transaction affiliation SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Time type:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderTypeTimeDescription(trans.time_type,ext_descr) : "0")); /* Sample output: Order type time: Time GTC (Good till cancel order) */ }
この関数は、取引トランザクションの所属を決定します。トランザクションが注文で実行された場合は、その期限によるタイプが返され、そうでない場合は0が返されます。
注文有効期限
未決注文の有効期限です(ORDER_TIME_SPECIFIEDおよびORDER_TIME_SPECIFIED_DAY型の注文用)。
//+------------------------------------------------------------------+ //| Return the order expiration time as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionTimeExpiration(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Time expiration:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Set the expiration time as a string. If 0, then set 0 string tm=(trans.time_expiration==0 ? "0" : (string)trans.time_expiration); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-s",indent,"",w,header,tm); /* Sample output: Time expiration: 0 */ }
構造体フィールドの有効期限がゼロに設定されている場合は「0」を表示し、そうでない場合は有効期限を日付形式で表示します。もしフィールドの値がゼロかどうかを確認しなければ、ゼロの値は1970年01月01日00:00:00と表示され、注文の有効期限切れの美観を損ねます。
価格
価格です。取引トランザクションのタイプに応じて、注文、取引、ポジションとなります。
//+------------------------------------------------------------------+ //| Return the order/deal/position price as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionPrice(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Receive symbol's Digits. If the character is not specified, use 1 int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price); /* Sample output: Price: 1.10331 */ }
逆指値注文のトリガー価格
逆指値注文(ORDER_TYPE_BUY_STOP_LIMITおよびORDER_TYPE_SELL_STOP_LIMIT)の逆指値(トリガー価格)です。
//+------------------------------------------------------------------+ //| Return the stop limit order trigger price as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionPriceTrigger(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price trigger:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Receive symbol's Digits. If a symbol is not specified or there is no stop price, use 1 int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1); if(trans.price_trigger==0) dg=1; //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_trigger); /* Sample output: Price trigger: 0.0 */ }
逆指値注文価格が指定されていない場合は「0.0」、指定されていない場合は注文価格が表示されます。
ストップロスレベル
損切りの価格です。取引トランザクションのタイプに応じて、注文、取引、ポジションを指すことがあります。
//+------------------------------------------------------------------+ //| Return Stop Loss price as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionPriceSL(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price SL:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Receive symbol's Digits. If a symbol is not specified or a Stop Loss price is absent, use 1 int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1); if(trans.price_sl==0) dg=1; //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_sl); /* Sample output: Price SL: 0.0 */ }
損切りが設定されていない場合、「0.0」と表示されます。
テイクプロフィットレベル
利食い価格です。取引トランザクションのタイプに応じて、注文、取引、ポジションを指すことがあります。
//+------------------------------------------------------------------+ //| Return a Take Profit price as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionPriceTP(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Price TP:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Receive symbol's Digits. If a symbol is not specified or a Take Profit price is absent, use 1 int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1); if(trans.price_tp==0) dg=1; //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_tp); /* Sample output: Price TP: 0.0 */ }
利食い価格が設定されていない場合は、「0.0」を表示し、そうでない場合は、利食い価格を表示します。
ロット数
ロット数です。取引トランザクションのタイプに応じて、現在の注文量、取引量、ポジション量を定義することができます。
//+------------------------------------------------------------------+ //| Return volume in lots as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionVolume(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Volume:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Get the number of decimal places in the lot value. If the character is not specified, use 1 int dg=(trans.symbol!="" ? (int)ceil(fabs(log10(SymbolInfoDouble(trans.symbol,SYMBOL_VOLUME_STEP)))) : 1); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.volume); /* Sample output: Volume: 0.10 */ }
ポジションチケット
トランザクションによって影響を受けるポジションのチケットです。
//+------------------------------------------------------------------+ //| Return the position ticket as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionPosition(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Position:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.position); /* Sample output: Position: 0 */ }
反対側ポジションのチケット
反対側のポジションのチケットです。ポジションを反対方向(同じ銘柄で建てたが反対方向)に決済するときに使用します。
//+------------------------------------------------------------------+ //| Return the opposite position ticket as a string | //+------------------------------------------------------------------+ string MqlTradeTransactionPositionBy(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Position by:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Return the property value with a header having the required width and indentation return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.position_by); /* Sample output: Position by: 0 */ }
使用例
上記の関数を使用すると、操作ログ内のMqlTradeTransaction構造体のすべてのフィールドを表示できます。
//+------------------------------------------------------------------+ //| Display the MqlTradeTransaction structure fields in the journal | //+------------------------------------------------------------------+ void MqlTradeTransactionPrint(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false) { Print(MqlTradeTransactionDeal(trans,header_width,indent)); Print(MqlTradeTransactionOrder(trans,header_width,indent)); Print(MqlTradeTransactionSymbol(trans,header_width,indent)); Print(MqlTradeTransactionType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionOrderType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionOrderState(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionTimeType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionTimeExpiration(trans,header_width,indent)); Print(MqlTradeTransactionPrice(trans,header_width,indent)); Print(MqlTradeTransactionPriceTrigger(trans,header_width,indent)); Print(MqlTradeTransactionPriceSL(trans,header_width,indent)); Print(MqlTradeTransactionPriceTP(trans,header_width,indent)); Print(MqlTradeTransactionVolume(trans,header_width,indent)); Print(MqlTradeTransactionPosition(trans,header_width,indent)); Print(MqlTradeTransactionPositionBy(trans,header_width,indent)); /* Sample output: Deal: 0 Order: 1829189788 Symbol: EURUSD Type: Order add Order type: Buy Limit Order state: Started Deal type: 0 Time type: Time GTC Time expiration: 0 Price: 1.09861 Price trigger: 0.0 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Position: 0 Position by: 0 */ }
この関数は、操作ログ内のMqlTradeTransaction構造体のすべてのフィールドを表示します。構造体フィールドは、取引イベントごとに異なって入力されます。
受信したトランザクションの分析に不可欠なパラメータは、typeフィールドで指定されたそのタイプです。例えば、TRADE_TRANSACTION_REQUEST型のトランザクション(サーバーによる取引リクエストの処理結果が受信された)の場合、構造体にはタイプのフィールドしかありません。それ以外の分野は分析していません。この場合、 OnTradeTransaction()ハンドラに送信された requestパラメータとresultパラメータの2つを分析することができます。
取引操作のタイプを知ることで、取引口座の注文、ポジション、取引の現状を分析することを決定できます。端末からサーバーに送信される1つの取引リクエストは、複数の取引トランザクションを生成できることに留意してください。端末への到着順は保証されていません。
MqlTradeTransaction構造体は、取引トランザクションの型(ENUM_TRADE_TRANSACTION_TYPE)に応じて異なる方法で入力されます。
TRADE_TRANSACTION_ORDER_*およびTRADE_TRANSACTION_HISTORY_*
未決済注文(TRADE_TRANSACTION_ORDER_ADD、TRADE_TRANSACTION_ORDER_UPDATE、TRADE_TRANSACTION_ORDER_DELETE)および注文履歴(TRADE_TRANSACTION_HISTORY_ADD、TRADE_TRANSACTION_HISTORY_UPDATE、TRADE_TRANSACTION_HISTORY_DELETE)の処理に関連する取引トランザクションでは、MqlTradeTransaction 構造体に以下のフィールドが入力されます。
- order:注文チケット
- symbol:注文の金融商品の名前
- type:取引トランザクションの種類
- order_type:注文の種類
- orders_state:注文の現在の状態
- time_type:注文の実行タイプ
- time_expiration:注文の有効期限(ORDER_TIME_SPECIFIEDおよびORDER_TIME_SPECIFIED_DAY有効期限タイプを持つ注文用)
- price :クライアントが指定した注文価格
- price_trigger:逆指値注文のトリガーとなる逆指値(ORDER_TYPE_BUY_STOP_LIMITとORDER_TYPE_SELL_STOP_LIMITのみ)
- price_sl:ストップロス注文価格(注文で指定された場合に入力)
- price_tp:テイクプロフィット注文価格(注文で指定された場合に入力)
- volume :現在の注文数量(未約定)(初期注文量はHistoryOrders*関数を使用して注文履歴から求められる)
- position:注文執行の結果、オープン、変更、クローズされたポジションのチケット(成行注文のみで入力、TRADE_TRANSACTION_ORDER_ADDでは未入力)
- position_by:反対ポジションのチケット(クローズバイ注文でのみ入力)
TRADE_TRANSACTION_DEAL_*
以下のフィールドは、MqlTradeTransaction構造体の取引処理に関連する取引トランザクション(TRADE_TRANSACTION_DEAL_ADD、TRADE_TRANSACTION_DEAL_UPDATE、TRADE_TRANSACTION_DEAL_DELETE)に対して入力されます。
- deal:取引チケット
- order:取引に基づく注文のチケット
- symbol:取引の金融商品名
- type:取引トランザクションの種類
- deal_type :取引の種類
- price :取引価格
- price_sl :ストップロス価格(取引が基づいている注文で指定されている場合に入力)
- price_tp :テイクプロフィット価格(取引が基づいている注文で指定された場合に入力)
- volume :ロット単位の取引量
- position:取引執行の結果としてオープン、変更、クローズされたポジションのチケット
- position_by:反対ポジションのチケット(取引のみで入力)
TRADE_TRANSACTION_POSITION
以下のフィールドは、MqlTradeTransaction構造体において、取引の執行とは無関係なポジションの変更に関連する取引トランザクション(TRADE_TRANSACTION_POSITION)について入力されます。
- symbol :ポジションの金融商品名
- type:取引トランザクションの種類
- deal_type:ポジションタイプ(DEAL_TYPE_BUYまたはDEAL_TYPE_SELL)
- price :加重平均ポジション始値
- price_sl:ストップロス価格
- price_tp:テイクプロフィット価格
- volume:変更された場合のロット単位のポジションサイズ
- position:ポジションチケット
取引の結果、ポジションを変更(追加、変更、削除)することは、TRADE_TRANSACTION_POSITION トランザクションを伴いません。
TRADE_TRANSACTION_REQUEST
取引トランザクションのMqlTradeTransaction構造体には、取引リクエストがサーバーによって処理され、結果を受信したことを示すフィールドが1つだけ入力されます(TRADE_TRANSACTION_REQUEST)。
- type:取引トランザクションの種類
したがって、入ってくる取引イベントを考慮し、MqlTradeTransaction構造体の各トランザクションのタイプに必要なフィールドのみをログに記録する関数を作成することができます。
//+------------------------------------------------------------------+ //| Trading transaction informer | //+------------------------------------------------------------------+ void TradeTransactionInformer(const MqlTradeTransaction &trans,const MqlTradeRequest& request,const MqlTradeResult& result, const uint header_width=0,const uint indent=0,const bool ext_descr=false) { //--- Declare variables to indicate transaction affiliation bool trans_req=false; // Request bool trans_order=false; // Order bool trans_deal=false; // Deal bool trans_pos=false; // Position //--- Set transaction affiliation SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos); //--- Depending on the transaction affiliation, display descriptions of the corresponding structure fields //--- Trading request if(trans_req) { //--- Inform of the "trading request" transaction type and indicate that it is necessary to analyze the fields of the trading request and server response structure PrintFormat("Transaction %s\n%*sThe second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:", MqlTradeTransactionType(trans,0,0,true),indent,""); //--- Display the description of the trade request and the request result received from the server TradeRequestPrint(request,header_width,indent,ext_descr); TradeResultPrint(trans.symbol,result,header_width,indent,ext_descr); } //--- Otherwise, if the order/deal/position else { //--- Display the transaction type in the journal PrintFormat("Transaction %s",MqlTradeTransactionType(trans,0,0,true)); //--- Order if(trans_order) { Print(MqlTradeTransactionOrder(trans,header_width,indent)); Print(MqlTradeTransactionSymbol(trans,header_width,indent)); Print(MqlTradeTransactionOrderType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionOrderState(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionTimeType(trans,header_width,indent,ext_descr)); if(trans.time_type==ORDER_TIME_SPECIFIED || trans.time_type==ORDER_TIME_SPECIFIED_DAY) Print(MqlTradeTransactionTimeExpiration(trans,header_width,indent)); Print(MqlTradeTransactionPrice(trans,header_width,indent)); if(trans.order_type==ORDER_TYPE_BUY_STOP_LIMIT || trans.order_type==ORDER_TYPE_SELL_STOP_LIMIT) Print(MqlTradeTransactionPriceTrigger(trans,header_width,indent)); Print(MqlTradeTransactionPriceSL(trans,header_width,indent)); Print(MqlTradeTransactionPriceTP(trans,header_width,indent)); Print(MqlTradeTransactionVolume(trans,header_width,indent)); if(trans.type!=TRADE_TRANSACTION_ORDER_ADD && (trans.order_type==ORDER_TYPE_BUY || trans.order_type==ORDER_TYPE_SELL)) Print(MqlTradeTransactionPosition(trans,header_width,indent)); if(trans.order_type==ORDER_TYPE_CLOSE_BY) Print(MqlTradeTransactionPositionBy(trans,header_width,indent)); } //--- Deal if(trans_deal) { Print(MqlTradeTransactionDeal(trans,header_width,indent)); Print(MqlTradeTransactionOrder(trans,header_width,indent)); Print(MqlTradeTransactionSymbol(trans,header_width,indent)); Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionPrice(trans,header_width,indent)); Print(MqlTradeTransactionPriceSL(trans,header_width,indent)); Print(MqlTradeTransactionPriceTP(trans,header_width,indent)); Print(MqlTradeTransactionVolume(trans,header_width,indent)); Print(MqlTradeTransactionPosition(trans,header_width,indent)); } //--- Position if(trans_pos) { Print(MqlTradeTransactionSymbol(trans,header_width,indent)); Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr)); Print(MqlTradeTransactionPrice(trans,header_width,indent)); Print(MqlTradeTransactionPriceSL(trans,header_width,indent)); Print(MqlTradeTransactionPriceTP(trans,header_width,indent)); Print(MqlTradeTransactionVolume(trans,header_width,indent)); Print(MqlTradeTransactionPosition(trans,header_width,indent)); } } /* Sample output when setting the Sell Limit order: Transaction Type: Order add (Adding a new open order) Order: 1833072954 Symbol: EURUSD Order type: Sell Limit (Sell Limit pending order) Order state: Started (Order checked, but not yet accepted by broker) Time type: Time GTC (Good till cancel order) Price: 1.10516 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: Order update (Updating an open order) Order: 1833072954 Symbol: EURUSD Order type: Sell Limit (Sell Limit pending order) Order state: Placed (Order accepted) Time type: Time GTC (Good till cancel order) Price: 1.10516 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: Request (The trade request has been processed by a server and processing result has been received) The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data: Request Pending (Place a trade order for the execution under specified conditions (pending order)): Symbol: EURUSD Volume: 0.10 Price: 1.10516 SL: 0.0 TP: 0.0 Type: Sell Limit (Sell Limit pending order) Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further) Type time: Time GTC (Good till cancel order) Expiration: 0 Magic: 1024 Comment: TestMqlTradeTransaction OrderSend result: Retcode: 10009 DONE (Request completed) Deal: 0 Order: 1833072954 Volume: 0.10 Price: 0.0 Bid: 0.0 Ask: 0.0 Comment: Request ID: 3768213464 Retcode External: 0 //--- Here, when placing a Buy Limit pending order, we received three transactions: 1. Request - a request to place a pending order was accepted by the server and a response was received. To clarify information, it is necessary to analyze the fields of the MqlTradeRequest trade request structure and the MqlTradeResult server response – 'request' and 'result', respectively. 2. Adding a new pending order with the ticket #1829788294. Its status - Started. 3. Changing an open order with the ticket #1829788294. Its status changed from Started to Placed. The order of transactions is not respected, but this is clearly indicated in the Help section concerning the OnTradeTransaction handler: https://www.mql5.com/ja/docs/event_handlers/ontradetransaction. */ }
取引情報提供EA
上述した機能の動作を確認するために、すべての取引トランザクションとサーバーの応答を追跡し、受信した取引トランザクションの説明を操作ログに表示するEAを作成してみましょう。設定で選択したキーを押すことで、未決注文(BuyStop、SellStop、BuyLimit、SellLimit)や建玉(ポジション)(Buy、Sell)を設定できるように実装してみましょう。デフォルトでは、以下のキーが取引管理に割り当てられます。
注文タイプ | 開く/インストールするためのキーボードショートカット | 閉じる/削除ためのキーボードショートカット |
---|---|---|
買い | B | X |
売り | S | X |
買い逆指値 | Shift+B | Shift+X、Ctrl+Shift+X |
買い指値 | Ctrl+Shift+B | Shift+X、Ctrl+Shift+X |
売りストップ | Shift+S | Shift+X、Ctrl+Shift+X |
売り指値 | Ctrl+Shift+S | Shift+X、Ctrl+Shift+X |
キーは設定で自由に割り当てることができます。EAは自動的に大文字に変換します。買い、売り、手仕舞い(ポジション決済)/注文削除の3つのキーを設定できます。リクエスト内の未決注文のタイプを変更するための CtrlとShift Ctrlキーは、デフォルトで割り当てられており、変更することはできません。B'を押すと買いポジションが開き、シフトを押しながら'B'を押すと買い逆指値注文が設定されます。CtrlとShiftを同時に押しながら'B'を押すと、買い指値の未決注文が設定されます。S」を押すだけで売りポジションがオープンし、Ctrlキーを押し続けると売りストップと売りリミットが設定されます。すべての未決済ポジションを閉じるには、「X」ボタンを押します。シフトまたはCtrl+シフト(関係ありません)を押しながら「X」を押すと、すべての未決済注文が削除されます。
//+------------------------------------------------------------------+ //| TestMqlTradeTransaction.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //--- input parameters input double InpLots = 0.1; /* Lots */ // Requested volume input int InpMagic = 1024; /* Magic number */ // EA ID input int InpDistance = 300; /* Orders placement distance */ // Distance for setting pending orders input uint InpDeviation = 5; /* Price deviation */ // Allowed deviation from the price input string InpKeyBuy = "B"; /* Key to open Buy */ // Key to open a Buy position (with Shift - Stop, with Ctrl+Shift - Limit) input string InpKeySell = "S"; /* Key to open Sell */ // Key to open Sell (with Shift - Stop, with Ctrl+Shift - Limit) input string InpKeyClose = "X"; /* Key to close/delete */ // Key for closing a position (without control keys) or deleting an order (with Shift or Shift+Ctrl) //--- Global variables ushort key_buy; // Key to send a buy order ushort key_sell; // Key to send a sell order ushort key_close; // Key to close or delete //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Convert the text assigned to Buy to uppercase and get the code of the first character string tmp=InpKeyBuy; tmp.Upper(); key_buy=StringGetCharacter(tmp,0); //--- Convert the text assigned to Sell to uppercase and get the code of the first character tmp=InpKeySell; tmp.Upper(); key_sell=StringGetCharacter(tmp,0); //--- Convert the text assigned to Close to uppercase and get the code of the first character tmp=InpKeyClose; tmp.Upper(); key_close=StringGetCharacter(tmp,0); //--- If the keys assigned to Buy and Sell match, report this and exit with an error if(key_sell==key_buy) { PrintFormat("The key assigned to Sell ('%c') is the same as the key assigned to Buy ('%c')",key_sell,key_buy); return INIT_PARAMETERS_INCORRECT; } //--- If the keys assigned to Close and Buy match, report this and exit with an error if(key_close==key_buy) { PrintFormat("The key assigned to Close ('%c') is the same as the key assigned to Buy ('%c')",key_close,key_buy); return INIT_PARAMETERS_INCORRECT; } //--- If the keys assigned to Close and Sell match, report this and exit with an error if(key_close==key_sell) { PrintFormat("The key assigned to Close ('%c') is the same as the key assigned to Sell ('%c')",key_close,key_sell); return INIT_PARAMETERS_INCORRECT; } //--- Successful initialization. Display the assigned keys in the journal and return successful execution string kb="Key assigned to Buy: "; string ks="Key assigned to Sell: "; string kc="Key assigned to Close: "; PrintFormat("%-23s%c (key code %lu)\n%-23s%c (key code %lu)\n%-23s%c (key code %lu)",kb,key_buy,key_buy,ks,key_sell,key_sell,kc,key_close,key_close); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- If a key is pressed if(id==CHARTEVENT_KEYDOWN) { //--- If neither Ctrl nor Shift are held if(!IsCtrlKeyPressed() && !IsShiftKeyPressed()) { //--- If the button is assigned to the Buy position, open Buy if(lparam==key_buy) OpenBuy(NULL,InpLots,InpMagic,InpDeviation,"TestMqlTradeTransaction"); //--- If the button is assigned to the Sell position, open Sell if(lparam==key_sell) OpenSell(NULL,InpLots,InpMagic,InpDeviation,"TestMqlTradeTransaction"); //--- If the button is assigned to closing positions, close all positions if(lparam==key_close) ClosePositionsAll(Symbol()); } //--- If only Shift is held if(IsShiftKeyPressed() && !IsCtrlKeyPressed()) { //--- If the button is assigned to Buy order, open Buy Stop order if(lparam==key_buy) SetBuyStop(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction"); //--- If the button is assigned to Sell order, open Sell Stop order if(lparam==key_sell) SetSellSellStop(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction"); //--- If the button is assigned to delete orders, delete all orders if(lparam==key_close) DeleteOrdersAll(NULL); } //--- If Shift is held together with Ctrl if(IsShiftKeyPressed() && IsCtrlKeyPressed()) { //--- If the button is assigned to Buy order, open Buy Limit order if(lparam==key_buy) SetBuyLimit(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction"); //--- If the button is assigned to Sell order, open Sell Limit order if(lparam==key_sell) SetSellLimit(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction"); //--- If the button is assigned to delete orders, delete all orders if(lparam==key_close) DeleteOrdersAll(Symbol()); } } } //+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { //--- Set all incoming trade transactions to the journal TradeTransactionInformer(trans,request,result,18,2,true); }
注文の発注とポジションのオープンは、EAのOnChartEvent()ハンドラで実装されます。OnTradeTransaction()ハンドラで、上で説明したTradeTransactionInformer()関数を呼び出します。操作ログの各入力トランザクションが表示されます。EAはその作業において、記事で取り上げたすべての関数を使用するので、エラーなくコンパイルするためには、EAファイルにそれらを含める必要があります。
BuyLimit注文を発注すると、処理されたすべてのトランザクションの以下の項目が操作ログに表示されます。
Transaction Type: Order add (Adding a new open order) Order: 1838106218 Symbol: EURUSD Order type: Buy Limit (Buy Limit pending order) Order state: Started (Order checked, but not yet accepted by broker) Time type: Time GTC (Good till cancel order) Price: 1.09449 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: Order update (Updating an open order) Order: 1838106218 Symbol: EURUSD Order type: Buy Limit (Buy Limit pending order) Order state: Placed (Order accepted) Time type: Time GTC (Good till cancel order) Price: 1.09449 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: Request (The trade request has been processed by a server and processing result has been received) The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data: Request Pending (Place a trade order for the execution under specified conditions (pending order)): Symbol: EURUSD Volume: 0.10 Price: 1.09449 SL: 0.0 TP: 0.0 Type: Buy Limit (Buy Limit pending order) Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further) Type time: Time GTC (Good till cancel order) Expiration: 0 Magic: 1024 Comment: TestMqlTradeTransaction OrderSend result: Retcode: 10009 DONE (Request completed) Deal: 0 Order: 1838106218 Volume: 0.10 Price: 0.0 Bid: 0.0 Ask: 0.0 Comment: Request ID: 930808478 Retcode External: 0
その後、発注した注文を削除する場合、端末操作ログに次のようなエントリが表示されます。
Transaction Type: Order update (Updating an open order) Order: 1838106218 Symbol: EURUSD Order type: Buy Limit (Buy Limit pending order) Order state: Request cancel (Order is being deleted (deleting from the trading system)) Time type: Time GTC (Good till cancel order) Price: 1.09449 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: Order delete (Removing an order from the list of the open ones) Order: 1838106218 Symbol: EURUSD Order type: Buy Limit (Buy Limit pending order) Order state: Canceled (Order canceled by client) Time type: Time GTC (Good till cancel order) Price: 1.09449 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: History add (Adding an order to the history as a result of execution or cancellation) Order: 1838106218 Symbol: EURUSD Order type: Buy Limit (Buy Limit pending order) Order state: Canceled (Order canceled by client) Time type: Time GTC (Good till cancel order) Price: 1.09449 Price SL: 0.0 Price TP: 0.0 Volume: 0.10 Transaction Type: Request (The trade request has been processed by a server and processing result has been received) The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data: Request Remove (Delete the pending order placed previously): Order: 1838106218 OrderSend result: Retcode: 10009 DONE (Request completed) Deal: 0 Order: 1838106218 Volume: 0.00 Price: 0.0 Bid: 0.0 Ask: 0.0 Comment: Request ID: 930808479 Retcode External: 0
結論
取引注文を作成し、それを確認し、サーバーに送信し、さらに取引操作の結果として口座で発生したすべての取引トランザクションの完全な説明を取得するためのすべての構造体を検討しました。
提案された関数はすべて「そのまま」使用できます。あるいは、読者の使用イメージに合わせて変更することもできます。
この記事で考慮されているすべての機能を含むEAファイルは添付ファイルに含まれています。ダウンロードして、自分ですべてをテストすることができます。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/13052
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索