PosititionModify keeps trying to modify the same position over and over again

 

Looking at the journal, you can see it is trying to modify the same position with the same SL and TP every tick:


2024.05.23 13:15:36.661 2024.05.01 21:00:58   order performed buy 1 at 1.06904 [#6 buy 1 EURUSD at 1.06904]

2024.05.23 13:15:36.663 2024.05.01 21:00:58   CTrade::OrderSend: market buy 1.00 EURUSD sl: 1.06603 tp: 1.07153 [done at 1.06904]
2024.05.23 13:15:36.990 2024.05.01 21:02:41   position modified [#6 buy 1 EURUSD 1.06904 sl: 1.06874 tp: 1.07004]
2024.05.23 13:15:36.992 2024.05.01 21:02:41   CTrade::OrderSend: modify position #6 EURUSD (sl: 1.06874, tp: 1.07004) [done]
2024.05.23 13:15:36.993 2024.05.01 21:02:41   failed modify #6 buy 1 EURUSD sl: 1.06874, tp: 1.07004 -> sl: 1.06874, tp: 1.07004 [Invalid stops]
2024.05.23 13:15:36.993 2024.05.01 21:02:41   CTrade::OrderSend: modify position #6 EURUSD (sl: 1.06874, tp: 1.07004) [invalid stops]
2024.05.23 13:15:37.094 2024.05.01 21:03:16   failed modify #6 buy 1 EURUSD sl: 1.06874, tp: 1.07004 -> sl: 1.06874, tp: 1.07004 [Invalid stops]
2024.05.23 13:15:37.094 2024.05.01 21:03:16   CTrade::OrderSend: modify position #6 EURUSD (sl: 1.06874, tp: 1.07004) [invalid stops]



this is a shame, I have tried coding this numerous ways to stop this happening, but I haven't figured out how to stop PositionModify() from executing on every new tick, so I need advice for how to fix the problem

here is what I have in OnTick:

            double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);  
            double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);   
                   
            double offset_pts; 
             
            ArrayResize(modifiedSellMap, (int)posTicket+1);
            ArrayResize(modifiedBuyMap, (int)posTicket+1);
            
            modifiedSellMap[posTicket] = false;    
            modifiedBuyMap[posTicket] = false;  
            
            if(posTicket > 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
               

                offset_pts = 30*_Point;
                     
                 if(ask <= open_price - 50*_Point && !modifiedSellMap[posTicket]){
                    
                       open_price = PositionGetDouble(POSITION_PRICE_OPEN);
                    
                       trade.PositionModify(posTicket, open_price + offset_pts, open_price-100*_Point);
                       
                       modifiedSellMap[posTicket] = true;
                 }
               
            }  
                
            else if(posTicket > 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
                        
                offset_pts = 30*_Point;

                if(bid >= open_price + 50*_Point && !modifiedBuyMap[posTicket]){

                        open_price = PositionGetDouble(POSITION_PRICE_OPEN);

                        trade.PositionModify(posTicket, open_price - offset_pts, open_price+100*_Point);

                        modifiedBuyMap[posTicket] = true;                           
                }

             }  


         


 

I have a solution which seems to counteract the problem...I initialize the buymap/sellmap buffers to false in a different loop before entering the main loop where it scans active positions

static bool modifiedSellMap[];
static bool modifiedBuyMap[];

for (int i = 0; i < PositionsTotal(); i++){
        
    ulong posTicket = PositionGetTicket(i);

    ArrayResize(modifiedSellMap, (int)posTicket + 1);
    ArrayResize(modifiedBuyMap, (int)posTicket + 1);

    if (PositionSelectByTicket(posTicket)){
            
        long positionType = PositionGetInteger(POSITION_TYPE);

        if (positionType == POSITION_TYPE_SELL){
            modifiedSellMap[i] = false;
        } 
        else if (positionType == POSITION_TYPE_BUY){
            modifiedBuyMap[i] = false;
        }
    }
}

for (int i = PositionsTotal() - 1; i >= 0; i--){
        
    ulong posTicket = PositionGetTicket(i);
    pos_profit = PositionGetDouble(POSITION_PROFIT);
    pos_price = PositionGetDouble(POSITION_PRICE_CURRENT);
    open_price = PositionGetDouble(POSITION_PRICE_OPEN);

    if (breakeven_func) {
        double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
        double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

        double offset_pts;

        if (posTicket > 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
            offset_pts = 30 * _Point;

            if (ask <= open_price - 50 * _Point && !modifiedSellMap[posTicket]){
                open_price = PositionGetDouble(POSITION_PRICE_OPEN);

                trade.PositionModify(posTicket, open_price + offset_pts, open_price - 100 * _Point);

                modifiedSellMap[posTicket] = true;
            }
        } 
        else if (posTicket > 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
            offset_pts = 30 * _Point;

            if (bid >= open_price + 50 * _Point && !modifiedBuyMap[posTicket]) {
                open_price = PositionGetDouble(POSITION_PRICE_OPEN);

                trade.PositionModify(posTicket, open_price - offset_pts, open_price + 100 * _Point);

                modifiedBuyMap[posTicket] = true;
            }
        }
        
    } // end of breakeven func
} // end of loop
 

My solution is :

   if(MathAbs(prev_sl-new_sl)>2*_Point || MathAbs(prev_tp-new_tp)>2*_Point)
      //PositionModify
It looks a bit funny but considering the issues related to IEEE-754 it is the best I achieved so far.
 
Yashar Seyyedin #:

My solution is :

It looks a bit funny but considering the issues related to IEEE-754 it is the best I achieved so far.

interesting, if that works maybe this could also potentially work:

//happen only once
static double current_open_price;
static int firstModifiedPosition = 0;

if(posTicket > 0 && firstModifiedPosition!=1){
        
        current_open_price = PositionGetDouble(POSITION_PRICE_OPEN); 
        firstModifiedPosition = 1;
}
        


double prev_open_price = PositionGetDouble(POSITION_PRICE_OPEN);   

if(current_open_price != prev_open_price){
        
        current_open_price = prev_open_price;
        
        //modify positions
        
}
 
Conor Mcnamara #:
if(current_open_price != prev_open_price){
if(MathAbs(current_open_price - prev_open_price)>2*_Point){...}

Equality check is not reliable for double type.(You may check IEEE 754 standard)

 
Yashar Seyyedin #:
IEEE 754

Fair enough, there are problems that can arise when the numbers are unrounded. But in this case due to the fact that new positions will be executed on a much different price than previous positions, it should work (in theory) to only modify the position once if the price is forced to be rounded