
交易事务. 请求和响应结构、描述和记录
目录
- 使用示例
- 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–这并不意味着请求的交易操作将成功执行。为了获得执行函数的结果的详细描述,我们应该分析上面给出的结果结构的字段。
在成功检查交易订单结构的字段完成后,可以将其发送到服务器。OrderSend()函数执行成功并不意味着订单已经执行完毕。我们简单地理解为订单已被服务器处理并接受。向服务器发送交易订单的结果将是MqlTradeResult结构的填充字段,该结构包含交易服务器对OrderSend()函数发送的请求的响应。
交易操作的结果返回到MqlTradeResult类型的变量,该变量作为第二个参数传递给OrderSend()函数,用于执行交易操作。
当使用OrdersSend()和OrderSendAsync()函数将请求发送到交易服务器时,终端会在request_id字段中设置ID。终端从交易服务器接收有关已执行交易的消息,并将其提交给OnTradeTransaction()函数进行处理,该函数包含以下组件作为参数:
- MqlTradeTransaction结构中的交易事务描述;
- 从OrderSend()或OrdersSendAsync()函数发送的交易请求的描述。请求ID由终端发送到交易服务器,而请求本身及其request_id存储在终端存储器中;
- 交易请求执行结果为MqlTradeResult结构,request_id字段包含该请求的ID。
OnTradeTransaction()函数接收三个输入参数,但最后两个参数应仅针对TRADE_TRANACTION_REQUEST类型的交易进行分析。在所有其他情况下,交易请求及其执行结果的数据都不会被填充。参数分析示例可在交易请求结构部分找到。
终端在将交易请求发送到服务器时为其设置request_id,主要是为了使用OrderSendAsync()异步函数。此标识符允许将执行的操作(OrderSend或OrderSendAsync函数调用)与发送到OnTradeTransaction()的此操作的结果相关联。
因此,我们可以控制服务器对交易订单的接受、交易订单在交易系统中的放置以及OnTradeTransaction()函数中的执行。在当前的文章中,我将编写函数来在日志中显示交易请求中涉及的所有结构的字段,从填写交易订单的结构开始,到分析OnTradeTransaction()中的事件结束。预期的结果是一个小的通知EA,它打印出日志中的所有交易事件。
处理交易订单可归结为以下步骤:
- 填写交易请求的结构,
- 检查填写结构的正确性以及下订单的可能性,
- 向服务器发送交易订单,
- 必要时分析向服务器发送订单的结果的结构,
- 从OnTradeTransaction()处理程序接收事件并分析日志中的消息。
辅助函数
文章末尾介绍的EA将通过按下键盘快捷键进行控制。让我们编写两个函数来判断按下Ctrl和Shift键的次数:
//+------------------------------------------------------------------+ //| 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键的标志,或者同时按住它们以响应控制键和字母数字键的组合。
当返回结构字段的描述时,我们需要打印交易服务器返回代码。让我们制作一个函数,返回服务器响应代码的描述:
//+------------------------------------------------------------------+ //| 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(交易品种的订单和仓位数量已达到极限)
返回订单类型说明的函数:
//+------------------------------------------------------------------+ //| 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结构的类型字段中指定,可以从ENUM_ORDR_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()函数发送交易请求时,可以在type_filling字段中设置必要的交易量执行策略,即在特殊的MqlTradeRequest结构中。ENUM_ORDER_TYPE_FILLING枚举中的值可用。要按特定的活动/已完成订单获取属性值,请使用带有ORDER_TYPE_FILLING修饰符的OrderGetInteger()或HistoryOrderGetIntegr()函数。
在发送在当前时间执行的订单之前,为了正确设置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) */ }
每个订单都有一个描述其状态的状态码,要获取信息,请使用带有ORDER_STATE修饰符的OrderGetInteger()或HistoryOrderGetIntegr()函数。有效值存在于ENUM_ORDR_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中。要获取交易类型的数据,请使用带有DEAL_TYPE修饰符的HistoryDealGetInteger()函数。
该函数按过期时间返回订单类型的描述:
//+------------------------------------------------------------------+ //| 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结构的字段中设置订单有效期。有效值为ENUM_ORDR_TYPE_TIME枚举中的值。要获取属性值,请使用带有ORDER_TYPE_TIME修饰符的OrderGetInteger()或HistoryOrderGetIntegr()函数。
交易事务可以与订单、交易和头寸一起发生。此类交易的每一类中都可以有不同的类型——添加、修改和删除。但有时我们只需要知道交易是用什么进行的,而不需要具体说明细节——订单、交易或头寸。为了实现这一点,让我们创建一个返回事务关联的函数:
//+------------------------------------------------------------------+ //| 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; } }
该函数接收事务类型和三个标志变量(通过引用),这些变量根据事务的具体执行情况进行设置/重置。
返回交易请求类型说明的函数:
//+------------------------------------------------------------------+ //| 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),而只使用一个(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 */ }
价格
订单应当被执行的价格. 对于“市场执行”(SYMBOL_TRADE_EXECUTION_MARKET)类型的具有TRADE_ACTION_DEAL类型资产的市场订单,不设置价格。
//+------------------------------------------------------------------+ //| 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 */ }
止损限价订单水平
用于止损限价买入和止损限价卖出挂单. 当价格达到“该价格”值时,将限价挂单的价格设置为此(此条件是强制性的),直到那一刻,挂单才被发送到交易系统。
//+------------------------------------------------------------------+ //| 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 用于设置止损限价买入挂单:
//+------------------------------------------------------------------+ //| 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 用来设置止损限价卖出挂单:
//+------------------------------------------------------------------+ //| 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 用来在发送准备好的请求之前做检查
我建议在向交易服务器发送请求之前先检查交易操作。检查由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) };
响应代码
返回代码。所有执行交易操作的订单都以MqlTradeRequest交易请求结构的形式使用OrderSend()函数发送。执行该函数的结果被放置到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()函数,用于执行交易操作。
实现以下函数以显示结构字段的描述:
运行结果代码
//+------------------------------------------------------------------+ //| 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 */ }
当前市场卖家报价
//+------------------------------------------------------------------+ //| 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 */ }
当前市场买家报价
//+------------------------------------------------------------------+ //| 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 */ }
下挂单时,结构中的“出价”和“要价”保持为空。如果订单因重新报价而未被接受,我们可以在出价和要价字段中看到订单被拒绝时的价格。
交易中的经纪商备注
//+------------------------------------------------------------------+ //| 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 结构
由于对交易帐户执行某些操作,其状态会发生变化。这些操作包括:
- 通过客户端中的任何MQL5应用程序使用OrderSend和OrderSendAsync函数发送交易请求及其后续执行;
- 通过终端的图形界面发送交易请求及其后续执行;
- 在服务器上触发挂单和停止订单;
- 在交易服务器端执行操作。
由于这些操作,该帐户将执行以下交易事务:
- 处理交易请求;
- 更改未结订单;
- 变更订单历史;
- 交易历史的变化;
- 改变仓位。
例如,当发送一个买入市场订单时,会对其进行处理,为该账户创建相应的买入订单,执行该订单,将其从未结订单列表中删除,并添加到订单历史记录中。然后,相应的交易被添加到历史记录中,并创建一个新的仓位。所有这些操作都是交易事务。
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_TRANACTION_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_ORDR_TYPE枚举值之一。
//+------------------------------------------------------------------+ //| 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_ORDR_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_IME_SPECIFIFIED_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”,否则显示日期格式的过期时间。如果我们不检查字段值是否为零,则零值将显示为01.01.1970 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_YPE_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_TRANACTION_REQUEST类型(已收到服务器处理交易请求的结果),则该结构的字段中只填写了type。其他字段不进行分析。在这种情况下,我们可以分析提交给OnTradeTransaction()处理程序的两个额外的request和result参数,如下所示
了解交易操作的类型,我们可以决定分析交易账户上订单、仓位和交易的当前状态。请记住,从终端发送到服务器的一个交易请求可以生成多个交易事务。它们到达终点站的顺序无法保证。
MqlTradeTransaction结构的填充方式因交易事务类型而异(ENUM_TRADE_TRANACTION_TYPE):
TRADE_TRANSACTION_ORDER_* 和 TRADE_TRANSACTION_HISTORY_*
对于与处理挂单相关的交易事务(TRADE_TRANACTION_ORDER_ADD、TRADE_TRANSACTION_ORDER_UPDATE和TRADE_TTRANSACTION_ONDER_DELETE)和订单历史记录(TRADE_TRANACTION_HISTORY_ADD、TRADE_TRANSACTION_HISTORY_UPDATE、TRADE_TRANACTION_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_TRANACTION_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_TRANACTION_POSITION):
- symbol — 仓位金融资产的名称;
- type — 交易事务类型;
- deal_type — 仓位类型 (DEAL_TYPE_BUY 或者 DEAL_TYPE_SELL);
- price — 开启仓位的加权平均价格;
- price_sl — 止损价格;
- price_tp — 获利价格;
- volume — 改变的仓位手数大小.
- position — 仓位编号.
由于交易而更改仓位(添加、更改或移除)并不需要TRADE_TRANACTION_POSITION交易。
TRADE_TRANSACTION_REQUEST
MqlTradeTransaction结构中只为交易事务填写一个字段,描述服务器已处理交易请求并收到结果(TRADE_TRANACTION_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/en/docs/event_handlers/ontradetransaction. */ }
交易事务通知EA交易
为了检查上面讨论的函数的操作,让我们创建一个跟踪所有交易交易和服务器响应的EA,并在日志中显示传入交易的描述。让我们实现它,这样我们就可以通过按下设置中选择的键来设置挂单(止损买入、止损卖出、限价买入和限价卖出)和开仓(买入和卖出)。默认情况下,以下按键将分配给交易管理:
订单类型 | 用于打开/设置的键盘快捷键 | 用于关闭/删除的键盘快捷键 |
---|---|---|
买入 | 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会自动将它们转换为大写。我们可以设置三个键-买入、卖出和平仓/删除订单。用于修改请求中挂单类型的Ctrl和Shift控制键是默认分配的,不能更改。当按下“B”时,将打开买入头寸,当按住Shift并按下“B”时,将设置买入止损买入挂单。当同时按住Ctrl和Shift并按下“B”时,将设置买入限价买入挂单。这同样适用于卖出——只需按下“S”即可打开卖出头寸,同时按下控制键可设置止损卖出和限价卖出。关闭所有未结头寸是通过按下“X”按钮进行的,按住Shift或Ctrl+Shift(无关紧要)并按下“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文件中,以便进行无错误编译。
下限价买入挂单时,所有已处理交易的以下条目将显示在日志中:
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



