MT5 CloseBy on multicurrency EAs

 

Hello again, probably some of you are hating me for all my requests and doubts about mt5 and I'm sorry for this. Since my first tests on mt5 I found some bug on CloseBy functions (ONLY WHEN WORKING WITH MULTISYMBOLS EA!).

I explain better, if my EA open trades only on one pair and I want to closeby them I have no problem, but if my EA open trades at the sime time on multi pairs, at the time of calling the closeby function orders are closed correctly but the profit calculations and close prices about closeby orders is totally wrong and produce wrong results on balance.

It seems that the CloseBy functions produces deals on the wrong symbol, and from logs I can see that it is exactly in this way.

This is the part of my code that trigger the CloseBy function.

void closeOrdersLIFOHedge()   {
   while(orderOpen("ALL")) {
      while(SelectBiggestOrder())
         {
            bool res=false;
            int retries=0;
            
            ulong                oTicket = m_pos.Ticket();
            ENUM_POSITION_TYPE   oType   = (ENUM_POSITION_TYPE)m_pos.PositionType();
            double               oSize   = m_pos.Volume();
            string               oSymbol = m_pos.Symbol();
            ulong                hTicket = 0;
            
            if( SymbolInfoInteger(oSymbol, SYMBOL_ORDER_MODE) && SYMBOL_ORDER_CLOSEBY != 0 ) {
               // Search for opened hedge order
               for(int k= PositionsTotal()-1; k>=0; k--) {
                  if( !m_pos.SelectByIndex(k) || m_pos.Magic()!=magicNumber || m_pos.PositionType()==oType ) continue;
                  if( m_pos.Symbol()==oSymbol && m_pos.Volume()==oSize ) {
                     hTicket = m_pos.Ticket();
                     break;
                  }
               }
               // Try closeby if hedge order found
               if( hTicket>0 ) {
                  do
                        {
                           Print("!!! PROCESSING CLOSEBY "+oSymbol+" #"+(string)oTicket+","+(string)hTicket);
                           res=m_trade.PositionCloseBy(oTicket,hTicket);
                           if(!res) {
                              Print("Closing order #"+(string)oTicket+" by #"+(string)hTicket+" failed, error: "+(string)GetLastError());
                              Sleep(100);
                           }
                           retries++;
                        }
                  while(!res && retries<maxRetries);
               }
     	}
   }
}

I've checked also the code of the CTrade.mqh "CTrade::PositionCloseBy" and I've seen that in the m_request that it generates, the information of symbol is missing.

I've tried (just for test) to adding symbol to the m_request in the CTrade.mqh file and it started to works correctly.

Now the question is: is it a bug in the library or do I need to setting the parameter to m_request and it's not enough to call m_trade.PositionCloseBy(ticket,ticket_by)?

Thanks to all

 

Maybe it is time to accept that when things do not work as expected it is not a bug, but mistake on coder side 99,9% of the time.

When working with trade class, set the symbol first before doing trade operations. Seems yours is set at GBPAUD while your trade operations are targeted towards other symbols.

 
Enrique Dangeroux:

Maybe it is time to accept that when things do not work as expected it is not a bug, but mistake on coder side 99,9% of the time.

When working with trade class, set the symbol first before doing trade operations. Seems yours is set at GBPAUD while your trade operations are targeted towards other symbols.

I never said it is a bug but I'm simply asking if I did something wrong, and in case, how can I assign symbol to the m_request object. symbol is assigned only to m_request in PositionOpen ClosePosition ClosePartial on CTrade but not in the CloseBy one. Ye can consider that is not needed to be done due to passes specific positions tickets, but... this is what happens.

m_trade object has GBPAUD as symbol select because probably it was the last position I opened, but why CloseBy need also to specific a symbol to work correctly? If I specify tickets that are unique there is no need to specify also symbol. 

PS. I don't know how it can possible that m_request contains my latest symbol order sent. There is a clear structures function before assigning values to m_request.

//+------------------------------------------------------------------+
//| Close one position by other                                      |
//+------------------------------------------------------------------+
bool CTrade::PositionCloseBy(const ulong ticket,const ulong ticket_by)
  {
//--- check stopped
   if(IsStopped(__FUNCTION__))
      return(false);
//--- check hedging mode
   if(!IsHedging())
      return(false);
//--- check position existence
   if(!PositionSelectByTicket(ticket))
      return(false);
   string symbol=PositionGetString(POSITION_SYMBOL);
   ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
   if(!PositionSelectByTicket(ticket_by))
      return(false);
   string symbol_by=PositionGetString(POSITION_SYMBOL);
   ENUM_POSITION_TYPE type_by=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
//--- check positions
   if(type==type_by)
      return(false);
   if(symbol!=symbol_by)
      return(false);
//--- clean
   ClearStructures();
//--- check filling
   if(!FillingCheck(symbol))
      return(false);
//--- setting request
   m_request.action     =TRADE_ACTION_CLOSE_BY;
   m_request.position   =ticket;
   m_request.position_by=ticket_by;
   m_request.magic      =m_magic;
//--- close position
   return(OrderSend(m_request,m_result));
  }
 

There is a flaw in you ticket loop. You assign a ticked while the previous iteration of the loop is selecting the ticket.

And there is more issues, first you 

 oSymbol = m_pos.Symbol()

then you 

if( m_pos.Symbol()==oSymbol ...

This will always return true. Why do it?

There may be other issues as well but my head hurts with all this fuzzy logic.

I will leave the rest for @Vladimir Karputov ;)

 

I cycle all positions and for each one I cycle again all positions to checking if there is an opposite one in order to trigger closeby.

oSymbol contain information about the "Main" order, m_pos.Symbol() return symbol of current selected position, if they are the same I check the size, If they are equals I trigger the closeby.

What's wrong?

 

I've had a lot of tries with the code, I've also tried to initialize a new CTrade object before each new CloseBy function but it not solved the issue.

The only thing that can solve the issue is adding this line in Trade.mqh (I see that in all other functions the symbol parameters is always set to the request variable, but not in PositionCloseBy)

bool CTrade::PositionCloseBy(const ulong ticket,const ulong ticket_by)
  {
//--- check stopped
   if(IsStopped(__FUNCTION__))
      return(false);
//--- check hedging mode
   if(!IsHedging())
      return(false);
//--- check position existence
   if(!PositionSelectByTicket(ticket))
      return(false);
   string symbol=PositionGetString(POSITION_SYMBOL);
   ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
   if(!PositionSelectByTicket(ticket_by))
      return(false);
   string symbol_by=PositionGetString(POSITION_SYMBOL);
   ENUM_POSITION_TYPE type_by=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
//--- check positions
   if(type==type_by)
      return(false);
   if(symbol!=symbol_by)
      return(false);
//--- clean
   ClearStructures();
//--- check filling
   if(!FillingCheck(symbol))
      return(false);
//--- setting request
   m_request.action     =TRADE_ACTION_CLOSE_BY;
   m_request.symbol     =symbol;   
   m_request.position   =ticket;   
   m_request.position_by=ticket_by;
   m_request.magic      =m_magic;
//--- close position
   return(OrderSend(m_request,m_result));
  }

And this is the correct result.

It seems absurd to me the need to edit Trade.mqh file which is certainly written by more competent people than me and it seems to me equally absurd that no one has ever had a similar issue...

The most obvious thing that I am ready to admit is that I have made some mistakes but so far the only thing that has solved the problem is the one written above

 

You use "while" - for such a code you need to beat your hands.

CTrade :: PositionCloseBy operates on TWO tickets (const ulong ticket, const ulong ticket_by). You are fully responsible for choosing tickets.


Look for problems in your code.

 

Tickets are choosen correctly and in the same way in both cases.

Not specifying symbol for closeby is quiet obvious due to the fact that ticket numbers are unique, but it's not obvious that mt5 produce deals on wrong symbol if I don't modify the CTrade::PositionCloseBy function, adding the right symbol.

I attach a very simple EA in which I reproduced the issue.

PS. I manually put ticket number in closeby function because I opened them sequentially in the oninit function (like what you did in an old example EA that you sent me.)


Files:
 
Fabio Cavalloni:

Tickets are choosen correctly and in the same way in both cases.

Not specifying symbol for closeby is quiet obvious due to the fact that ticket numbers are unique, but it's not obvious that mt5 produce deals on wrong symbol if I don't modify the CTrade::PositionCloseBy function, adding the right symbol.

I attach a very simple EA in which I reproduced the issue.

PS. I manually put ticket number in closeby function because I opened them sequentially in the oninit function (like what you did in an old example EA that you sent me.)


You are right, there is a bug in the standard library PositionCloseBy(). (Actually it is a bug in the underlying MqlTradeRequest).
 
Fabio Cavalloni :

Tickets are choosen correctly and in the same way in both cases.

Not specifying symbol for closeby is quiet obvious due to the fact that ticket numbers are unique, but it's not obvious that mt5 produce deals on wrong symbol if I don't modify the CTrade::PositionCloseBy function, adding the right symbol.

I attach a very simple EA in which I reproduced the issue.

PS. I manually put ticket number in closeby function because I opened them sequentially in the oninit function (like what you did in an old example EA that you sent me.)


Thanks for the short and clear example.

 

@Fabio Cavalloni Just stumbled on this thread by coincidence, not sure how i missed this but Fabio, please accept my apologies. While i stand by my post, in this case i was wrong. Even though i am a guy, i am woman enough to admit i am wrong ;)

Ill be eating my left shoe, please allow me a pinch of salt and pepper.

Reason: