Разделение открытых позиций на группы - страница 3

 

Ура, кажется добился приемлевого результата.

Массив заполняется нужными данными, по мере того как открываются позиции.

Если запустить советник в тестере, то в коментах видно первые четыре записи, если тестер на малой скорости, и используется пауза - все наглядно.

Файл с кодом прилагаю.

Пошел колдовать с первым условием и присвоением позициям, отвечающим этому условию  N_Caste = 1;

Критика приветствуется.

Спасибо всем неравнодушным.

Файлы:
Sower_1_3.mq5  21 kb
 
Nikolay Kositsin:

... Такие вещи или пишутся самостоятельно, или заказываются во фрилансе.  

Пардон, не смог пройти мимо. А есть вещи не такие? 

 

Доброй ночи.

В развитие сообщений выше - научил советник создавать двумерный массив, вносить в него значения тикета и ранга для каждой позиции, по мере открытия позиций.

В дальнейшем при поступлении сигналов или наступлении условий ранги соответствующих позиций будут меняться. Так я планирую управлять позициями.

Есть проблема - профессионалов прошу откликнуться. Помогите разобраться с удалением элиментов из массива.

По мере того как позиции закрываются, в массиве накапливаются элименты, которые хранят тикет и ранг "мертвой" уже закрытой позиции, как удалить не знаю.

Операция на стр. 172-173 не работает

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

В OnTick() на каждой свече открываются позиции, модифицируются их стопы, их тикеты заносятся в массив, присваивается исходный нулевой ранг. 

По мере срабатывания стопов в массиве накапливаются лишние элименты. Для наглядности вывел нужные коменты и все видно в онлайне.

Код пока маленький, потому выложу сдесь и файл прикреплю тоже.

Помогите плиз организовать чистку массива.

//+------------------------------------------------------------------+
//|                                                        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()));
                     }
               }
            }
         }
      }
}  
//+------------------------------------------------------------------+
Файлы:
Sower_1_6.mq5  20 kb
 

Для наглядности процесса СтЛосс лучше поставить 0, ТПроф оставить 50, советник накинуть на часовой график любой валюты. Это в тэстере.

На демо в онлане конечно лучше минутки

 
Sergey Voytsekhovsky:

Для наглядности процесса СтЛосс лучше поставить 0, ТПроф оставить 50, советник накинуть на часовой график любой валюты. Это в тэстере.

На демо в онлане конечно лучше минутки

St.Loss † © На стену себе!

Я упал с кресла)

Видно St.Loss неизбежен.

Хм.. кто-то у нас по такой теме, ну †, уже на форуме есть.. )

 
onedollarusd:

St.Loss † © На стену себе!

Я упал с кресла)

Видно St.Loss неизбежен.

Хм.. кто-то у нас по такой теме, ну †, уже на форуме есть.. )

Согласен, звучит смешно. Но ведь это просто моделька, что-бы отработать часть алгоритма. Рад что смог улучшить Ваше настроение.

Если не затруднит подкиньте ссылку на "....кто-то у нас по такой теме, ну †, уже на форуме есть.. " плиз.

 
Sergey Voytsekhovsky:

Если не затруднит подкиньте ссылку на "....кто-то у нас по такой теме, ну †, уже на форуме есть.. " плиз.

А еще лучше подскажите, если знаете, как удалить из двухмерного массива элементы, которые уже не нужны ???

Голову сломал, справочник затер до дыр. Обидно что мозгов не хватает.

 
Sergey Voytsekhovsky:

 как удалить из двухмерного массива элименты, которые уже не нужны ???

ArrayResize();

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

А еще лучше подскажите, если знаете, как удалить из двухмерного массива элементы, которые уже не нужны ???

Голову сломал, справочник затер до дыр. Обидно что мозгов не хватает.

Копирование массива "сам в себя", начиная с позиции следующей за удаляемой и писать начиная с удаляемой. А затем изменить размер как подсказал Grigori.S.B

   int src_data[10];
   //--- Не важно как заполнен массив
   //--- Удалим индекс 4
   ArrayCopy(src_data, src_data, 4, 5);
   ArrayResize(src_data, ArraySize(src_data)-1);
Для двухмерного массива надо номер строки для удаления умножить на 2. Для 3х мерного на 3...
 
Grigori.S.B:

ArrayResize();

Доброе утро, спасибо за ответ.

Вы видимо не обратили внимание, выше можно посмотреть, все вопросы касались MQL5.

Понимаю что разница не принципиальна иногда, но тем не менее. Приведенная Вами функция изменяет размер массива, возможно отрезает лишние элименты, если размер уменьшается.

Это не то что нужно. Нужно удалить элимент, найдя его по значению. Да и пробовал я воспользоваться и этой функцией, в #23 писал про это. В любом случае - спасибо.

Причина обращения: