MQL4 Book  Programming of Trade Operations  Modification of Orders

Modification of Orders


MQL4 allows you to modify market and pending orders. Orders are modified according to the rules described in Order Characteristics and in Appendix 3.

Function OrderModify()


Trade requests for modifying of market and pending orders are formed using the function OrderModify().

bool OrderModify(int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE)

The function modifies the parameters of market and pending orders. The function returns TRUE, if the trade is made successfully. Otherwise, it returns FALSE.

Parameters:

ticket - the unique number of the order.

price - the newly requested price of a pending order or the new open price for a market order.

stoploss - the new value of StopLoss.

takeprofit - the new value of TakeProfit.

expiration - the expiration time of a pending order.

arrow_color - the color of arrows for modifying of StopLoss and/or TakeProfit in the chart. If this parameter is unavailable or its value is equal to that of CLR_NONE, the arrows will not be displayed in the chart.

Note: You can change open price and expiration only for pending orders.

If you pass unchanged values as the function parameters, the terminal will generate error 1 (ERR_NO_RESULT). There can be a limitation set for application of expiration time to pending orders on some trade servers. In this case, if you try to create a non-zero value in the parameters of expiration, error 147 (ERR_TRADE_EXPIRATION_DENIED) will be generated.

Modification of Market Orders


A standard market order contains two stop orders - StopLoss and TakeProfit. They instruct to close the order at the requested prices in order to stop losses and fix profits. Modification of market orders may be useful for changing of the requested prices of stop orders either as a result of new calculated values obtained in the program or at the trader's initiative. The client terminal has its own tool used for modification of StopLoss: Trailing Stop. It allows the program to modify the level of StopLoss following the rate at a certain fixed distance from it (see MetaTrader 4 Cleitn Terminal User Guide).

The order-modifying function OrderModify() expands the modification capacities considerably: The requested prices of both stop orders can be changed in the direction of the market price or deleted. A limitation for market order modification is the minimum allowed distance between the stop order and the market price, set by the dealing center (see Order Characteristics and Requirements and Limitations in Making Trades). If the program tries to change the position of a stop order in such a way that it is placed closer to the market than the allowed minimum distance, such trade request will be rejected by the client terminal and the execution of the function OrderModify() will fail (error 130). This is why you should provide a special block in your program, which will consider this limitation.


Example of a simple Expert Advisor that modifies StopLosses of all market orders, for which the distance between the requested price of StopLoss and the market price is larger than the preset one (modifystoploss.mq4)

//------------------------------------------------------------------------------------
// modifystoploss.mq4
// The code should be used for educational purpose only.
//------------------------------------------------------------------------------------
extern int Tral_Stop=10; // Trailing distance
//------------------------------------------------------------------------------- 1 --
int start() // Special function 'start'
{
string Symb=Symbol(); // Symbol
//------------------------------------------------------------------------------- 2 --
for(int i=1; i<=OrdersTotal(); i++) // Cycle searching in orders
{
if (OrderSelect(i-1,SELECT_BY_POS)==true) // If the next is available
{ // Analysis of orders:
int Tip=OrderType(); // Order type
if(OrderSymbol()!=Symb||Tip>1)continue;// The order is not "ours"
double SL=OrderStopLoss(); // SL of the selected order
//---------------------------------------------------------------------- 3 --
while(true) // Modification cycle
{
double TS=Tral_Stop; // Initial value
int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);//Min. distance
if (TS < Min_Dist) // If less than allowed
TS=Min_Dist; // New value of TS
//------------------------------------------------------------------- 4 --
bool Modify=false; // Not to be modified
switch(Tip) // By order type
{
case 0 : // Order Buy
if (NormalizeDouble(SL,Digits)< // If it is lower than we want
NormalizeDouble(Bid-TS*Point,Digits))
{
SL=Bid-TS*Point; // then modify it
string Text="Buy "; // Text for Buy
Modify=true; // To be modified
}
break; // Exit 'switch'
case 1 : // Order Sell
if (NormalizeDouble(SL,Digits)> // If it is higher than we want
NormalizeDouble(Ask+TS*Point,Digits)
||
NormalizeDouble(SL,Digits)==0)//or equal to zero
{
SL=Ask+TS*Point; // then modify it
Text="Sell "; // Text for Sell
Modify=true; // To be modified
}
} // End of 'switch'
if (Modify==false) // If it is not modified
break; // Exit 'while'
//------------------------------------------------------------------- 5 --
double TP =OrderTakeProfit(); // TP of the selected order
double Price =OrderOpenPrice(); // Price of the selected order
int Ticket=OrderTicket(); // Ticket of the selected order

Alert ("Modification ",Text,Ticket,". Awaiting response..");
bool Ans=OrderModify(Ticket,Price,SL,TP,0);//Modify it!
//------------------------------------------------------------------- 6 --
if (Ans==true) // Got it! :)
{
Alert ("Order ",Text,Ticket," is modified:)");
break; // From modification cycle.
}
//------------------------------------------------------------------- 7 --
int Error=GetLastError(); // Failed :(
switch(Error) // Overcomable errors
{
case 130:Alert("Wrong stops. Retrying.");
RefreshRates(); // Update data
continue; // At the next iteration
case 136:Alert("No prices. Waiting for a new tick..");
while(RefreshRates()==false) // To the new tick
Sleep(1); // Cycle delay
continue; // At the next iteration
case 146:Alert("Trading subsystem is busy. Retrying ");
Sleep(500); // Simple solution
RefreshRates(); // Update data
continue; // At the next iteration
// Critical errors
case 2 : Alert("Common error.");
break; // Exit 'switch'
case 5 : Alert("Old version of the client terminal.");
break; // Exit 'switch'
case 64: Alert("Account is blocked.");
break; // Exit 'switch'
case 133:Alert("Trading is prohibited");
break; // Exit 'switch'
default: Alert("Occurred error ",Error);//Other errors
}
break; // From modification cycle
} // End of modification cycle
//---------------------------------------------------------------------- 8 --
} // End of order analysis
} // End of order search
//------------------------------------------------------------------------------- 9 --
return; // Exit start()
}
//------------------------------------------------------------------------------ 10 --

The above program is an Expert Advisor. If necessary, you can easily realize the order-modifying function in a script. However, it wouldn't be very useful to use a normal script in this example, because the script would end its operations after the trade has been made. The use of a script would be reasonable, in case the program realizes a one-time performing of an operation, for example, opening or closing orders. In this case, however, we're solving a task that needs continuous control over the situation: change the position of a stop order, if a certain condition is met, namely, if the distance between the market rate and the requested value of the stop order exceeds a certain preset value (10 points, in our case). For a long-term usage, it is much more convenient to write an EA that is launched for execution at every tick and stops working only upon the direct instruction by the user.

The algorithm of the above EA modifystoploss.mq4 is very simple. The main calculations are performed in the cycle of searching in the orders (block 2-9). The order is searched in both market and pending orders (the parameter 'pool' in the function call OrderSelect() is not explicitly specified). In block 2-3, pending orders and the orders opened for another symbol are filtered out; for the orders that have been selected, the value of StopLoss is determined.

Block 3-9 represents a cycle for modification of the selected order. In block 3-4, the new current value of the limiting distance is determined (your broker can change this value at any moment). In block 4-5, the necessity to modify the selected order (currently processed in the cycle 'for') is calculated, as well as a new value of StopLoss. If the current order needn't be modified, the program exits the cycle 'while' at the end of block 4-5 and this order is not modified (in block 5-6). However, if the order needs to be modified, the control is passed to block 5-6, in which the necessary parameters are calculated and the function OrderModify() is called that forms a trade request.

If a trade is completed successfully, the operator 'break' in block 6-7 will end the execution of the cycle 'while', which results in ending of the current iteration of the order-searching cycle 'for' (the next order will start to be processed at the next iteration). If the trade is not performed successfully, the errors will be processed. If an error turns out not to be critical, the program retry to make a trade. However, if the error is estimated as critical, the control will be passed outside the modification cycle for processing of the next order (in the cycle 'for').

You should note a small feature here that relates to the modification of market orders. Function OrderModify() sets new price values for both stop orders simultaneously. However, the necessity to comply with the minimum distance concerns only the stop order, the new value of which differs from the current one. If the new value remains the same as the current one, the stop order may be at any distance from the market price, whereas the corresponding trade request is considered as correct.

For example, we have a market order Buy opened at the price of 1.295467, with the following stop orders: StopLoss = 1.2958 and TakeProfit = 1.2960. The minimum distance set by the broker is 5 points. For the market price Bid = 1.2959, the conditions for modification of the order arise, namely, for placing StopLoss = 1.2949 (Bid - 10 points). In order to execute the function OrderModify(), you should also specify a new value of TakeProfit. Our EA does not change the position of TakeProfit, so we set its current value in the function: TakeProfit = 1.2960.

In spite of the fact that the new requested value of TakeProfit = 1.2960 is close to the market price Bid (only 1 point, i.e., less than the allowed minimum distance of 5 points), this value does not differ from the current value of TakeProfit = 1.2960, so the trade request will be considered as correct and performed on the server (in general, the request may be rejected, but for other reasons). Fig. 102 and 103 represent the results of a successful modification in such situation.


Fig. 102. Alerting window and symbol window as they appear at modification of an order by EA modifystoploss.mq4 when the market rate is close to the requested value of TakeProfit.



Fig. 103. Modified order in the "Terminal" window.

We can see in Fig. 103 that the modification resulted in the new value of StopLoss = 1.2949, and the current price Bid = 1.2959 was at a distance of 1 point from the value of TakeProfit.

It must be noted separately that neither market nor pending orders should be modified) in isolation from the market situation analysis. Such modification can only be useful, if the market rate moves rapidly and in one direction, which may happen after important news. However, if you trade on a "normal" market, the decision of the necessity to modify orders must be made on the basis of market criteria. In Expert Advisor modifystoploss.mq4, we also use a criterion (StopLoss is further from the market price than we want), on the basis of which the program decides to modify orders. However, this criterion is too simple and tough to be considered as a criterion that characterizes market situation.

Modification of Pending Orders


Modification of pending orders slightly differs from that of market orders. The important difference is that it is possible to change the requested price of the order itself. You must keep the rules limiting the position of a pending order as related to the market price and of stop orders as related to the requested order price (see Order Characteristics and Requirements and Limitations in Making Trades). At the same time, all characteristics of the pending order are considered as newly requested, whatever the previous history of related events is stored.

For example, suppose we have a pending order BuyStop = 1.2030 with StopLoss = 1.2025 and TakeProfit = 1.2035. The broker set the minimum allowed distance as 5 points. It is easy to see that the stop orders are within the allowed band, so any modification of the requested order open price will result in the necessary modification of at least one of the stop orders. However, if a trade request is formed that is going to change the requested order price, the values of stop orders remaining the same, the client terminal will consider this request as a wrong one and will not send it to the server for execution. For example, if the request specifies the following values: BuyStop = 1. 2028, StopLoss = 1.2025 and TakeProfit = 1.2035, this request is wrong, although the values of its stop orders have not been changed: in this case, the request is breaking the rule of keeping the minimum distance between the requested order open price and the price of one of the stop orders (see Requirements and Limitations in Making Trades).

Let's see how a script may look that modifies a pending order to approximate its requested price to the market price to a certain predefined distance. Let's set the distance as 10 points. In order to indicate the order to be modified (there can be several pending orders in the window), we are using the price, at which the script was attached to the symbol window.


Example of a simple script that modifies a pending order, the requested open price of which is closer to the script-attachment price than the prices of other pending orders (modifyorderprice.mq4).


//------------------------------------------------------------------------------------
// modifyorderprice.mq4
// The code should be used for educational purpose only.
//------------------------------------------------------------------------------- 1 --
int start() // Special function 'start'
{
int Tral=10; // Approaching distance
string Symb=Symbol(); // Symbol
double Dist=1000000.0; // Presetting
double Win_Price=WindowPriceOnDropped(); // The script is dropped here
//------------------------------------------------------------------------------- 2 --
for(int i=1; i<=OrdersTotal(); i++) // Cycle searching in orders
{
if (OrderSelect(i-1,SELECT_BY_POS)==true) // If the next is available
{ // Analysis of orders:
//---------------------------------------------------------------------- 3 --
if (OrderSymbol()!= Symb) continue; // The symbol is not "ours"
if (OrderType()<2) continue; // Market order
//---------------------------------------------------------------------- 4 --
if(NormalizeDouble(MathAbs(OrderOpenPrice()-Win_Price),Digits)
<
NormalizeDouble(Dist,Digits)) // Select the nearest one
{
Dist=MathAbs(OrderOpenPrice()-Win_Price);// New value
int Tip =OrderType(); // Type of the selected order.
int Ticket=OrderTicket(); // Ticket of the selected order
double Price =OrderOpenPrice(); // Цена выбранн. орд.
double SL =OrderStopLoss(); // SL of the selected order
double TP =OrderTakeProfit(); // TP of the selected order
} // End of 'if'
} // End of order analysis
} // End of order search
//------------------------------------------------------------------------------- 5 --
if (Tip==0) // If there are no pending orders
{
Alert("For ",Symb," no pending orders available");
return; // Exit the program
}
//------------------------------------------------------------------------------- 6 --
while(true) // Order closing cycle
{
RefreshRates(); // Update data
//------------------------------------------------------------------------- 7 --
double TS=Tral; // Initial value
int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);//Min distance
if (TS < Min_Dist) // If less than allowed
TS=Min_Dist; // New value of TS
//------------------------------------------------------------------------- 8 --
string Text=""; // Not to be modified
double New_SL=0;
double New_TP=0;
switch(Tip) // By order type
{
case 2: // BuyLimit
if (NormalizeDouble(Price,Digits) < // If it is further than by
NormalizeDouble(Ask-TS*Point,Digits))//..the preset value
{
double New_Price=Ask-TS*Point; // Its new price
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price-(Price-SL); // New StopLoss
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price+(TP-Price); // New TakeProfit
Text= "BuyLimit "; // Modify it.
}
break; // Exit 'switch'
case 3: // SellLimit
if (NormalizeDouble(Price,Digits) > // If it is further than by
NormalizeDouble(Bid+TS*Point,Digits))//..the preset value
{
New_Price=Bid+TS*Point; // Its new price
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price+(SL-Price); // New StopLoss
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price-(Price-TP); // New TakeProfit
Text= "SellLimit "; // Modify it.
}
break; // Exit 'switch'
case 4: // BuyStopt
if (NormalizeDouble(Price,Digits) > // If it is further than by
NormalizeDouble(Ask+TS*Point,Digits))//..the preset value
{
New_Price=Ask+TS*Point; // Its new price
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price-(Price-SL); // New StopLoss
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price+(TP-Price); // New TakeProfit
Text= "BuyStopt "; // Modify it.
}
break; // Exit 'switch'
case 5: // SellStop
if (NormalizeDouble(Price,Digits) < // If it is further than by
NormalizeDouble(Bid-TS*Point,Digits))//..the preset value
{
New_Price=Bid-TS*Point; // Its new price
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price+(SL-Price); // New StopLoss
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price-(Price-TP); // New TakeProfit
Text= "SellStop "; // Modify it.
}
}
if (NormalizeDouble(New_SL,Digits)<0) // Checking SL
New_SL=0;
if (NormalizeDouble(New_TP,Digits)<0) // Checking TP
New_TP=0;
//------------------------------------------------------------------------- 9 --
if (Text=="") // If it is not modified
{
Alert("No conditions for modification.");
break; // Exit 'while'
}
//------------------------------------------------------------------------ 10 --
Alert ("Modification ",Text,Ticket,". Awaiting response..");
bool Ans=OrderModify(Ticket,New_Price,New_SL,New_TP,0);//Modify it!
//------------------------------------------------------------------------ 11 --
if (Ans==true) // Got it! :)
{
Alert ("Modified order ",Text," ",Ticket," :)");
break; // Exit the closing cycle
}
//------------------------------------------------------------------------ 12 --
int Error=GetLastError(); // Failed :(
switch(Error) // Overcomable errors
{
case 4: Alert("Trade server is busy. Retrying..");
Sleep(3000); // Simple solution
continue; // At the next iteration
case 137:Alert("Broker is busy. Retrying..");
Sleep(3000); // Simple solution
continue; // At the next iteration
case 146:Alert("Trading subsystem is busy. Retrying..");
Sleep(500); // Simple solution
continue; // At the next iteration
}
switch(Error) // Critical errors
{
case 2 : Alert("Common error.");
break; // Exit 'switch'
case 64: Alert("Account is blocked.");
break; // Exit 'switch'
case 133:Alert("Trading is prohibited");
break; // Exit 'switch'
case 139:Alert("Order is blocked and is being processed");
break; // Exit 'switch'
case 145:Alert("Modification prohibited. ",
"Order is too close to the market");
break; // Exit 'switch'
default: Alert("Occurred error ",Error);//Other alternatives
}
break; // Exit the closing cycle
} // End of closing cycle
//------------------------------------------------------------------------------ 13 --
Alert ("The script has completed its operations -----------------------");
return; // Exit start()
}
//------------------------------------------------------------------------------ 14 --

The distance between the market price and the requested price of the pending order is set in the variable Tral. The variable Win_Price contains the value of the price, at which the script was attached to the symbol window. In the cycle of searching in orders (block 2-5), the characteristics of the order closest to the script-attachment level are calculated. Block 6-13 represents the cycle of closing orders. In block 8-9, it is decided about whether the selected order must be modified. If necessary, the new values of the requested price of stop orders are calculated here. The modification of the order is requested using the function OrderModify() in block 10-11. Errors are processed in block 11-13.

Block 8-9 consists of four similar blocks, in which the new values used in the request are calculated. Let's consider the one intended for order SellLimit:

         case 3:                                // SellLimit 
            if (NormalizeDouble(Price,Digits) > // If it is further than by
                NormalizeDouble(Bid+TS*Point,Digits))//..the preset value
               {
                New_Price=Bid+TS*Point;         // Its new price
                if (NormalizeDouble(SL,Digits)>0)
                  New_SL = New_Price+(SL-Price);// New StopLoss
                if (NormalizeDouble(TP,Digits)>0)
                  New_TP = New_Price-(Price-TP);// New TakeProfit
                Text= "SellLimit ";             // Modify it
               }
            break;                              // Exit 'switch'

The new parameters of the order are calculated only if the current price 'Price' is further from the current market price Bid than the desired distance TS. If it is so, the control will be passed to the body of the operator 'if' where the new open price of the order, New_Price, is calculated. The new values of StopLoss and TakeProfit are calculated only for nonzero values. The distance between the requested order price and each price of the stop order remains the same.

For example, order SellLimit is placed at 1.2050, its StopLoss = 1.2073 and its TakeProfit = 1. 2030. Suppose the calculations result in the new order open price equal to 1.2040. In this case, the new values of stop orders will be as follows: StopLoss = 1.2063, TakeProfit = 1. 2020. Thus, the program operations result in that the order is modified "as a whole" - all three basic parameters (open price, StopLoss and TakeProfit) move down simultaneously, keeping a distance between them.

At the end of block 8-9, the new values of stop orders are checked for negative values. This checking is useful if a previously placed (by another program or manually) stop order was close to zero price, for example, only 1 point above zero. In this case, if the order moves down by more than 1 point, the new price of one of the stop orders will become negative. If this value were specified in a trade request, the request would be rejected by the client terminal.

We have to point at a disadvantage of such programs - both scripts and Expert Advisors. The program modifyorderprice.mq4 above is highly limited in its action decision. The order to be modified can only be moved in one direction - in the direction of the market rate, its stop orders being strictly "anchore" to the order. This program is not adjusted to modifying of the requested order price in the direction other than the market price. The possibility to change the position of any separate stop order is not realized in the program either.

The above limitation is determined, first of all, by the amount of the controls used. In this program, there is only one control of the kind - the location where the script was attached to the symbol window. Using this parameter, the trader can determine any order to be modified. However, this is all of the user's initiative. In order to work more efficiently, the user needs additional tools allowing him or her to affect other parameters of orders.

These tasks can be quite efficiently solved using MQL4. However, you will have to use another, more "intellectual" algorithm for this purpose. It is possible to create a program that will automate your trading and modify orders in accordance with your desires. You can use in such a program, for example, graphical objects as additional controlling tools for manual trading.