moving SLs

 

Hey there,

though I am aware that there are lots of threads out there that cover this problem I just wanted someone to have a quick glimpse on my particular approach to the "moving SL after price has moved XY pips in my favor" and give me a hint as to why it is not working properly.

Not working properly means that the EA does move the SL but only one of two adjustments is made per order. Sometimes the first, sometimes the second one and that in a totally random seeming pattern. It is as if one excludes the other from being executed. If for instance price has moved 100 pips in my favor from my entry point the EA should ideally have already made two SL adjustments by that time. The first one after 20 pips, the second one after 30 pips. The EA however only makes one of them. So in a backtest result protocol a trade should typically look like this: entry -> modify a -> modify b -> exit What it does look like in practice however is this: entry -> either modify a or modify b -> exit Help would be strongly appreciated.

int start () 
{

//declaration of variables

int SL1 = 20;
int SL2 = 30;
double entry = OrderOpenPrice();
double oldSL = OrderStopLoss();
double firstSL;
double newSL;

//then follows the order selection cycle...

//and then the first Stoploss adjustment
if(SL1 > 0)
{
            if((Bid > entry + SL1 * Point) && (oldSL < entry)) 
               {               
                  int newSLinc = 10;
                  newSL = OrderOpenPrice() - newSLinc * Point * 10; //<- I have a 5 digit broker -.-'
                  firstSL = newSL;
                  if(newSL > oldSL)
                  OrderModify(OrderTicket(),OrderOpenPrice(),
                              NormalizeDouble(newSL, Digits),
                              OrderTakeProfit(),0,Green);
                  return(0);
               }
}

            //the second Stoploss adjustment
if(SL2 > 0)
{  
            if((Bid > entry + SL2 * Point) && (newSL < entry))
               {  
                  newSL = OrderOpenPrice();
                  if (newSL > firstSL)
                  OrderModify(OrderTicket(),OrderOpenPrice(),
                              NormalizeDouble(newSL, Digits),
                              OrderTakeProfit(),0,Green);
                  return(0);
               }
}
 

How do you do this . . .

double entry = OrderOpenPrice();
double oldSL = OrderStopLoss();

before . . .

//then follows the order selection cycle...

You need to use OrderSelect before you can use OOP or OrderStopLoss . . .

You need to check the return values for ALL Order operations . . including OrderModify otherwise how will you know if it fails ?

 
  1. int start () 
    {
    double entry = OrderOpenPrice();
    double oldSL = OrderStopLoss();
    You can NOT use OOP/OSL etc until you do an order select.

  2. Bid > entry + SL1 * Point
    A pip is not a point on a 5 digit broker
    //++++ These are adjusted for 5 digit brokers.
    int     pips2points;    // slippage  3 pips    3=points    30=points
    double  pips2dbl;       // Stoploss 15 pips    0.015      0.0150
    int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    int     init(){
         if (Digits % 2 == 1){      // DE30=1/JPY=3/EURUSD=5 https://www.mql5.com/en/forum/135345
                    pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
        } else {    pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; }
        // OrderSend(... Slippage.Pips * pips2points, Bid - StopLossPips * pips2dbl
    //---- These are adjusted for 5 digit brokers.
        /* On ECN brokers you must open first and THEN set stops
        int ticket = OrderSend(..., 0,0,...)
        if (ticket < 0)
           Alert("OrderSend failed: ", GetLastError());
        else if (!OrderSelect(ticket, SELECT_BY_TICKET))
           Alert("OrderSelect failed: ", GetLastError());
        else if (!OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0)
           Alert("OrderModify failed: ", GetLastError());
         */
    
 
WHRoeder:
  1. You can NOT use OOP/OSL etc until you do an order select.

  2. A pip is not a point on a 5 digit broker

1. I cannot? Coz I did. And the moveSLs work, individually. I can see that from the backtest results. They just don't do together in succession as I'd like them to. Regardless, I placed them inside the OrderSelect cycle. Nothing changed. Exactly the same trades in the tester i.e. the placement of OOP / OSL inside the code had no influence at all over the outcoming results.

2. Your favorite line. I multiplied every mention of Point as well as slippage, takeprofit and SL with *10 or *Point*10 respectively-> Nothing changed. Exactly the same trades in the tester i.e. pip to points conversion didn't affect the outcoming results in anyway.

I deleted any historical data from the tester suspecting an error there but the backtests return exactly the same results. It has to be something about the way I formulated the moveSL if-conditions...

 
Yojimbo:

1. I cannot?

OrderOpenPrice quote from the documentation . . . "Order must be first selected by the OrderSelect() function."
 
Yojimbo:

1. I cannot? Coz I did. [...]

The point is that yes, syntactically you can do this, but you shouldn't because the results are unpredictable if you use OrderOpenPrice() without first using OrderSelect(). If it's working then it's probably because you do a call to OrderSelect() later, and that selection is maintained for subsequent calls to start(). That would probably break outside of backtesting, and it's also liable to break inside backtesting because you're relying on how MT4 happens to work, not how the documentation says that it does and will work.

From context it looks as though your EA opens one order at a time. From the code excerpt you've given us, it's impossible to be certain that OrderOpenPrice() and OrderStopLoss() are going to be referring to the order which is currently open rather than one of the orders which have been closed. The cause of your "random" behaviour could be that, under some circumstances, the code is trying to modify a recently closed order rather than the currently-open order.

It would also help more generally if you log what the code is doing, and the results of the OrderModify(). At the moment you don't know - or at least you aren't telling us - whether the SL1 and SL2 blocks aren't getting activated at all, or are getting activated but the OrderModify() isn't succeeding.

 
jjc:

The point is that yes, syntactically you can do this, but you shouldn't because the results are unpredictable if you use OrderOpenPrice() without first using OrderSelect(). If it's working then it's probably because you do a call to OrderSelect() later, and that selection is maintained for subsequent calls to start(). That would probably break outside of backtesting, and it's also liable to break inside backtesting because you're relying on how MT4 happens to work, not how the documentation says that it does and will work.

From context it looks as though your EA opens one order at a time. From the code excerpt you've given us, it's impossible to be certain that OrderOpenPrice() and OrderStopLoss() are going to be referring to the order which is currently open rather than one of the orders which have been closed. The cause of your "random" behaviour could be that, under some circumstances, the code is trying to modify a recently closed order rather than the currently-open order.

It would also help more generally if you log what the code is doing, and the results of the OrderModify(). At the moment you don't know - or at least you aren't telling us - whether the SL1 and SL2 blocks aren't getting activated at all, or are getting activated but the OrderModify() isn't succeeding.


Thank you very much for your insightful reply. I'll start over from scratch and add features one by one to get to the root of the problem. In the meanwhile I'll upload the mq4 for you guys to have a look at it.

Files:
ea.mq4  10 kb
 
Yojimbo:
1. I cannot? Coz I did.
You can't divide by zero either. This code will compile but will stop your EA dead.
double zero = 0.;
double one  = 1.;
Print(one/zero);
Just because it compiles doesn't mean it works correctly.
 
WHRoeder:
You can't divide by zero either. This code will compile but will stop your EA dead. Just because it compiles doesn't mean it works correctly.
I am not assuming that the EA and it's OrderModifys work because it compiles. Never said that. I assume the EA's OrderModifys work because I did backtests that produce trading logs that clearly state the word "modify" with the SLs actually being moved. Again, the moveSL commands are executed i.e. EA does modify orders individually. But not always and never consecutively like I want to.
 
You said
I cannot? Coz I did.
You didn't. The values you were using were either totally bogus, or were from the last select - totally out of date. Modifies might have moved the stops, but not where you wanted them.
 
WHRoeder:
You said You didn't. The values you were using were either totally bogus, or were from the last select - totally out of date. Modifies might have moved the stops, but not where you wanted them.

Wrong. The modifies moved the stops exactly where I wanted them. The problem is that the modifies didn't always trigger.

And yes I did - place the OOP and OSL outside of the order selection loop - and I've already stated that moving them to inside the loop according to the backtest results didn't change the outcome. I am not saying that this is the correct use and practice but there has to be something else missing. Your mention about "the last select" and "outdated" might be the clue.

Reason: