Questions from Beginners MQL5 MT5 MetaTrader 5 - page 1207

 

mql5 (hedge)

How to implementan algorithm for closing positions under two conditions?

1 case. If there are 2 positions open, then close the one with more profit than... 2 case. If there are 2 or more open positions, then close by averaging over the value of...

Now I have two methods of closing these positions,

For 1 case compare positions by profit and close the one with more profit, for 2 case close all positions by Equity, by averaging.

These methods work well separately, but not together, because one of two events falls under the distribution of both methods.

I cannot manage to separate them. As a result both cases are closed mostly on Equity with closing of all positions. This leads to the fact that in the first case the desired position is deleted and reopened.

As a result. Double spread, double commission. It is frustrating)))

The scheme of setting orders and positions looks like this For SELL (and further only for SELL).

Limit order. SELL_LIMIT

position. SELL(always between orders)

Stop order.SELL_STOP

I am attaching the chart.

Closing of positions.

1. If a stop order is triggered, i.e. two or more positions appear at the same time, you should close one position which has a higher profit than... (20)

2. if a Limit order has triggered, i.e. two or more positions are opened simultaneously, their average (by Equity) value should be closed... (15)

Question. How to separate these two methods, so that they would handle only their own event?

Maybe there is some other method how to handle these two conditions?

Examples of methods I use.

//+---------------------------------------------------------------------+
//|  -- ЗАКРЫВАЕМ ОДНУ ИЗ ДВУХ ПОЗИЦИЙ С НИЗУ, ГДЕ ПРОФИТ БОЛЬШЕ ЧЕМ ---|
//+---------------------------------------------------------------------+ 
ulong ticket_n=ULONG_MAX;  double profit=DBL_MIN;

     if(invert_close == true) //Проверка на наличие 2х и более поз.
     {
     int positions=PositionsTotal();
     for(int i=PositionsTotal()-1; i>=0; i--)
     {
     ulong tmp_ticket=PositionGetTicket(i);
     if(ticket_n!=0)
     {
     double tmp_profit=PositionGetDouble(POSITION_PROFIT);
     if(tmp_profit>profit+Prof_eqw_niz)// допустим 20
     {
     ticket_n=tmp_ticket;
     profit=tmp_profit;
     }
     }
     }
//-----------
     if(ticket_n!=ULONG_MAX)
     m_trade.PositionClose(ticket_n);
     invert_close = false;
     Print("------  ЗАКРЫЛИ ТОЛСТУЮ ---------");
     }       

//+---------------------------------------------------------------------+
//|                     Э К В И Т И   ДЛЯ SELL_LIMIT                    |
//+---------------------------------------------------------------------+
   npos_ALL=0; NPos_ALL(npos_ALL);
   if (npos_ALL>=Metod_Eqw && m_account.Equity()>= m_account.Balance()+Prof_eqw)//Допустим 15
   {
   CloseAllPositions();
   Print("------  ЗАКРЫЛИ ВСЕ ---------");
   }
Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
 
Vladpedro:


Are positions opened by the symbol on which the EA works? Is Magic number used?
 
Vladimir Karputov:
Are positions opened by the symbol on which the EA works? Magic number is used

Yes, by the current symbol. Yes, magik is used.

 
Vladpedro:

Yes, by the current character. Yes magik is used.

Explain the second condition, what does it mean?(If 2 or more positions are open, then close by averaging over the value... )

 
Vladimir Karputov:

Explain the second condition, what does it mean?(If 2 or more positions are open, close by averaging over the value... )

It means: If two or more positions are open and the Equity is greater than the balance by any value (say 15), then all positions are closed.

For example, three positions are opened. The first has a current loss of -10, the second has a profit of -5, the third has a +30 profit and total +15, all positions can be closed.

If an average profit of +15 has not been reached, the positions will be closed by their own preset SL or TP. (This is sort of the third condition for closing positions, but there are no problems with it, so I have omitted it).

 
Vladpedro:

This means: If two or more positions are open and the Equity is greater than the balance by any value (say 15), then all positions will be closed.

For example, three positions are open. The first has a current loss of -10, the second has a profit of -5, the third has a +30+ total of +15, all positions can be closed.

If an average profit of +15 has not been reached, the positions will be closed by their own preset SL or TP. (this is kind of the third condition for closing positions, but there is no problem with it, that's why I omitted it).

Here is the full code for two conditions:

//+------------------------------------------------------------------+
//|                                       Closing Two conditions.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
#property version   "1.00"
/*
   barabashkakvn Trading engine 3.116
*/
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
CSymbolInfo    m_symbol;                     // object of CSymbolInfo class
//--- input parameters
input double   InpProfitTarget      = 15;       // Profit target, in deposit money (if Positions > 2)
input ulong    InpDeviation         = 10;       // Deviation, in points (1.00045-1.00055=10 points)
input ulong    InpMagic             = 200;      // Magic number
//---
bool     m_need_close_all           = false;    // close all positions
ulong    m_need_close_ticket        = ULONG_MAX;// close one position
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   if(!m_symbol.Name(Symbol())) // sets symbol name
     {
      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");
      return(INIT_FAILED);
     }
//---
   m_trade.SetExpertMagicNumber(InpMagic);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
   m_trade.SetDeviationInPoints(InpDeviation);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(m_need_close_all)
     {
      if(IsPositionExists())
        {
         CloseAllPositions();
         return;
        }
      else
         m_need_close_all=false;
     }
//---
   if(m_need_close_ticket!=ULONG_MAX)
     {
      //--- close one position
      if(m_position.SelectByTicket(m_need_close_ticket))
        {
         m_trade.PositionClose(m_need_close_ticket); // close a position
         return;
        }
      else
         m_need_close_ticket=ULONG_MAX;
     }
//--- calculate all positions
   int total=0;
   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()==m_symbol.Name() && m_position.Magic()==InpMagic)
            total++;

   if(total==2)
     {
      //--- conditon 1
      ulong tmp_ticket=ULONG_MAX;
      double tmp_profit=DBL_MIN;
      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()==m_symbol.Name() && m_position.Magic()==InpMagic)
              {
               double profit=m_position.Commission()+m_position.Swap()+m_position.Profit();
               if(profit>tmp_profit)
                 {
                  tmp_profit=profit;
                  tmp_ticket=m_position.Ticket();
                 }
              }
      //---
      if(tmp_ticket!=ULONG_MAX)
         m_need_close_ticket=tmp_ticket;
     }
   else
     {
      if(total>2)
        {
         //--- conditon 2
         double profit=0;
         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()==m_symbol.Name() && m_position.Magic()==InpMagic)
                  profit+=m_position.Commission()+m_position.Swap()+m_position.Profit();
         //---
         if(profit>=InpProfitTarget)
            m_need_close_all=true;
        }
     }
  }
//+------------------------------------------------------------------+
//| Is position exists                                               |
//+------------------------------------------------------------------+
bool IsPositionExists(void)
  {
   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()==m_symbol.Name() && m_position.Magic()==InpMagic)
            return(true);
//---
   return(false);
  }
//+------------------------------------------------------------------+
//| Close all positions                                              |
//+------------------------------------------------------------------+
void CloseAllPositions(void)
  {
   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()==m_symbol.Name() && m_position.Magic()==InpMagic)
            m_trade.PositionClose(m_position.Ticket()); // close a position by the specified m_symbol
  }
//+------------------------------------------------------------------+
 
Vladimir Karputov:

Here's the full code for the two conditions:

Thank you Vladimir. I will try to figure it out.

I tried to solve it in my own way, I understand how you can separate these two conditions.

For example.

Let's declare three logical variables.

Pos_1;

Pos_2_Clos_1;

Pos_2_Clos_All;

1. Check for the number of open positions.

If we have only 1 open position SELL is set to :

Pos_1=true ; Pos_2_Clos_1=false; Pos_2_Clos_All=false;

If there are 2 positions opened and the equity amount is positive (this may only occur when the SELL_STOP order triggers), assign a logical value to this event

Pos_1=false ; Pos_2_Clos_1=true; Pos_2_Clos_All=false;

If 2 positions are opened and equity amount is negative (this may only occur when an SELL_LIMIT order triggers), then

Pos_1=false ; Pos_2_Clos_1=false; Pos_2_Clos_All=true;

That seems to be all... You can check for logical variables and assign them to your closing method, but for some reason it didn't work for me...

I am a lousy programmer yet, maybe I made a mistake somewhere...

Thanks for the help)

Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
 

Vladimir Karputov:

Vladimir, I'm having trouble with this. When SELL_STOP orders trigger, everything is OK. Only one position with bigger profit is being closed,

But when SELL_LIMIT is triggered, everything is closed incorrectly, not by the sum of all open positions but it looks like the position with the higher profit is being closed.

I had similar error before, now I start to think, maybe it is my fault, maybe I do not calculate and open positions correctly.

Please review my ready for testing code and see if you have errors, but maybe there are some inconsistencies in your code too, or maybe I have not explained them correctly... What is the average profit for me?

I've started to analyze the algorithm now and realized that it is a bit more complicated in its consequences than I told you before.

The third condition when you close a position by its SL may cause errors in the algorithm of the first two conditions.

I will once again describe the complete algorithm of position closing only for the SELL_LIMIT case since the SEL_STOP case is executed properly. Let's leave it for now.

1. We initially have one open position SELL that has specified SL but it is higher than SELL_LIMIT, which means that SL is not going to be activated before SELL_LIMIT.

2. SELL_LIMIT has triggered and there is a second SELL position with its own SL, which will also not be able to close before the next SELL_LIMIT

If the SELL_LIMIT order has triggered, a new SELL_LIMIT order has been placed. (always)

4. The number of open SELL_LIMIT positions may be1-3 or more, it all depends on how far they are standing SL. Consider the case if there are a maximum of three. (I can limit this to SL)

Now the scenarios for closing positions.

If open positions. 2, only two scenarios are possible for closing one or all positions

1. By Equity, if it is more than balance by 15(all positions are closed), (m_account.Equity()>= m_account.Balance()+15) I meant to close several positions by averaging.

2. By own SL (one position is closed).

3. the remaining one position, now has to be cleared of closing conditions if they were set before, because we do not know what condition to apply to it.

It can repeat the SELL_LIMIT scenario, or it can come down to SEL_STOP and go to another close condition.

4. If there were three positions, we also close them(m_account.Equity()>= m_account.Balance()+15) or one of them will trigger SL and two positions remain.

Apply this rule until there is one position left, for which no closing conditions have been defined...

Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
 
Vladpedro:

Vladimir Karputov:

Vladimir, I'm having trouble with this. When my SELL_STOP order triggers, everything is OK. Only one position with bigger profit is being closed,

But when SELL_LIMIT is triggered, the order is closing incorrectly, not by the sum of all open positions but appears to be closing the position with the highest profit.

I had similar error before, now I start to think, maybe it is my fault, maybe I do not calculate and open positions correctly.

Please review my ready for testing code and see if you have errors, but maybe your code does not meet the conditions. Or maybe I have not explained them correctly... what is the average profit for me.

In general, it does not matter which pending order triggers - in fact, we end up with a position and then calculate the profit of the position.

 
Vladimir Karputov:

It does not make any difference which pending order triggered - after all, we get a position and then count the profit of the position

It does not make any difference. I have a suspicion that there is a difference because when setting orders and positions, I have assigned them "comments" of my own to positions and my own to orders. As a result, when an order moves to a position, it inherits the comment of the order.

Then when we were checking positions through comments, there was a mess... the comments were different. I fixed that.

I have not found in your code, or do not understand how the positions are closed for the condition SELL_LIMIT triggered by Equity.

if(total==2)
   {
//-------------------------------------------------------- conditon 1
      ulong tmp_ticket=ULONG_MAX;
      double tmp_profit=DBL_MIN;
      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()==m_symbol.Name() && m_position.Magic()==InpMagic)
      {
      double profit=m_position.Commission()+m_position.Swap()+m_position.Profit();
      if(profit>tmp_profit)
      {
      tmp_profit=profit;
      tmp_ticket=m_position.Ticket();
      }
      }
      //---
      if(tmp_ticket!=ULONG_MAX)
      m_need_close_ticket=tmp_ticket;
      }
      else
      {
      if(total==2)
        {
//--------------------------------------------------------- conditon 2
        double profit=0;
        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()==m_symbol.Name() && m_position.Magic()==InpMagic)
        profit+=m_position.Commission()+m_position.Swap()+m_position.Profit();
//--------
       if(profit>=InpProfitTarget)
        m_need_close_all=true;
        }
        }

It seems that we have checked if all positions can be closed, and the flag is set for it

but in theCloseAllPositions();

if(m_need_close_all)
   {
   if(IsPositionExists())
   {
   CloseAllPositions();
   return;
   }
   else
   m_need_close_all=false;
   }

there is something missing.

 if(m_account.Equity()>= m_account.Balance()+15)

There is no check for closing all positions for the case - SELL_LIMIT has triggered

Perhaps this samem_account.Equity()>= m_account.Balance()+15is implemented in some other way?

Or maybe it's because I've misinterpreted what I mean by "averaging".