2

I have trouble with modifying the stoploss of a running trade using MQL5. Selecting the order works out for me. But if I try to access the variables ( for instance OrderTicket() & OrderOpenPrice() ), it always returns 0.00000:

2017.06.01 00:06:32.114 2016.04.08 00:00:00   failed modify  buy 0.00  sl: 0.00000, tp: 0.00000 -> sl: 1.41594, tp: 0.00000 [Invalid request]

Here's my stoploss modyfing void:

void modifyStops() {

   int total = OrdersTotal();          // total number of placed pending orders
   Print( total + " Orders on the line!!!" );

   //--- Over all placed pending orders
   for ( int i = 0; i <  total; i++ )
   {     bool isOrderSelected = OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
         if (  isOrderSelected )
         {  // TODO: Check the Trades to contain the correct Order Number

               Print( "Symbol & Magicnumber matching" );
               double newStopLoss;

            // Update the stop loss
               if (  OrderType() == OP_BUY )
               {
                     newStopLoss = addTolerance( SL );
               } 
               else if (  OrderType() == OP_SELL )
               {
                          newStopLoss = minusTolerance( SL );
               }       
               newStopLoss = NormalizeDouble( newStopLoss, Digits );
               Print( "NEW STOP LOSS::::=====> ", Symbol(), " at ", newStopLoss );

               if ( !OrderModify( OrderTicket(), OrderOpenPrice(), newStopLoss, OrderTakeProfit(), 0, Green ) )
               {
                     Print( "OrderModify returned the error of ", GetLastError() );
               }  
     }
}

The CTrade class isn't working properly for me. I tried to implement the code you've posted - however: It still doesn't seem to work out.

Unfortunately I implemented that in my EA and the OrderGetTicket(i) returns zero when the trade is live. So my void looks like this:

void modifyStops() {
for(int i=0; i<PositionsTotal();i++) 
    {
    ulong ticket;
    if((ticket=PositionGetTicket(i))>0) 
        { 
         //--- return order properties 
         double open_price    =PositionGetDouble(POSITION_PRICE_OPEN); 
         datetime time_open     =(datetime)PositionGetInteger(POSITION_TIME); 
         string symbol        =PositionGetString(POSITION_SYMBOL); 
         int order_magic   =PositionGetInteger(POSITION_MAGIC); 
         double volume        =PositionGetDouble(POSITION_VOLUME); 
         double stoploss      =PositionGetDouble(POSITION_SL); 
         double takeprofit    =PositionGetDouble(POSITION_TP); 
         ENUM_ORDER_TYPE type          =EnumToString(ENUM_ORDER_TYPE(PositionGetInteger(POSITION_TYPE))); 
         //--- prepare and show information about the order 
         printf("#ticket %d %s %G %s at %G, with sl: %G tp: %G was set up at %s", 
                ticket,                 // order ticket 
                type,                   // type 
                volume,                 // placed volume 
                symbol,                 // symbol 
                open_price,             // specified open price
                stoploss,               //
                takeprofit,             // 
                TimeToString(time_open) // time of order placing 
                ); 
        } 
    }
}

And the printf function returns nothing:

2017.06.02 01:42:26.910 2016.04.07 00:00:00   #ticket 1 (non-string passed) 0  at 0, with sl: 0 tp: 0 was set up at 1970.01.01 00:00

I can't believe it's that hard to simply modify an SL in MQL5. That's horribly. However I need to get through it to test my strategy over several pairs...

Do you have another idea? I set up trades with the following code:

void createPendingOrder(ENUM_ORDER_TYPE orderType, double lots, double stopLoss) {
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};

//--- parameters to place a pending order
   request.action   =TRADE_ACTION_PENDING;                             // type of trade operation
   request.symbol   =Symbol();                                         // symbol
   request.volume   =lots;                                             // volume of 0.1 lot
   //request.deviation=2;                                              // allowed deviation from the price
   request.magic    =224466      ;                                     // MagicNumber of the order
   //int offset = 3;                                                   // offset from the current price to place the order, in points
   double price;                                                       // order triggering price
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);                // value of point
   int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);                // number of decimal places (precision)
   //--- checking the type of operation
   if(orderType==ORDER_TYPE_BUY_STOP)
     {
      request.type         =ORDER_TYPE_BUY_STOP;                            // order type
      price                =entryPrice;   
      request.price        =NormalizeDouble(price,digits);                      // normalized opening price 
      request.sl           =stopLoss;
     }
   else if(orderType==ORDER_TYPE_SELL_STOP)
     {
      request.type         =ORDER_TYPE_SELL_STOP;                           // order type
      price                =entryPrice;           
      request.price        =NormalizeDouble(price,digits);                  // normalized opening price 
      request.sl           =stopLoss;
     }
   else Alert("This example is only for placing pending orders");   // if not pending order is selected
//--- send the request
   if(!OrderSend(request,result))
      PrintFormat("OrderSend error %d",GetLastError());                 // if unable to send the request, output the error code
//--- information about the operation
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
}

Would it for instance be possible to save the result object in a Array and then access the running trade through that object?

kenorb
  • 155,785
  • 88
  • 678
  • 743
Aurus
  • 173
  • 1
  • 5
  • 12
  • functions minusTolerance(SL) and addTolerance() - do they loop over trades? check ticket number at start and before sending modify request – Daniel Kniaz Jun 01 '17 at 05:50
  • Thanks for your answer. MinusTolerance and addTolerance only add a few pips to a fixed stop price. There's no loop in these double methods. Like you can see in the first code section of the post - The selection of the order works without an Error, but the Variables don't contain any value. For example OrderTicket(), OrderOpenPrice(), or OrderStopLoss() all contain zero. – Aurus Jun 01 '17 at 07:56
  • yes i understand the problem, that is why i adviced to check ticket at start and before sending. by the way, is it mql5 or mql4? Print("symbol and magic match "+OrderTicket()); to make sure it selects the right ticket – Daniel Kniaz Jun 01 '17 at 08:10
  • I firstly had another filter line where I checked whether Pair and Magic Number matched, but the funny part was: Whenever the trades went live - so they have been executed and not a pending order anymore - the OrderMagicNumber() was null and the same went for the Ordersymbol(). While the order was pending and unexecuted These methods return the correct values... – Aurus Jun 01 '17 at 08:20
  • It is MQL5 btw. Okay I'll check the OrderTicket. What is it supposed to return? – Aurus Jun 01 '17 at 08:28
  • either something wrong with your broker (that changes tickets magic), but i do not think so as magic is stored in client mt4 as far as i know, or you are doing sth wrong. so please provide a piece of code that can be compiled, executed, and still has a problem, and we will try to advice. now - this piece of code seems fine (except looping from 0 is bad practice, start from OrdersTotal()-1 to >=0 – Daniel Kniaz Jun 01 '17 at 08:29
  • MQL5 do not have OrderSelect(i,SELECT_BY_POS) as far as i remember, it requires only 1 parameter (ticket id, ulong) – Daniel Kniaz Jun 01 '17 at 08:30
  • You're right with that one. In the documentation it says the only parameter for OrderSelect is the TicketID. I'll check that this evening and post some further code if I don't manage to get it running. I also read somewhere that I might have to make a cross at allow the EA to do live trading (even though its only in the strategy tester). I'm now guessing that the problem is that I call OrderSelect with invalid Parameters and only would need to call it with the "i". Gonna test that too and post an update. Thanks for your help. – Aurus Jun 01 '17 at 09:00
  • in tester it doesnt matter if you allow trading or not, on demo account - yes you need to make ea smiling – Daniel Kniaz Jun 01 '17 at 09:37

1 Answers1

6

Your problem is you are trying to run MQL4 code in MQL5.

There are no OrderModify(), OrderOpenPrice(), OrderTicket() in MQL5!!!

See the documentation here on how to select, query values and modify trades.

you will need to be using OrderGetDouble(), OrderGetInteger() and OrderGetString() to query open price, stop loss etc. e.g.

if((ticket=OrderGetTicket(i))>0) 
    { 
     //--- return order properties 
     open_price    =OrderGetDouble(ORDER_PRICE_OPEN); 
     time_setup    =(datetime)OrderGetInteger(ORDER_TIME_SETUP); 
     symbol        =OrderGetString(ORDER_SYMBOL); 
     order_magic   =OrderGetInteger(ORDER_MAGIC); 
     positionID    =OrderGetInteger(ORDER_POSITION_ID); 
     initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL); 
     type          =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE))); 
     //--- prepare and show information about the order 
     printf("#ticket %d %s %G %s at %G was set up at %s", 
            ticket,                 // order ticket 
            type,                   // type 
            initial_volume,         // placed volume 
            symbol,                 // symbol 
            open_price,             // specified open price 
            TimeToString(time_setup)// time of order placing 
            ); 
    } 

Orders are modified using the OrderSend() function https://www.mql5.com/en/docs/trading/ordersend

Update

MQL5 uses a much more complex system of Orders, Positions, Deals and historyOrders. An MQL5 community article attempts to explain how they all relate to one another.

  • Orders = Pending trades (Buy Stop, Buy Limit, Sell Stop, Sell Limit)
  • Positions = Open trades (Buy, Sell)
  • HistoryOrders = Closed/Deleted Trades
  • Deals = transactions that make up an order/position

To loop through and look at pending Orders:

for(int i=0; i<OrdersTotal();i++) 
    {
    if((ticket=OrderGetTicket(i))>0) 
        { 
         //--- return order properties 
         open_price    =OrderGetDouble(ORDER_PRICE_OPEN); 
         time_setup    =(datetime)OrderGetInteger(ORDER_TIME_SETUP); 
         symbol        =OrderGetString(ORDER_SYMBOL); 
         order_magic   =OrderGetInteger(ORDER_MAGIC); 
         positionID    =OrderGetInteger(ORDER_POSITION_ID); 
         initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL); 
         type          =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE))); 
         //--- prepare and show information about the order 
         printf("#ticket %d %s %G %s at %G was set up at %s", 
                ticket,                 // order ticket 
                type,                   // type 
                initial_volume,         // placed volume 
                symbol,                 // symbol 
                open_price,             // specified open price 
                TimeToString(time_setup)// time of order placing 
                ); 
        } 
    }

To loop through and look at open trades:

for(int i=0; i<PositionsTotal();i++) 
    {
    if((ticket= PositionGetTicket(i))>0) 
        { 
         //--- return order properties 
         open_price    =PositionGetDouble(POSITION_PRICE_OPEN); 
         time_open     =(datetime)PositionGetInteger(POSITION_TIME); 
         symbol        =PositionGetString(POSITION_SYMBOL); 
         order_magic   =PositionGetInteger(POSITION_MAGIC); 
         volume        =PositionGetDouble(POSITION_VOLUME); 
         stoploss      =PositionGetDouble(POSITION_SL); 
         takeprofit    =PositionGetDouble(POSITION_TP); 
         type          =EnumToString(ENUM_ORDER_TYPE(PositionGetInteger(POSITION_TYPE))); 
         //--- prepare and show information about the order 
         printf("#ticket %d %s %G %s at %G, with sl: %G tp: %G was set up at %s", 
                ticket,                 // order ticket 
                type,                   // type 
                volume,                 // placed volume 
                symbol,                 // symbol 
                open_price,             // specified open price
                stoploss,               //
                takeprofit,             // 
                TimeToString(time_open) // time of order placing 
                ); 
        } 
    }

Hopefully, someone else will be able to provide a better explanation of Orders, Positions, Deals, history Orders as they still give me a headache.

To make it simpler I usually just create an instance of the CTrade Class

Update2

Minimal example of trailSL for buy Positions using standard trade functions and Ctrade class

Init

Ctrade *m_trade;
CSymbolInfo *m_symbol;
Void OnInit()
{
    m_trade  = new Ctrade();
    m_trade.SetExpertMagicNumber(100);
    m_symbol = new CSymbolInfo();
    m_symbol.Name(Symbol());
}
void OnTick()
{
   m_symbol.RefreshRates();
}

Trail SL of Buy trade with standard functions

void modifysl()
  {
   ulong ticket;
   MqlTradeRequest request = {0};
   MqlTradeResult  result  = {0};
   double newsl;

   for(int i=0; i<PositionsTotal();i++)
     {
      ticket=PositionGetTicket(i);
      if(ticket>0)
        {
         request.action   = TRADE_ACTION_SLTP; // type of trade operation
         request.position = ticket;   // ticket of the position
         request.symbol   = PositionGetString(POSITION_SYMBOL);     // symbol 
         request.sl       = PositionGetDouble(POSITION_SL);                // Stop Loss of the position
         request.tp       = PositionGetDouble(POSITION_TP);                // Take Profit of the position
         request.magic    = 100;                                    // MagicNumber of the position

   
         newsl = NormalizeDouble(m_symbol.Bid()-100*m_symbol.Point(),
                                 m_symbol.Digits());
         if(newsl>request.sl)
           {
            request.sl = newsl;
            if(!OrderSend(request,result))
              {
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
              }
            //--- information about the operation   
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
           }
        }
     }
  }

Trail Buy Position StopLoss using CTrade

void modifyslCtrade()
  {
   ulong ticket;
   MqlTradeRequest request= {0};
   MqlTradeResult response ={0};
   double newsl;

   for(int i=0; i<PositionsTotal();i++)
     {
      ticket=PositionGetTicket(i);
      if(ticket>0)
        {
         newsl = NormalizeDouble(m_symbol.Bid()-100*m_symbol.Point(),
                                 m_symbol.Digits());
         if(newsl>PositionGetDouble(POSITION_SL))
           { 
            m_trade.PositionModify(ticket,
                                   newsl,
                                   PositionGetDouble(POSITION_TP));
           }
        }
     }
  }
Community
  • 1
  • 1
rgunning
  • 568
  • 2
  • 16