Keep getting requoted when using PositionClose() and PositionClosePartial()

 

I'm writing a hedging EA, and in a section I try to close multiple open positions once I've hit a specific profit target. The logic loops through all positions, checks if it is the correct ENUM_POSITION_TYPE, and executes the PositionClose() function with the matching position's ticket number. For the positions that don't match that position type, it will reduce the position partially by a percentage of the current volume.

The problem is when I backtest the EA, each one gets requoted. I looked at the parameters for this function and the last one is a deviation that defaults to ULONG_MAX. So I would think that any requoted price should be acceptable for the order to be successful.


// Find position type to close based on current price
ENUM_POSITION_TYPE positionDirection;
positionDirection = (ea_symbol.Bid() >= g_recoveryZoneLong) ? POSITION_TYPE_SELL : POSITION_TYPE_BUY;
Print("======== Closing all positions that are type ", EnumToString(positionDirection));

// Close negative positions and reduce positive positions volume
for (int i = 0; i < PositionsTotal(); i++) {
        ea_position.SelectByIndex(i);
        if (ea_position.Magic() == inp_magicNumber && ea_position.Symbol() == ea_symbol.Name()) {
                // Close all negative positions
                if (ea_position.PositionType() == positionDirection) {
                        Print("*****CLOSING POSITION #", ea_position.Ticket(),"*****");
                        ea_trade.PositionClose(ea_position.Ticket());
                        continue;
                }
               
                // Reduce size of all positive positions
                Print("*****REDUCING POSITION #", ea_position.Ticket(), " BY ",NormalizeDouble((ea_position.Volume() * inp_reducePositionPercent), 2),
                      " LOTS*****");
                ea_trade.PositionClosePartial(ea_position.Ticket(), NormalizeDouble((ea_position.Volume() * inp_reducePositionPercent), 2));
         }
}

Here is the output of the journal from the backtest:


2021.09.01 22:24:01.094 2021.08.27 17:00:58   ======== Closing all positions that are type POSITION_TYPE_BUY

2021.09.01 22:24:01.094 2021.08.27 17:00:58   *****CLOSING POSITION #2*****

2021.09.01 22:24:01.094 2021.08.27 17:00:58   requote 1.17781 / 1.17788 (instant sell 0.01 EURUSD at 1.17772)

2021.09.01 22:24:01.094 2021.08.27 17:00:58   requote 1.17781 / 1.17788 (instant sell 0.01 EURUSD at 1.17772, close #2 buy 0.01 EURUSD 1.17608)

2021.09.01 22:24:01.094 2021.08.27 17:00:58   CTrade::OrderSend: instant sell 0.01 position #2 EURUSD at 1.17772 [requote (1.17781/1.17788)]

2021.09.01 22:24:01.096 2021.08.27 17:00:58   *****REDUCING POSITION #4 BY 0.02 LOTS*****

2021.09.01 22:24:01.096 2021.08.27 17:00:58   requote 1.17758 / 1.17765 (instant buy 0.02 EURUSD at 1.17788)

2021.09.01 22:24:01.096 2021.08.27 17:00:58   requote 1.17758 / 1.17765 (instant buy 0.02 EURUSD at 1.17788, close #4 sell 0.02 EURUSD 1.17490)

2021.09.01 22:24:01.096 2021.08.27 17:00:58   CTrade::OrderSend: instant buy 0.02 position #4 EURUSD at 1.17788 [requote (1.17758/1.17765)]

2021.09.01 22:24:01.098 2021.08.27 17:00:58   *****CLOSING POSITION #5*****

2021.09.01 22:24:01.098 2021.08.27 17:00:58   requote 1.17767 / 1.17774 (instant sell 0.03 EURUSD at 1.17758)

2021.09.01 22:24:01.098 2021.08.27 17:00:58   requote 1.17767 / 1.17774 (instant sell 0.03 EURUSD at 1.17758, close #5 buy 0.03 EURUSD 1.17555)

2021.09.01 22:24:01.098 2021.08.27 17:00:58   CTrade::OrderSend: instant sell 0.03 position #5 EURUSD at 1.17758 [requote (1.17767/1.17774)]

What am I missing?

Thanks for your time and consideration.

 

You need to count down when looping your positions.

deviation=ULONG_MAX means the default deviation will be used, which is 10 points unless you set it to an other value.

 

Thanks Alain I'll try to correct this and see if that's what it is, probably is. I'm looking at the source for the trade class and you're right it does default to the set deviation. So theoretically I just need to set the deviation for the trade object or specify in the call on that line.

I've noticed other EAs count down when looping and wasn't sure why. Is this a best practice of some kind?  Does it have something to do with the potential to run into an "Out of bounds array" error?

 
Jon McMillan #:

Thanks Alain I'll try to correct this and see if that's what it is, probably is. I'm looking at the source for the trade class and you're right it does default to the set deviation. So theoretically I just need to set the deviation for the trade object or specify in the call on that line.

I've noticed other EAs count down when looping and wasn't sure why. Is this a best practice of some kind?  Does it have something to do with the potential to run into an "Out of bounds array" error?

It's not a best practice, it's mandatory if you don't want bugs. If you close position at index 0, the position which was at index 1 will become index 0, but on the next iteration you i variable will be 1, and you will miss the "new" index 0 position.

 

Okay I reversed the order of the loop so it's counting down. Even when putting the deviation at 20 within the function call I am still getting requoted. Another point is this is while backtesting in the Strategy Tester. I printed out the request details within the code and am getting the following, it seems the deviation being set to 20 is true within the request. Something is still wrong.



2021.09.02 16:29:52.001 2021.08.27 17:00:58   ======== Closing all positions that are type POSITION_TYPE_SELL
2021.09.02 16:29:52.001 2021.08.27 17:00:58   *****REDUCING POSITION #9 BY 0.14 LOTS*****
2021.09.02 16:29:52.005 2021.08.27 17:00:58   requote 1.17781 / 1.17788 (instant sell 0.14 EURUSD at 1.17772)
2021.09.02 16:29:52.005 2021.08.27 17:00:58   requote 1.17781 / 1.17788 (instant sell 0.14 EURUSD at 1.17772, close #9 buy 0.18 EURUSD 1.17557)
2021.09.02 16:29:52.005 2021.08.27 17:00:58   CTrade::OrderSend: instant sell 0.14 position #9 EURUSD at 1.17772 [requote (1.17781/1.17788)]
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestAction: TRADE_ACTION_DEAL
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestOrder: 0
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestPrice: 1.17772
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestVolume: 0.14
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestDeviation: 20
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestType: ORDER_TYPE_SELL
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestTypeFilling: ORDER_FILLING_FOK
2021.09.02 16:29:52.005 2021.08.27 17:00:58   ResultReturnCode: 10004

2021.09.02 16:29:52.005 2021.08.27 17:00:58   ResultReturnCodeDescription: requote (1.17781/1.17788)


That was an example with using PositionClosePartial(), below is PositionClose().

2021.09.02 16:29:52.006 2021.08.27 17:00:58   *****CLOSING POSITION #8*****
2021.09.02 16:29:52.006 2021.08.27 17:00:58   requote 1.17758 / 1.17765 (instant buy 0.12 EURUSD at 1.17788)
2021.09.02 16:29:52.006 2021.08.27 17:00:58   requote 1.17758 / 1.17765 (instant buy 0.12 EURUSD at 1.17788, close #8 sell 0.12 EURUSD 1.17488)
2021.09.02 16:29:52.006 2021.08.27 17:00:58   CTrade::OrderSend: instant buy 0.12 position #8 EURUSD at 1.17788 [requote (1.17758/1.17765)]
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestAction: TRADE_ACTION_DEAL
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestOrder: 0
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestPrice: 1.17788
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestVolume: 0.12
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestDeviation: 20
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestType: ORDER_TYPE_BUY
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestTypeFilling: ORDER_FILLING_FOK
2021.09.02 16:29:52.006 2021.08.27 17:00:58   ResultReturnCode: 10004
2021.09.02 16:29:52.006 2021.08.27 17:00:58   ResultReturnCodeDescription: requote (1.17758/1.17765)


I do get some orders that go through without issue, like this one below.

2021.09.02 16:29:52.008 2021.08.27 17:00:59   *****CLOSING POSITION #4*****
2021.09.02 16:29:52.008 2021.08.27 17:00:59   instant buy 0.02 EURUSD at 1.17783, close #4 (1.17776 / 1.17783)
2021.09.02 16:29:52.008 2021.08.27 17:00:59   deal #9 buy 0.02 EURUSD at 1.17783 done (based on order #11)
2021.09.02 16:29:52.008 2021.08.27 17:00:59   deal performed [#9 buy 0.02 EURUSD at 1.17783]
2021.09.02 16:29:52.008 2021.08.27 17:00:59   order performed buy 0.02 at 1.17783 [#11 buy 0.02 EURUSD at 1.17783]
2021.09.02 16:29:52.010 2021.08.27 17:00:59   CTrade::OrderSend: instant buy 0.02 position #4 EURUSD at 1.17783 [done at 1.17783]
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestAction: TRADE_ACTION_DEAL
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestOrder: 0
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestPrice: 1.17783
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestVolume: 0.02
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestDeviation: 20
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestType: ORDER_TYPE_BUY
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestTypeFilling: ORDER_FILLING_FOK
2021.09.02 16:29:52.010 2021.08.27 17:00:59   ResultReturnCode: 10009
2021.09.02 16:29:52.010 2021.08.27 17:00:59   ResultReturnCodeDescription: done at 1.17783



 
Alain Verleyen #:

It's not a best practice, it's mandatory if you don't want bugs. If you close position at index 0, the position which was at index 1 will become index 0, but on the next iteration you i variable will be 1, and you will miss the "new" index 0 position.

Ah yes, logic error on my part for sure. Thank you for explaining that, it didn't even occur to me. Unfortunately still getting requotes, so still trying to figure that out.
 
Jon McMillan #:

Okay I reversed the order of the loop so it's counting down. Even when putting the deviation at 20 within the function call I am still getting requoted. Another point is this is while backtesting in the Strategy Tester. I printed out the request details within the code and am getting the following, it seems the deviation being set to 20 is true within the request. Something is still wrong.



2021.09.02 16:29:52.001 2021.08.27 17:00:58   ======== Closing all positions that are type POSITION_TYPE_SELL
2021.09.02 16:29:52.001 2021.08.27 17:00:58   *****REDUCING POSITION #9 BY 0.14 LOTS*****
2021.09.02 16:29:52.005 2021.08.27 17:00:58   requote 1.17781 / 1.17788 (instant sell 0.14 EURUSD at 1.17772)
2021.09.02 16:29:52.005 2021.08.27 17:00:58   requote 1.17781 / 1.17788 (instant sell 0.14 EURUSD at 1.17772, close #9 buy 0.18 EURUSD 1.17557)
2021.09.02 16:29:52.005 2021.08.27 17:00:58   CTrade::OrderSend: instant sell 0.14 position #9 EURUSD at 1.17772 [requote (1.17781/1.17788)]
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestAction: TRADE_ACTION_DEAL
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestOrder: 0
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestPrice: 1.17772
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestVolume: 0.14
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestDeviation: 20
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestType: ORDER_TYPE_SELL
2021.09.02 16:29:52.005 2021.08.27 17:00:58   RequestTypeFilling: ORDER_FILLING_FOK
2021.09.02 16:29:52.005 2021.08.27 17:00:58   ResultReturnCode: 10004

2021.09.02 16:29:52.005 2021.08.27 17:00:58   ResultReturnCodeDescription: requote (1.17781/1.17788)


That was an example with using PositionClosePartial(), below is PositionClose().

2021.09.02 16:29:52.006 2021.08.27 17:00:58   *****CLOSING POSITION #8*****
2021.09.02 16:29:52.006 2021.08.27 17:00:58   requote 1.17758 / 1.17765 (instant buy 0.12 EURUSD at 1.17788)
2021.09.02 16:29:52.006 2021.08.27 17:00:58   requote 1.17758 / 1.17765 (instant buy 0.12 EURUSD at 1.17788, close #8 sell 0.12 EURUSD 1.17488)
2021.09.02 16:29:52.006 2021.08.27 17:00:58   CTrade::OrderSend: instant buy 0.12 position #8 EURUSD at 1.17788 [requote (1.17758/1.17765)]
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestAction: TRADE_ACTION_DEAL
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestOrder: 0
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestPrice: 1.17788
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestVolume: 0.12
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestDeviation: 20
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestType: ORDER_TYPE_BUY
2021.09.02 16:29:52.006 2021.08.27 17:00:58   RequestTypeFilling: ORDER_FILLING_FOK
2021.09.02 16:29:52.006 2021.08.27 17:00:58   ResultReturnCode: 10004
2021.09.02 16:29:52.006 2021.08.27 17:00:58   ResultReturnCodeDescription: requote (1.17758/1.17765)


I do get some orders that go through without issue, like this one below.

2021.09.02 16:29:52.008 2021.08.27 17:00:59   *****CLOSING POSITION #4*****
2021.09.02 16:29:52.008 2021.08.27 17:00:59   instant buy 0.02 EURUSD at 1.17783, close #4 (1.17776 / 1.17783)
2021.09.02 16:29:52.008 2021.08.27 17:00:59   deal #9 buy 0.02 EURUSD at 1.17783 done (based on order #11)
2021.09.02 16:29:52.008 2021.08.27 17:00:59   deal performed [#9 buy 0.02 EURUSD at 1.17783]
2021.09.02 16:29:52.008 2021.08.27 17:00:59   order performed buy 0.02 at 1.17783 [#11 buy 0.02 EURUSD at 1.17783]
2021.09.02 16:29:52.010 2021.08.27 17:00:59   CTrade::OrderSend: instant buy 0.02 position #4 EURUSD at 1.17783 [done at 1.17783]
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestAction: TRADE_ACTION_DEAL
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestOrder: 0
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestPrice: 1.17783
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestVolume: 0.02
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestDeviation: 20
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestType: ORDER_TYPE_BUY
2021.09.02 16:29:52.010 2021.08.27 17:00:59   RequestTypeFilling: ORDER_FILLING_FOK
2021.09.02 16:29:52.010 2021.08.27 17:00:59   ResultReturnCode: 10009
2021.09.02 16:29:52.010 2021.08.27 17:00:59   ResultReturnCodeDescription: done at 1.17783



What broker/server are you using ?

What strategy tester settings ?

 
Alain Verleyen #:

What broker/server are you using ?

What strategy tester settings ?

I'm running off of one of the MetaQuotes Demo servers. Below are my current Strategy Tester settings.

EURUSD - 5M from 2021/08/27 to 2021/08/31. Delay is set to current server ping (137ms). Everything is default/grayed out for the button to emulate slippage and requotes.

Modelling is "Every tick based on real ticks". Optimization is disabled and I use visual mode to see the trades happen. The tested symbol settings are all default.

 
Jon McMillan #:

I'm running off of one of the MetaQuotes Demo servers. Below are my current Strategy Tester settings.

EURUSD - 5M from 2021/08/27 to 2021/08/31. Delay is set to current server ping (137ms). Everything is default/grayed out for the button to emulate slippage and requotes.

Modelling is "Every tick based on real ticks". Optimization is disabled and I use visual mode to see the trades happen. The tested symbol settings are all default.

1. Metaquotes demo server is not a broker, you should not use it unless you have a good reason (being a beta tester for example).

2. Using a delay means you will have slippage and requotes. The "button" beside the delay has nothing to do with it (It's a poor design to place this button there).

3. There is a bug in MT5 Strategy Tester, using delays, which doesn't respect the deviation value.

MT5/mql5 reported and confirmed bugs.
MT5/mql5 reported and confirmed bugs.
  • 2021.05.11
  • www.mql5.com
I will use this topic to post reported bugs to Metaquotes in a centralized place. Please DON'T POST here without contacting me in private firstly...