Articles on MQL4
OrderSend()

OrderSend()


for example, forex

Function OrderSend() in MQL-4 is, I suppose, most frequently used, as with its help pending orders are placed and buy and sell orders are opened. Let’s consider the usage of this function taking as an example a script that will turn round an open position in a particular instrument. Let’s suppose that we have one or several open long positions in EURUSD. Suppose, the price surged and reached the target level (according to our suppositions) where it is necessary to take profit (close out positions), and it is also desirable to open an equal opposite position, i.e. short position. In conditions of fast market when price changes rather quickly it is impossible to perform such operation quickly by hand. We have to:

  1. Close successively one or several buy orders.
  2. Open one sell order of the equal total volume.
MQL-4 and MetaTrader4 allow executing all these operation in one action. The matter is that the terminal MT4 allows closing out an open position by the opposite open position, i.e. to close out buy orders by sell orders. Additionally we save a sum of money equal to the spread value. If we have an order to buy 0.1 EURUSD lot at 1.2000 and an order to sell 0.1 EURUSD lot at 1.2500 (and there are no more orders open in EURUSD), then no matter where the price is at the moment, the total current profit for these two orders is equal to 500 points (Point=0.001). Swap points, calculated for these two orders will be as the result negative, but for us it doesn’t matter. MT4 allows to close out a buy order opened at 1.2000, by a sell order at ask price(1.2500). Of course the sizes of the two orders must be the same.

Suppose, at the moment Bid in EURUSD is equal to 1.2600. If we close each of the two orders independently we will get the following: we close the buy order 1.2000 at 1.2600 (+600 points) and we close the sell order 1.2500 at 1.2603 (Bid + spread 3 points) – in all we have minus 103 points. In all the profit is equal to 600-103=497 points. Suppose the price between two closings out didn’t change. If we closed one order by the other we would get 500 points (1.2500-1.2000). If sizes of opposite orders don’t coincide, then the order of the smaller size is fully closed out, and an order of the size equal to the difference between the opposite orders is left. I.e. in case with 0.2 buy and 0.1 sell, after a partial closing we would get an order to buy 0.1 lot at bid price. This very feature will be used in our turn round script Revers.mq4. We will check availability of only buy or only sell orders, will calculate the total volume of the position open in this instrument and will open an opposite position of doubled size. Thus after the script’s work we will have order(s) of the volume V1 and the opposite order of the volume V2=2*V1. Then we will be able to close out by hand necessary orders and to leave one order of the volume V2-V1=2*V1-V1=V1.

We will create the script according to the principle of overcoming obstacles. If at some stage conditions are not fulfilled – the script terminates working early. First of all (as usually) we build in protection from a real account:

 
 


If the script is launched on a live account, the warning will appear and the script will terminate working. Next step is to check availability of orders:

 
 


If there are no orders ( OrdersTotal() is equal to zero) – there is no sense to continue working. But even if there are orders, we need to make sure that there are orders in our symbol (the chart of the instrument on which we launch the script), and the orders are open, not pending. We will use the loop to count orders open in our instrument. At the same time we will count the volumes of sell and buy orders separately.

 
 


We can see that if an order is open not in our symbol (OrderSymbol()!=Symbol()), the work with the order terminates and the script proceeds to the order which is next in the list (operator continue;) . After the list of orders is checked, we may check separately availability of buy orders and sell orders, but we may also check both counters by one operation – having added the counters. If the sum is equal to zero there are no open orders, there are only pending orders.

 
 


Such variant doesn’t suit us as well, so we exit. The next check – we need to have only buy orders or only sell orders. We want to have a uniquely defined situation. I checked it by means of multiplying counters, if the product is equal to zero then we have orders of one type only.

 
 


If the script after all these checks hasn’t terminated its work it means that this is high time to open the opposite order of doubled volume. br />
 
 


We haven’t got the doubled order directly, i.e. instead of writing reversLots=2*sellLots (for sell orders) , a complicated construction was used. What for was it done? The size of position is of the type double, and in computer calculations 2.0 multiplied by 2.0 is not always equal to 4.0. This is connected with the mistakes of rounding off not integer variables in the binary numeral system. Though 2 multiplied by 2 is always equal to 4. That’s why at first we will multiply buyLots by 10 (without a decimal point) and then we will double the received integer result. For example, 0.2(lot)*10*2=4. We have got an integer result four. Now we need to receive the size of reversLots(0.4) 10 times smaller accurate to the first decimal place. For this we divide intLots (integer lots) of the type int by 10.0 of the type double (direct your attention to the dot) and then we normalize the result to the accuracy of the first decimal place. As a result we have got the value 0.4 with the necessary accuracy.

If we divided 4 by 10 (4/10), then, as both numbers are integer (int), the result of division would be calculated according to the rules of integer arithmetic. As 4(integer) isn’t divided by 10 (integer) the result would be zero. This is one of the common mistakes; one mustn’t forget the difference between integer division and division of real numbers in computer calculations.

So, the size of the opposite order has been calculated, we only have to send the trading instruction to the server. Sometimes prices move so quickly that while the script was making calculations the current prices have become different from the prices at the moment of the script’s launch. It is necessary to have the latest prices always in order to prevent a denial of the server for the reason of invalid prices. For this there is such command as RefreshRates(), I recommend to read the Help on it. When this command is executed the broker’s trading server isn’t addressed, that’s why it may be used as often as it is necessary, not fearing to fall across sanctions from the broker. At last we may send the trading order OrderSend(). Though the Help menu on this function contains all the necessary information, I have to single out two common mistakes in its usage:
  1. often traders forget to specify the symbol in which an order is opened. I.e. they simply missed the first parameter of the function (Symbol()), but MQL-4 allows to open orders in «alien» instrument (which is impossible in the tester). The compiler forgives such mistake and doesn’t report anything, and then the user wonders why orders wouldn’t open.
  2. when users open an order of the type OP_BUY they mistakenly put Bid as the opening price, and for selling – vice versa. Naturally the order will be hardly opened.
Besides, it is desirable not to set the parameter Slippage equal to zero, as this increases probability of a denial due to the change of price – during the time needed for your trading order to reach the trading server, the price may change, the zero Slippage parameter will be interpreted by the server as a denial of making a deal at somewhat different price and the order won’t pass.

In fact, the number of errors, returned by the terminal or trading server is rather big, and these errors help to correct the algorithm. In order to know the code of the returned error there is the GetLastError() function. It is necessary to ask for the error code by means of this function each time we get a mistaken situation. As in the case of a failure OrderSend() returns the value -1, we output this error in case if ticket is less then zero (we could as well check ticket==-1). If the order opens normally, we won’t see the error report. The script is ready, I launch it on the chart of USDCHF, in which an order to buy 0.1 lot was open.

 
 


We can see that the script opened the opposite order doubled in size.

 
 

In the order comment it is indicated «revers order» - out mark. Now at any moment we can click on one of these order, choose the type «Close covered orders», we only have to press the yellow button.

 
 


You can download the script here.
Go to article «Expert Advisor».

+7 (495) 710-76-76
© 1998—2008 «Alpari»

close

Your Personal Area

For alpari.classic enter your account number (a letter and 4 figures) and the code word for the Personal Area.

For alpari.micro account: enter your login (6 figures) and the password for MT.

Open an account!Forgotten your password?