2
votes

I'm trying to ADD a stop loss to my open market orders in MetaTrader 4 when a position gets 100 pips "to the good" which is to be equal to the Order Open Price;

OrderStopLoss() == OrderOpenPrice()

But this isn't happening.

I've added Print() & GetLastError() functions and nothing is coming up in the journal, so it must be something in my coding - but cannot see what would be wrong.

OK this is what I have so far, one for loop for the buy, one for the sell. I've also Normalized the "doubles" as I have been advised to do & have also declared the BuyMod & SellMod to "true" at the very top. This should ensure that the default won't resort to false. I also thought it might be helpful if I told you I have the MetaEditor version 5 build 1241:)

The following code I have is the following;

/*Breakeven Order Modification*/
bool BuyMod               =  true;
bool SellMod              =  true;
                for(int b = OrdersTotal()-1;b>=0;b--)
                {
                if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
                   {
                   double   aBidPrice   =  MarketInfo(Symbol(),MODE_BID);
                   double   anOpenPrice =  OrderOpenPrice();
                   double   aNewTpPrice =  OrderTakeProfit();
                   double   aCurrentSL  =  OrderStopLoss();
                   double   aNewSLPrice =  anOpenPrice;
                   double   pnlPoints   =  (aBidPrice - anOpenPrice)/_Point;
                   double   stopPoints  =  (aBidPrice - aNewSLPrice)/_Point;
                   int      stopLevel   =  int(MarketInfo(Symbol(),MODE_STOPLEVEL));
                   int      aTicket     =  OrderTicket();
                   if(OrderType() == OP_BUY)
                   if(stopPoints >= stopLevel)
                   if(aTicket > 0)
                   if(pnlPoints >= breakeven)
                   if(aNewSLPrice != aCurrentSL)
                      {
                      BuyMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,buycolor);
                      SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
                      }
                   }
                }
                for(int s = OrdersTotal()-1; s>=0; s--)
                {
                if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))
                   {
                   double   anAskPrice  =  MarketInfo(Symbol(),MODE_ASK);
                   double   anOpenPrice =  OrderOpenPrice();
                   double   aNewTpPrice =  OrderTakeProfit();
                   double   aCurrentSL  =  OrderStopLoss();
                   double   aNewSLPrice =  anOpenPrice;
                   double   pnlPoints   =  (anOpenPrice - anAskPrice)/_Point;
                   double   stopPoints  =  (aNewSLPrice - anAskPrice)/_Point;
                   int      stopLevel   =  int(MarketInfo(Symbol(),MODE_STOPLEVEL));
                   int      aTicket     =  OrderTicket();
                   if(OrderType()== OP_SELL)
                   if(stopPoints >= stopLevel)
                   if(pnlPoints >= breakeven)
                   if(aNewSLPrice != aCurrentSL)
                   if(aTicket > 0)
                      {
                      SellMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,sellcolor);
                      SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
                      }
                   }
                }

trading algorithmic-trading mql4 metatrader4

shareeditdeleteflag

edited just now

asked 2 days ago

Todd Gilbey 264

You might want to know, StackOverflow does not promote duplicate questions. ( see the

3
On updated code-segment: the tp issue is still there, the Print() right after OrderModify() is still missing.user3666197
While StackOverflow is not a Do-a-Homework site, let me propose a few directions for the solution in the update belowuser3666197
I'm sorry, what tp issue & I want to Print all errors when the Order Modify fails. The reason I'm just so confused right now is because this is the same format as with the OrderClose & there were no issues. I have a fully coded strategy which is extremely profitable. Now I'm adding this piece to it & I don't see why this so stupidly hard to implement.user6216142
The tp issue was explained in your 2nd or 3rd question on this same subject >>> stackoverflow.com/a/36743552/3666197 Plus your updated code still does zero self-diagnostics on values used in a OrderModify() call and GetLastError(). There could hardly be other method to diagnose the root cause of the trouble than to perform these two steps. Or hire some professional service in this field to cover your issues by knowledge outsourcing. Having a few hundreds man*years experience in the team, no one can have the same, identical knowledgebase. But one sure can buy the missing parts.user3666197
Let me also remark, that OrderClose() has by far a very different function call signature, than that of OrderModify(). Check the MQL4 IDE documentation and review carefully the differences.user3666197

3 Answers

1
votes

Besides meeting an MQL4 syntax-rules,
there are more conditions:


A first hidden trouble is in number rounding issues.

MetaQuotes, Inc., recommends wherever possible, to normalise float values into a proper price-representation.

Thus,
wherever a price goes into a server-side instruction { OrderSend(), OrderModify(), ... } one shall always prepare such aPriceDOMAIN value
by a call to NormalizeDouble( ... , _Digits ), before a normalised price hits any server-side instruction call.

May sound rather naive, but this saves you issues with server-side rejections.

Add NormalizeDouble() calls into your code on a regular base as your life-saving vest.


A second, even a better hidden trouble is in STOP_ZONE-s and FREEZE_ZONE-s

While not visible directly, any Broker set's in their respective Terms & Conditions these parameters.

In practice,
this means, if you instruct { OrderSend() | OrderModify() } to set / move aPriceDOMAIN level to be setup too close to current actual Ask/Bid ( violating a Broker-forbidden STOP_ZONE )
or
to delete / modify aPriceDOMAIN level of TP or SL, that are already set and is right now, within a Broker-forbidden FREEZE_ZONE distance from actual Ask/Bid,
such instruction will not be successfully accepted and executed.

So besides calls to the NormalizeDouble(), always wait a bit longer as the price moves "far" enough and regularly check for not violating forbidden STOP_ + FREEZE_ zones before ordering any modifications in your order-management part of your algotrading projects.

Anyway, Welcome to Wild Worlds of MQL4

Update: while StackOverflow is not a Do-a-Homework site, let me propose a few directions for the solution:

for ( int b = OrdersTotal() - 1; b >= 0; b-- ) // ________________________ // I AM NOT A FAN OF db.Pool-looping, but will keep original approach for context purposes
{     if (  ( OrderSelect( b, SELECT_BY_POS, MODE_TRADES ) ) == true )
      {    // YES, HAVE TO OPEN A CODE-BLOCK FOR if()-POSITIVE CASE:
           // ------------------------------------------------------
              double aBidPRICE   = MarketInfo( Symbol(), MODE_BID );       // .UPD
              double anOpenPRICE     = OrderOpenPrice();                   // .SET FROM a db.Pool Current Record
              double aNewTpPRICE     = OrderTakeProfit();                  // .SET FROM a db.Pool Current Record
              double aCurrentSlPRICE = OrderStopLoss();                    // .SET FROM a db.Pool Current Record
              double aNewSlPRICE     = anOpenPRICE;                        // .SET
              double  pnlPOINTs      = ( aBidPRICE - anOpenPRICE )/_Point; // .SET
              double stopPOINTs      = ( aBidPRICE - aNewSlPRICE )/_Point; // .SET
           // ------------------------------------------------------------ // .TEST
              if (                        OP_BUY    == OrderType()        )
                   if (                   Period()  == OrderMagicNumber() )
                        if (             stopPOINTa >  stopLevel          )
                             if (         pnlPOINTs >= breakeven          )
                                  if (  aNewSlPRICE != aCurrentSlPRICE    )
                                  {  // YES, HAVE TO OPEN A BLOCK {...}-CODE-BLOCK FOR THE if()if()if()if()-chain's-POSITIVE CASE:
                                     // -------------------------------------------------------------------------------------------
                                        int aBuyMOD = OrderModify( OrderTicket(),
                                                                   OrderOpenPrice(),
                                                                   NormalizeDouble( aNewSlPRICE, Digits ),
                                                                   NormalizeDouble( aNewTpPRICE, Digits ),
                                                                   0,
                                                                   buycolor
                                                                   );
                                        switch( aBuyMOD )
                                        {   case ( NULL  ): { ...; break; } // FAIL ( ANALYSE ERROR )
                                            default:        { ...; break; } // PASS OrderModify()
                                        }
      }
}
0
votes

The problem is in your call to a built-in OrderModify() function.

OrderStopLoss() == OrderModify() will evaluate as false which in turn will evaluate as 0 since == is a comparison operator.

An OrderStopLoss() is a call to another built-in function (not a variable), you can't save anything to it so OrderStopLoss() = 4 wouldn't work either.

From the MQL4 documentation:

bool  OrderModify( int        ticket,      // ticket 
                   double     price,       // price 
                   double     stoploss,    // stop loss 
                   double     takeprofit,  // take profit 
                   datetime   expiration,  // expiration 
                   color      arrow_color  // color 
                   );

In your case that would be the following, assuming ModBuy is already defined somewhere in the code:

ModBuy = OrderModify(  OrderTicket(),      // <-ticket from record OrderSelect()'d
                       OrderOpenPrice(),   // <-price  from current record
                       OrderOpenPrice(),   // <-price  from current record
                       OrderTakeProfit(),  // <-TP     from current record
                       0,                  // ( cannot set P/O expiration for M/O )
                       buycolor            // ( set a color for a GUI marker )
                       );

Or you could just use any other valid value instead of the second OrderOpenPrice() to set a new stoploss.

0
votes

I'm really sorry, I'm new to Stackoverflow, this is the revised code I now have based on everyone's comments & recommendation's below

 **Local Declarations**
  pnlPoints            =  0;
  point                =  MarketInfo(Symbol(),MODE_POINT);
  stopLevel            =  int(MarketInfo(Symbol(),MODE_STOPLEVEL)+MarketInfo (Symbol(),MODE_SPREAD));
  sl                   =  NormalizeDouble(OrderStopLoss(),Digits);
  tp                   =  OrderTakeProfit();
  cmd                  =  OrderType();
  breakeven            =  100;

  **Global Variables**
  double   pnlPoints;
  double   price,sl,tp;
  double   point;
  int      stopLevel;
  int      cmd;
  int      breakeven;
  double   newSL;
                for(int b = OrdersTotal()-1; b>=0; b--)
                {
                if((OrderSelect(b,SELECT_BY_POS,MODE_TRADES))==true)
                price = MarketInfo(Symbol(),MODE_BID);
                newSL = NormalizeDouble(OrderOpenPrice(),Digits);
                pnlPoints = (price - OrderOpenPrice())/point;
                   {
                   if(OrderType()==OP_BUY)
                      if(OrderMagicNumber() == Period())
                         if((price-newSL)/point>=stopLevel)
                            if(pnlPoints>=breakeven)
                               if(sl!=newSL)
                                  ModBuy = OrderModify(OrderTicket(),OrderOpenPrice(),newSL,tp,buycolor);
                                   else if(ModBuy == false)
                                   {
                                   Print("OrderModify failed with error #",GetLastError());
                                   }
                   }              
                }