How to save on commissions by using PositionCloseBy

 

Hi there due to my expert it's not getting profitable due to spend on commissions my question is the following: How to save on commissions by using PositionCloseBy?

Made a test by using this code but it's not working the same as the original version(less profit):

      int OrdersCount=0;
      int BuyOrders=0,SellOrders=0;
      for(int i=0;i<PositionsTotal();i++){
         ulong jTicket=PositionGetTicket(i);
         if(PositionSelectByTicket(jTicket)&&
         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.PositionCloseBy(jTicket,PositionGetTicket(0))){
                  Print("PositionClose error ",trade.ResultRetcode());
                  return;
                  }
               }
            }
         }

Hope someone can help on this topic, thank you in advance.

 

We have four positions:


Code:

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2018, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
/*
   barabashkakvn Trading engine 3.138
*/
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
#property version "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   ulong    old_ticket_buy    = 0;
   ulong    old_ticket_sell   = 0;
   ulong    young_ticket_buy  = 0;
   ulong    young_ticket_sell = 0;
   datetime old_time_buy      = D'3000.12.31 00:00';
   datetime old_time_sell     = D'3000.12.31 00:00';
   datetime young_time_buy    = D'1970.01.01 00:00';
   datetime young_time_sell   = D'1970.01.01 00:00';
//---
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==Symbol())
           {
            datetime pos_time=m_position.Time();
            if(m_position.PositionType()==POSITION_TYPE_BUY)
              {
               if(pos_time<old_time_buy)
                 {
                  old_time_buy=pos_time;
                  old_ticket_buy=m_position.Ticket();
                 }
               if(pos_time>young_time_buy)
                 {
                  young_time_buy=pos_time;
                  young_ticket_buy=m_position.Ticket();
                 }
               continue;
              }
            else
               if(m_position.PositionType()==POSITION_TYPE_SELL)
                 {
                  if(pos_time<old_time_sell)
                    {
                     old_time_sell=pos_time;
                     old_ticket_sell=m_position.Ticket();
                    }
                  if(pos_time>young_time_sell)
                    {
                     young_time_sell=pos_time;
                     young_ticket_sell=m_position.Ticket();
                    }
                 }
           }
//--- old_ticket_buy -> young_ticket_sell
   if(old_ticket_buy>0 && young_ticket_sell>0)
      m_trade.PositionCloseBy(old_ticket_buy,young_ticket_sell);
//--- old_ticket_sell -> young_ticket_buy
   if(old_ticket_sell>0 && young_ticket_buy>0)
      m_trade.PositionCloseBy(old_ticket_sell,young_ticket_buy);
  }
//+------------------------------------------------------------------+

Result:

2020.08.18 21:48:43.516 Scripts script 1 (GBPUSD,H1) loaded successfully
2020.08.18 21:48:43.528 Trades  '32113828': close position #686455741 buy 0.02 GBPUSD by position #686720600 sell 0.02 GBPUSD
2020.08.18 21:48:43.595 Trades  '32113828': accepted close position #686455741 buy 0.02 GBPUSD by position #686720600
2020.08.18 21:48:43.614 Trades  '32113828': deal #665327266 sell 0.02 GBPUSD at 1.32391 done (based on order #686721037)
2020.08.18 21:48:43.616 Trades  '32113828': close position #686455741 buy 0.02 GBPUSD by position #686720600 done in 88.341 ms
2020.08.18 21:48:43.616 Trades  '32113828': close position #686720589 sell 0.02 GBPUSD by position #686720571 buy 0.02 GBPUSD
2020.08.18 21:48:43.660 Trades  '32113828': accepted close position #686720589 sell 0.02 GBPUSD by position #686720571
2020.08.18 21:48:43.662 Trades  '32113828': deal #665327270 buy 0.02 GBPUSD at 1.32401 done (based on order #686721040)
2020.08.18 21:48:43.664 Trades  '32113828': close position #686720589 sell 0.02 GBPUSD by position #686720571 done in 48.044 ms
2020.08.18 21:48:43.664 Scripts script 1 (GBPUSD,H1) removed
Files:
1.mq5  6 kb
 

Finally used this code:

      ulong iTicket=0;
      int OrdersCount=0;
      int BuyOrders=0,SellOrders=0;
      for(int i=0;i<PositionsTotal();i++){
         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++;}
            }
         }
      //----------------------------------------- PositionCloseBy ---!
      for(int h=PositionsTotal()-1;h>=0;h--){
         ulong hTicket=PositionGetTicket(h);
         if(PositionSelectByTicket(hTicket)&&
         PositionGetString(POSITION_SYMBOL)==SName){
            OrdersCount++;if(OrdersCount>1){
               if(!trade.PositionCloseBy(hTicket,iTicket)){
                  Print("PositionCloseBy error ",trade.ResultRetcode());
                  return;
                  }
               }
            }
         }

Results comparison between Reversal Close&Open (1) and PositionCloseBy (2) before commissions:

The same curve with less profit, it seems to be some kind of problem with LotSizing.

 
David Diez:

Finally used this code:

Results comparison between Reversal Close&Open (1) and PositionCloseBy (2) before commissions:

The same curve with less profit, it seems to be some kind of problem with LotSizing.

To all, 

When using closeby, ticket order doesn't matter. What does matter is you use some kind of recursion to cleanup all your flattened positions and this is vitally important because if/when you use different position sizes in the closeby it will spawn new positions of smaller sizes. The key is to constantly widdle them down until there is none left. If you're not re-scanning the position pool after each call to closeby then you will have bugs and you will miss positions, I guarantee it. 

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool closeByAll(const string symbol)
  {
   CPositionInfo pos;
   for(int i=PositionsTotal()-1; i>=0; --i)
     {
      if(pos.SelectByIndex(i) && pos.Symbol() == symbol)
        {
         ENUM_POSITION_TYPE type1 = pos.PositionType();
         ulong ticket1 = pos.Ticket();
         for(int j=i-1; j>=0; --j)
           {
            if(pos.SelectByIndex(j) && pos.Symbol() == symbol && pos.PositionType() != type1)
              {
               CTrade trade;
               if(trade.PositionCloseBy(ticket1, pos.Ticket())
              {
               return closeByAll(symbol);
                 }
               return false;
              }
           }
        }
     }
   return true;
  }
 
nicholish en:

To all, 

When using closeby, order doesn't matter. What does matter is you use some kind of recursion to cleanup all your flattened positions and this is vitally important because if/when you use different position sizes in the closeby it will spawn new positions of smaller sizes. The key is to constantly widdle them down until there is none left. If you're not re-scanning the position pool after each call to closeby then you will have bugs and you will miss positions, I guarantee it. 

Thank you for your reply. So you're closing a ticket by the same one?

         ulong ticket1 = pos.Ticket();
         for (int j=i-1; j>=0; --j) {
            if (pos.SelectByIndex(j) && pos.Symbol() == symbol && pos.PositionType() != type1) {
               CTrade trade;
               if (trade.PositionCloseBy(ticket1, pos.Ticket())
 
David Diez:

Thank you for your reply. So you're closing a ticket by the same one?

No. See code. Not the same. 

 
nicholish en:

No. See code. Not the same. 

Oh, ok. Does this really save on commissions?
 
David Diez:
Oh, ok. Does this really save on commissions?

If you have opposing orders with a net flat position then of course, yes.

 
nicholish en:

If you have opposing orders with a net flat position then of course, yes.

I tried to make your method (one loop inside another) in my way of coding, but doesn't properly work. These are the lines:

      for(int i=0;i<PositionsTotal();i++){
         ulong iTicket=PositionGetTicket(i);
         if(PositionSelectByTicket(iTicket)&&
         PositionGetString(POSITION_SYMBOL)==SName){
            for(int j=PositionsTotal()-1;j>=0;j--){
               ulong jTicket=PositionGetTicket(j);
               if(PositionSelectByTicket(jTicket)&&
               PositionGetString(POSITION_SYMBOL)==SName){
                  OrdersCount++;if(OrdersCount>1){ // <-- If there are two positions they are opposite.
                     if(!trade.PositionCloseBy(jTicket,iTicket)){
                        Print("PositionCloseBy error ",trade.ResultRetcode());
                        return;
                        }
                     }
                  }
               }
            }
         }

Return: PositionCloseBy error 0.

 
David Diez :

I tried to make your method ( one loop inside another ) in my way of coding, but doesn't properly work. These are the lines:

A nested loop is dangerous and wrong.

You need to do one cycle: during the cycle, find opposite positions and memorize their tickets. After the loop, just apply CloseBy.


I gave an example in a post  - this is a simple way. But you can make it even more complicated: search for positions by lot size, by opposite profit ...

How to save on commissions by using PositionCloseBy
How to save on commissions by using PositionCloseBy
  • 2020.08.18
  • www.mql5.com
Hi there due to my expert it's not getting profitable due to spend on commissions my question is the following: How to save on commissions by using...
 
You can create an interesting algorithm: allow many positions (BUY and SELL) open for the current symbol. And the task is to close all positions. In such a loop, a table of BUY and SELL tickets is compiled. After the loop, we process the table and execute CloseBy.