Most of the functionality and syntax between MQL4 and MQL5 are similar. However, some core functions and code structures may vary. This is, for example, the case for executing trade operations. MQL4 and MQL5 OrderSend() function do not share the same properties. In this article, we will highlight the difference between both languages and how to place a trade with MQL4 and MQL5.
Before we deep dive into the code, let us define the various types of basic trade operations that can be performed on MetaTrader. There are four types of operations:
- Market order, which is a buy or sell order placed immediately at the current market price.
- Pending order, which is an order to buy or sell at a different price than the current market price, for instance, BUY STOP, SELL LIMIT, BUY LIMIT and SELL STOP.
- Modifying or removing a non-executed pending order.
- Closing, adding, partial close of a position.
The four basic types of trade operations
The four basic types of trade operations are performed with the function OrderSend(). The type of trade operations is defined by ENUM_ORDER_TYPE properties in MQL5 and by the order properties OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP, OP_SELLSTOP in MQL4.
The four type of pending orders (Fig.94):
- BUY STOP: Buy stop is an order placed above the current market price. It is designed to enter a long position at the specified level once the market price crosses the defined threshold.
- BUY LIMIT: Buy limit, on the other hand, will open a long position if the market price crosses the threshold and moves back above the defined level. Buy limit is a pending order placed below market price.
- SELL LIMIT: Sell limit is a pending order that is placed above market price and triggers a short position once the price has moved beyond the defined level and moves back down, crossing the threshold.
- SELL STOP: Sell stop is an order placed below the market price and designed to execute a short position once the defined level has been crossed downward.
The concept of magic number
MetaTrader and by extent, MQL4 and MQL5 robots are using a defined number to identify which trade belongs to which expert advisor. This unique number is what we name “magic number.” It is a unique number to track open positions and to allow multiple expert advisors to run in parallel without affecting each other’s operations. The magic number is declared and defined as a global variable. Some practical example of the use of magic number:
- You have two different trading strategies provided by two expert advisors. Both expert advisors are trading on the EUR/USD pair. One of the expert advisors will close all EUR/USD opened positions with the condition that the market price crosses the 20-day moving average. The second expert advisor condition is to close the trade once it reaches a predefined target price of 100 pips. The use of a magic number to differentiate each of the expert advisor’s trading positions will avoid mistakenly closing another expert advisor’s trade.
- You have a trading strategy that operates on two different time frames but on the same currency pair. One of the strategies is a one-hour timeframe moving average crossover strategy, and the other is a daily time frame pivot point trading. Each strategy belongs to one expert advisor. The first strategy will open and close GBP/USD positions according to the price action on the one-hour chart. The second strategy will open GBP/USD positions at the beginning of the day and close trades according to the pivot points. In this case, two different magic numbers will be used to differentiate which trade belongs to which strategy.
- Magic numbers are defined as global variables.
- More than one magic number can be defined in an expert advisor to organize and segregate strategies.
- Magic number is an integer; hence only a series of numbers can be assigned.
OrderSend() function parameters
Trade requests are executed with the function OrderSend(). The function OrderSend() is designed to manage all the functionality to manage trading operations, from opening trade at market price, set pending order, modification of stop loss, and take profit level and closing positions. The function OrderSend() does exactly the same thing; however, the structure of the function differs. In MQL4, OrderSend() requires eleven parameters and returns an integer, as a result, while in MQL5, OrderSend() requires only two parameters and returns a Boolean as a result (Fig.95).
Fig.95 OrderSend() function in MQL4 and MQL5 language
|Symbol (EURUSD, GBPUSD, Symbol() )||MqlTradeRequest | request|
|cmd (OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP, OP_SELLSTOP)||MqlTradeResult | result|
|Volume (Lot size: 0.1, 0.01, 1.0)|
|Price (Entry price: 1.30, Ask, Bid)|
|Slippage (Maximum price slippage to enter)|
|Stoploss (Stop loss level)|
|Takeprofit (Take profit level)|
|Comment=NULL (Order comment text)|
|Magic (Order magic number)|
|Expiration (We recommend leaving this parameter to 0 to avoid some errors from some brokers which do not support this function)|
|arrow_color=clrNONE (The color of the arrow that is displayed on the chart)|
MqlTradeRequest and MqlTradeResult are a structure that is specific to MQL5. MQL4 use a set of parameters to define an order while MQL5 regroups type into a predefined structure which is defined as follows:
|MQL5 Request Structure|
|action; //Trade operation type (*1)
magic; //Expert Advisor ID (magic
order; //Order ticket
symbol; //Trade symbol
volume; //Requested volume for a deal in
stoplimit; //StopLimit level of the order
sl; //Stop Loss level of the order
tp; //Take Profit level of the order
deviation; //Maximal possible deviation
type; //Order type (*2)
type_filling; //Order execution type
type_time; //Order expiration type
expiration; //Order expiration time (for the
comment; //Order comment
position; //Position ticket
position_by; //The ticket of opposite position
|retcode; //Operation return code
deal; //Deal ticket, if it is performed
order; //Order ticket, if it is placed
volume; //Deal volume, confirmed by broker
price; //Deal price, confirmed by broker
bid; //Current Bid price
ask; //Current Ask price
comment; //Broker comment to operation
request_id; //Request ID set by the terminal
retcode_external; //External return code
|MQL5 MqlTradeRequest type|
|action (*1)||type (*2)|
Place a trade order for immediate execution with the specified parameters (market order).
Place a trade order for the execution under specified conditions (pending order).
Modify Stop Loss and Take Profit values of an opened position.
Modify the parameters of the order placed previously.
Delete the pending order placed previously.
Close a position by an opposite one.
Market Buy order
Market Sell order
Buy Limit pending order.
Sell Limit pending order.
Buy Stop pending order.
Sell Stop pending order.
Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price.
Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price.
Order to close a position by an opposite one
|Retrieve market price function and properties for MQL4 and MQL5|
- Use the function Symbol() to get the symbol from which you are attaching your expert advisor.
- For the parameter “Price,” you can either enter the entry price by providing the price or use the predefined property SYMBOL_ASK, SYMBOL_BID in MQL5.
How to open a buy or sell at market price?
Line 97: Define a return status for the OrderSend() function. If OrderSend() successfully performs a position on the market, it will return the value of the status to the variable ticket. If -1 is returned, then MetaTrader fails to place the trade.
Line 98: Check the ticket value returned by OrderSend().
Line 97: Note that the second parameter from OrderSend() differentiates the buy from the sell with the property OP_BUY and OP_SELL.
Fig.96 Open a buy or sell market order with MQL4
MQL5 approach to OrderSend() differs from MQL4. MQL5 approach to OrderSend() is only through two parameters, MqlTradeRequest and MqlTradeResult. These two parameters regroup type-specific to trade order.
Line 90 -91: Declare and initialize MqlTradeRequest and MqlTradeResult structure.
Line 93 – 99: Define parameters.
Line 93: Note that for market orders, the action type is defined as TRADE_ACTION_DEAL.
Line 96: Define the type of order, ORDER_TYPE_BUY or ORDER_TYPE_SELL.
Line 102: Conditional check of the OrderSend() function with the provided parameters. OrderSend() returns true if an error occurred during the process.
Line 103: With the function GetLastError(), you can get the error code to facilitate troubleshooting and debugging. Use PrintFormat() to display the error message in the log.
Fig.97 Open a buy or sell market order with MQL5
How to open a pending buy or sell stop order?
Line 97: Send order buy stop as specified by OP_BUYSTOP, the second parameter from the function OrderSend(). Variable ticket collects the returned code from the function OrderSend().
Line 98 – 100: Check the value of the variable ticket and if the returned value is less than 0, print an error message in the log.
Line 114: Send order sell stop as specified by OP_SELLSTOP, the second parameter from the function OrderSend().
Fig.98 Open a pending buy stop or pending sell stop with MQL4
Line 61 – 62: Declare structure MqlTradeRequest and MqlTradeResult and assign request and result.
Line 64 – 72: Define trade order parameters.
Line 64: Note that for pending order, the type is TRADE_ACTION_PENDING.
Line 65: Define the type of order: ORDER_TYPE_BUY_STOP or ORDER_TYPE_SELL_STOP.
Line 74: OrderSend() execute the order and return a code that determines if it succeeds. The if statement checks the returned logical value. If the value is false, the error code is printed in the log as per the function GetLastError() (Line 76).
Fig.99 Open a pending buy stop or pending sell stop with MQL5
How to open a pending buy or sell limit order?
Line 97: Note the second parameter of the function OrderSend(), which defines a buy limit order with OP_BUYLIMIT. OrderSend() returns a status value, -1 if it fails to place the trade order.
Line 98: If statement that checks the value of the variable ticket that contains the returned status value from OrderSend().
Line 114: The second parameter from the function OrderSend() defines the type of order, which is a sell limit with OP_SELLLIMIT.
Fig.100 Open a pending buy limit or pending sell limit with MQL4
Line 61 – 62: Declare MqlTradeRequest and MqlTradeResult, which are structures that contain specific parameters for the trade order.
Line 64 – 72: Define parameters of the trade order.
Line 64 – 65: Define the type of trade. Note that a buy limit or a sell limit is a pending order which corresponds to the type of TRADE_ACTION_PENDING. Specify the type of trade with ORDER_TYPE_BUY_LIMIT for a buy limit or ORDER_TYPE_SELL_LIMIT for a sell limit.
Line 74: Execute the order with OrderSend(). Note that OrderSend() returns a status value of the trade execution. In case an error occurred during the process, OrderSend() will return false.
Fig.101 Open a pending buy limit or pending sell limit with MQL5
- Use function and properties instead of input value or manually defined values. For instance, to retrieve the symbol to trade, instead of providing “EUR/USD” as the symbol, use the function Symbol(). As for price as well, use a dynamic price allocation such as Ask +2, Bid -5, instead of providing a fixed price such as 1.3503. Using properties and functions allow you more flexibility and code reusability.
- Instead of calling multiple time OrderSend() for each criterion, implement a function to manage and facilitate your algorithm logic.