Close by opposite signal (multisymbol)

 

Hi there, I'm trying to implement a reversal close module into my new advisor.

This is a multipair advisor and all the algorithm is working into this loop, where the value for _Symbol is 'SName':

   for(int s=0;s<SymbolsTotal(true);s++){
      string SName=SymbolName(s,true);

The code is working fine on backtest, there's a buy and a sell signal when the condition is met, so I wrote a few lines to close the first order when there are more than one deal from the same symbol (SName'), cause they would be opposite:

      for(int i=0;i<PositionsTotal();i++){
         ulong iTicket=PositionGetTicket(i);
         if(PositionSelectByTicket(iTicket)&&
         PositionGetString(POSITION_SYMBOL)==SName){
            if(PositionsTotal()>1){
               if(!trade.PositionClose(iTicket,ULONG_MAX)){
                  Print("PositionClose error ",trade.ResultRetcode());
                  return;
                  }
               }
            }
         }

The matter what's happening on my demo account is when there is a new deal, the first one is closed no matter the symbol and don't actually know why. Can anybody check this lines for if there is any mistake?

Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Account Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Account Properties
  • www.mql5.com
, then each symbol positions will be closed in the same order, in which they are opened, starting with the oldest one. In case of an attempt to close positions in a different order, the trader will receive an appropriate error. There are several types of accounts that can be opened on a trade server. The type of account on which an MQL5 program...
 
David Diez :

Hi there, I'm trying to implement a reversal close module into my new advisor.

This is a multipair advisor and all the algorithm is working into this loop, where the value for _Symbol is 'SName':

The code is working fine on backtest, there's a buy and a sell signal when the condition is met, so I wrote a few lines to close the first order when there are more than one deal from the same symbol (SName') , cause they would be opposite:

The matter what's happening on my demo account is when there is a new deal, the first one is closed no matter the symbol and don't actually know why. Can anybody check this lines for if there is any mistake?

You are bypassing the whole cycle of POSITIONS wrong - you need to go Towards zero:

for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions

You absolutely do not count the number of POSITIONS (namely POSITIONS, not orders). You are not searching for the "first" position (the search must be sorted by the time the position was opened).

I recommend doing these two steps in one function.

 

Example:

//+------------------------------------------------------------------+
//|                                                   CloseFirst.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
/*
   barabashkakvn Trading engine 3.136
*/
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
//--- input parameters
input int      Input1=9;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Close First                                                      |
//+------------------------------------------------------------------+
void CloseFirst(const string symbol_name)
  {
   int count=0;
   datetime time=TimeCurrent()+60*60*24;
   ulong ticket=0;
   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==symbol_name/* && m_position.Magic()==InpMagic*/)
           {
            count++;
            if(m_position.Time()<time)
              {
               time=m_position.Time();
               ticket=m_position.Ticket();
              }
           }
//---
   if(count>1)
      m_trade.PositionClose(ticket);
  }
//+------------------------------------------------------------------+
Files:
 
Vladimir Karputov:

Example:

Could it be done this way?

void CloseFirst(const string SName){
   int count=0;
   ulong ticket=0;
   for(int i=PositionsTotal()-1;i>=0;i--){ // returns the number of current positions
      if(PositionGetTicket(i)){ // selects the position by index for further access to its properties
         if(PositionGetString(POSITION_SYMBOL)()==SName){
            count++;
            }
         }
      }
   if(count>1)
      if(!trade.PositionClose(ticket,ULONG_MAX);
      }
   }
 
Vladimir Karputov:

Example:

You were right in the solution it's a backcounter loop, but I made it in a simpler way:

MQL4:

   int OrdersCount=0;
   double ClosePrice=0;
   int BuyOrders=0,SellOrders=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)&&
      OrderSymbol()==SName&&OrderMagicNumber()==MagicNumber){
         if(OrderType()==OP_BUY){BuyOrders++;ClosePrice=SBid;}
         if(OrderType()==OP_SELL){SellOrders++;ClosePrice=SAsk;}
         OrdersCount++;if(OrdersCount>1){
            if(!OrderClose(OrderTicket(),OrderLots(),ClosePrice,3,clrYellow)){
               Print("OrderClose error ",GetLastError());
               RefreshRates();
               return;
               }
            }
         }
      }

MQL5:

      int OrdersCount=0;
      int BuyOrders=0,SellOrders=0;
      for(int i=PositionsTotal()-1;i>=0;i--){
         ulong iTicket=PositionGetTicket(i);
         if(PositionSelectByTicket(iTicket)&&
         PositionGetString(POSITION_SYMBOL)==SName){
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY){BuyOrders++;}
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL){SellOrders++;}
            OrdersCount++;if(OrdersCount>1){
               if(!trade.PositionClose(iTicket,ULONG_MAX)){
                  Print("PositionClose error ",trade.ResultRetcode());
                  return;
                  }
               }
            }
         }
 

You do not need to select a position twice (you select a position first in PositionGetTicket and then again in PositionSelectByTicket). You need to select a position once - in PositionGetTicket.

reference

PositionGetTicket

The function returns the ticket of a position with the specified index in the list of open positions and automatically selects the position to work with using functions PositionGetDouble, PositionGetInteger, PositionGetString.


PositionSelectByTicket

Selects an open position to work with based on the ticket number specified in the position
Documentation on MQL5: Trade Functions / PositionGetTicket
Documentation on MQL5: Trade Functions / PositionGetTicket
  • www.mql5.com
Trade Functions / PositionGetTicket - Reference on algorithmic/automated trading language for MetaTrader 5
Reason: