Dividing open positions into groups - page 3

 

Hooray, I think I've achieved an acceptable result.

The array fills with the required data as the positions are opened.

If I run the EA in the tester, I can see the first four entries in the comments, if the tester is at low speed, and a pause is used - everything is clear.

I attach the file with the code.

Now I try to fool around with the first condition and assign N_Caste = 1 to positions that meet this condition;

The critics are welcome.

Thanks to all not indifferent.

Files:
Sower_1_3.mq5  21 kb
 
Nikolay Kositsin:

... Such things are either self-written or commissioned from freelancing.

Sorry, couldn't get past it. Aren't there things like that?

 

Goodnight.

As a follow-up to the messages above - taught the EA to create a two-dimensional array, enter into it the values of the ticket and rank for each position, as the positions open.

In the future, when signals or conditions come, ranks of corresponding positions will change. This is how I plan to manage positions.

There is a problem - I ask professionals to respond. Help me to deal with deleting elements from the array.

As positions are closed, elites accumulate in the array, which stores the ticket and the rank of a "dead" already closed position, how to remove I do not know.

The operation on pp. 172-173 does not work.

         if(dead_pos)ArrayRemove(Arr_Position,e,2);
         ArrayResize(Arr_Position,All_Position);

In OnTick() at each candlestick, positions are opened, their stops are modified, their ticks are entered into the array, and the original zero rank is assigned.

As the stops trigger, the array accumulates unnecessary elements. For clarity I've output the necessary comments and everything is visible online.

The code is small, so I will post it here and attach the file too.

Please help me organize the array cleaning.

//+------------------------------------------------------------------+
//|                                                        Sower_1_6 |
//|                                              Sergei Voicehovskii |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Sergei Voicehovskii"
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\TerminalInfo.mqh>
#include <Trade\Trade.mqh>
#include <Arrays\ArrayInt.mqh>
//---
CAccountInfo      m_account;
CDealInfo         m_deal;
CHistoryOrderInfo m_history;
COrderInfo        m_order;
CPositionInfo     m_position;
CSymbolInfo       m_symbol;
CTerminalInfo     m_terminal;
CTrade            m_trade;
CArrayInt         m_array;
//---
#define  observations 2
int  Arr_Position[][observations];
int  Array_Change[];
//--- input parameters
input int      SL                      = 50;
input int      TP                      = 50;
input double   Lot                     = 0.01;
input double   InpCloseProfit_money    = 5.0;   
input double   InpCloseProfit_points   = 50.0;   
input double   InpCloseProfit_percent  = 3.0;   
input ulong    InpDeviation            = 10;    
input bool     InpPrintLog             = true;
input bool     InpCommentLog           = true;
input ulong    Magic                  = 557755; 
//---
      int   stoploss    = SL;   
      int   takeprofit  = TP;
      ulong slippage    = InpDeviation;
      
      datetime Time_OpenPos;
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Обновляем данные
   Refresh_Rates();
//--- Устанавливаем символ
   m_symbol.Name(_Symbol);
//--- Устанавливаем Magic
   m_trade.SetExpertMagicNumber(Magic);
//--- Определяем режим расчета маржи    
   m_trade.SetMarginMode();
//--- Определяем режим исполнения ордеров    
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
//--- Устанавливаем максимальное отклонение от запрашиваемой цены   
   m_trade.SetDeviationInPoints(slippage);
//---
   ArrayFree(Arr_Position);  
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if(Checking_NewBar())
   {
//+---Открываем начальные позиции "свежего" бара       
      m_trade.Buy(0.01);
      m_trade.Sell(0.01);
//+---Выставляем стопы начальных позиций       
      ModifySLTP_1_range(stoploss,takeprofit,Magic);
//+---Заполняем массив c тикет/кастой позиций 
      int N = Array_Creating_Caste_Positions();
//+--- 
      int R = ArrayRange(Arr_Position,0)-1;
      if(R<30)R=0;else R=30;
      int tic = Arr_Position[R][0];
      if(m_position.SelectByTicket(tic))
      Time_OpenPos = m_position.Time();
      int P = PositionsTotal();
      
      if(InpCommentLog){
         Comment("Выводим данные \n"
         "ticket:                       ",tic,"\n"
         "Время открытия позиции:       ",Time_OpenPos,"\n"
         "Сколько элементов в массиве:  ",R+1,"\n"
         "Проверок тикета за проход:  ",N,"\n"
         "Ввсего открыто позиций:       ",P,"\n"
         //"Время жизни позиции (стр): ",structura_time.year," год. ",structura_time.mon," мес. ",structura_time.day," дн. ",structura_time.hour," час. ",structura_time.min," мин. ",structura_time.sec," сек. \n"
         );}
//---
      ArrayPrint(Arr_Position); 
//---
   }
//---
}
//+------------------------------------------------------------------+
int Array_Creating_Caste_Positions()
{
   int  n           = 0;
   long ticket      = 0;
   bool new_pos     = true;
//---Запись новых тикетов в массив позиций        
   int All_Position = PositionsTotal();
   int Array_Size   = ArrayRange(Arr_Position,0);
//---  
   for(int i = 0; i < All_Position; i++)
      {
      if(m_position.SelectByIndex(i))
         {
            ticket  = PositionGetInteger(POSITION_TICKET);
            new_pos = true;
         }
      for(int e = 0; e < Array_Size; e++)
         {
            if(Arr_Position[e][0]==ticket)
               {
                  new_pos = false;
                  n++;
                  break;
               }
         }
      if(new_pos){
      int New_Size = Array_Size+1;
      ArrayResize(Arr_Position,New_Size,0);
         Arr_Position[Array_Size][0] = (int)ticket;//Ticket
         Arr_Position[Array_Size][1] = 0;//Number_Caste (0 = начальные позиции)
         n++;}                       
      }
//---Удаление из массива мёртвых тикетов 
      Array_Size   = ArrayRange(Arr_Position,0);
      All_Position = PositionsTotal();
//---      
      for(int e = 0; e < Array_Size; e++)
      {
         int tickt = Arr_Position[e][0];
         bool dead_pos = true;
         
         for(int i = 0; i < All_Position; i++)
         {
            if(m_position.SelectByIndex(i))
               {
                  if(tickt == PositionGetInteger(POSITION_TICKET))
                     {
                        dead_pos = false;
                        n++;
                        break;
                     }   
               }
         }
         if(dead_pos)ArrayRemove(Arr_Position,e,2);
         ArrayResize(Arr_Position,All_Position);
      }
//---     
return(n);
}
//+------------------------------------------------------------------+
//Проверка на наличие нового бара
//+------------------------------------------------------------------+
bool Checking_NewBar()
{
//--- переменная для возврата функции
   bool new_bar_opened = false;
//--- статическая переменная для хранения времени открытия последнего бара 
   static datetime last_bar_time=0; 
//--- если статическая переменная еще неинициализирована 
   if(last_bar_time==0) 
     { 
      //--- это первый вызов, запишем время открытия и выйдем 
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE); 
      if(InpPrintLog)
      PrintFormat("Инициализировали переменную last_bar_time значением %s",TimeToString(last_bar_time)); 
     } 
//--- получим время открытия последнего бара по своему символу 
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); 
//--- если время открытия текущего бара не совпадает с тем, что хранится в last_bar_time то открылся новый бар
   if(curr_time!=last_bar_time) 
     { 
      new_bar_opened = true;
      //--- запомним время открытия нового бара в статической переменной 
      last_bar_time=curr_time; 
      //--- выведем сообщение об этом событии 
      if(InpPrintLog)
      PrintFormat("На символе %s открылся новый бар в %s",_Symbol,TimeToString(TimeCurrent())); 
     } 
return(new_bar_opened);   
} 
//+------------------------------------------------------------------+
//Обновление котировок
//+------------------------------------------------------------------+
bool Refresh_Rates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
     {
      if(InpPrintLog)
         Print(__FILE__," ",__FUNCTION__,", ERROR: ","RefreshRates error");
      return(false);
     }
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
     {
      if(InpPrintLog)
         Print(__FILE__," ",__FUNCTION__,", ERROR: ","Ask == 0.0 OR Bid == 0.0");
      return(false);
     }
//---
   return(true);
  }

//+------------------------------------------------------------------+
void ModifySLTP_1_range(int    stplss, 
                        int    tkprfit, 
                        ulong  mgc)
{
      double sl     = 0.0,
             tp     = 0.0;      
      double slbuy  = 0.0,
             slsell = 0.0,
             tpbuy  = 0.0,
             tpsell = 0.0;
             
      Refresh_Rates();
      
      if(stplss>0)
      {
       slbuy  = m_symbol.Bid() - stplss*m_symbol.Point();
       slsell = m_symbol.Ask() + stplss*m_symbol.Point();
      }
      if(tkprfit>0)
      { 
       tpbuy  = m_symbol.Bid() + tkprfit*m_symbol.Point();    
       tpsell = m_symbol.Ask() - tkprfit*m_symbol.Point();
      }

      for(int i=PositionsTotal()-1;i>=0;i--)
      {
         if(m_position.SelectByIndex(i))
         {
            if(m_position.Symbol()==Symbol())
            { 
                if(m_position.Magic() == mgc)
                {   
                     if(m_position.PositionType()==POSITION_TYPE_BUY)
                     {
                        sl = m_position.StopLoss()   > 0 ? m_position.StopLoss()   : slbuy;
                        tp = m_position.TakeProfit() > 0 ? m_position.TakeProfit() : tpbuy;
                              m_trade.PositionModify(m_position.Ticket(),NormalizeDouble(sl,Digits()),NormalizeDouble(tp,Digits()));
                     }
                     if(m_position.PositionType()==POSITION_TYPE_SELL)
                     {
                        sl = m_position.StopLoss()   > 0 ? m_position.StopLoss()   : slsell;
                        tp = m_position.TakeProfit() > 0 ? m_position.TakeProfit() : tpsell;
                              m_trade.PositionModify(m_position.Ticket(),NormalizeDouble(sl,Digits()),NormalizeDouble(tp,Digits()));
                     }
               }
            }
         }
      }
}  
//+------------------------------------------------------------------+
Files:
Sower_1_6.mq5  20 kb
 

For the clarity of the process it is better to put StLoss 0, TProf should leave 50, and the EA should be put on the hourly chart of any currency. This is in the tester.

On the onlan demo, of course minutes is better

 
Sergey Voytsekhovsky:

For the clarity of the process it is better to put StLoss 0, TProf should remain 50, and the EA should be placed on the hourly chart of any currency. This is in the tester.

On the onlan demo, of course minutes is better.

St.Loss † ©On your wall!

I fell off my chair)

St.Loss is inevitable.

Hmmm... we've got someone on the subject, well †, already on the forum... )

 
onedollarusd:

St.Loss † © On your wall!

I fell out of my chair)

Apparently St.Loss is inevitable.

Hmmm... someone we have on such a topic, well †, already on the forum... )

I agree, it sounds ridiculous. But it's just a model to work out part of the algorithm. Glad I could improve your mood.

If you don't mind throwing a link to ".... someone on this topic, well †, is already on the forum... " plz.

 
Sergey Voytsekhovsky:

If you don't mind throwing in a link to ".... someone on a topic like this, well †, already on the forum... " please.

And better yet, tell me if you know how to remove elements from a two-dimensional array, which are no longer needed?

Broke my head, the directory wiped to the holes. It's a shame I don't have the brains for it.

 
Sergey Voytsekhovsky:

how to remove elements from a two-dimensional array that are no longer needed ???

ArrayResize();

ArrayResize - Операции с массивами - Справочник MQL4
ArrayResize - Операции с массивами - Справочник MQL4
  • docs.mql4.com
При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры. Функция может быть применена только к динамическим массивам. При этом необходимо иметь ввиду, что нельзя изменять размер для динамических массивов, назначенных в...
 
Sergey Voytsekhovsky:

Better yet, if you know how to remove elements from a two-dimensional array that are no longer needed.

I've lost my head, I've wiped the reference book to the ground. It's a shame I don't have the brains for it.

Copying of the array "in itself", starting from the position next to the deleted and write starting from the deleted. And then resize as Grigori.S.B suggested

   int src_data[10];
   //--- Не важно как заполнен массив
   //--- Удалим индекс 4
   ArrayCopy(src_data, src_data, 4, 5);
   ArrayResize(src_data, ArraySize(src_data)-1);
For a 2-dimensional array, multiply the line number to delete by 2. For a 3-dimensional array multiply by 3...
 
Grigori.S.B:

ArrayResize();

Good morning, thanks for the reply.

I guess you haven't noticed, you can look above, all the questions were about MQL5.

I understand that the difference is not crucial sometimes, but nevertheless. The function you cited resizes the array, perhaps cutting off extra elements if the size is reduced.

This is not what is needed. You need to remove an element by finding it by value. I tried this function too, I wrote about it in #23. Thanks anyway.

Reason: