Dividir las posiciones abiertas en grupos - página 3

 

Hurra, creo que he conseguido un resultado aceptable.

La matriz se llena con los datos necesarios a medida que se abren las posiciones.

Si ejecuto el EA en el probador, puedo ver las cuatro primeras entradas en los comentarios, si el probador está a baja velocidad, y se utiliza una pausa - todo es claro.

Adjunto el archivo con el código.

Ahora trato de jugar con la primera condición y asignar N_Caste = 1 a las posiciones que cumplen esta condición;

Las críticas son bienvenidas.

Gracias a todos los que no son indiferentes.

Archivos adjuntos:
Sower_1_3.mq5  21 kb
 
Nikolay Kositsin:

... Estas cosas se escriben por cuenta propia o se encargan a los autónomos.

Lo siento, no pude pasar de ahí. ¿No hay cosas así?

 

Buenas noches.

Como seguimiento a los mensajes anteriores - enseñó al EA a crear un array bidimensional, introducir en él los valores de la entrada y el rango para cada posición, a medida que las posiciones se abren.

En el futuro, cuando lleguen las señales o las condiciones, cambiarán los rangos de las posiciones correspondientes. Así es como pienso gestionar las posiciones.

Hay un problema: pido a los profesionales que respondan. Ayúdame a lidiar con la eliminación de elementos de la matriz.

A medida que se cierran posiciones, las élites se acumulan en el array, que almacena el billete y el rango de una posición"muerta" ya cerrada, cómo eliminarla no lo sé.

La operación de las páginas 172-173 no funciona.

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

En OnTick() en cada vela se abren posiciones, se modifican sus stops, se introducen sus ticks en un array y se asigna el rango cero original.

A medida que se disparan las paradas, la matriz acumula elementos innecesarios. Para mayor claridad, he emitido los comentarios necesarios y todo está visible en línea.

El código es pequeño, así que lo publicaré aquí y adjuntaré el archivo también.

Por favor, ayúdame a organizar la limpieza de la matriz.

//+------------------------------------------------------------------+
//|                                                        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()));
                     }
               }
            }
         }
      }
}  
//+------------------------------------------------------------------+
Archivos adjuntos:
Sower_1_6.mq5  20 kb
 

Para la claridad del proceso es mejor poner StLoss 0, TProf debe permanecer 50, y el EA debe ser colocado en el gráfico horario de cualquier moneda. Esto está en el probador.

En la demostración de onlan, por supuesto que los minutos son mejores

 
Sergey Voytsekhovsky:

Para la claridad del proceso es mejor poner StLoss 0, TProf debe dejar 50, y el EA debe ser puesto en el gráfico horario de cualquier moneda. Esto está en el probador.

En la demo de Onlan, por supuesto que los minutos son mejores.

St.Loss † ©¡En su pared!

Me caí de la silla)

La pérdida es inevitable.

Hmmm... tenemos a alguien sobre el tema, bueno †, ya en el foro.... )

 
onedollarusd:

St.Loss † © ¡En su pared!

Me caí de la silla)

Aparentemente la pérdida de San es inevitable.

Hmmm... alguien tenemos en tal tema, bueno †, ya en el foro... )

Estoy de acuerdo, suena ridículo. Pero es sólo un modelo para elaborar parte del algoritmo. Me alegro de haber podido mejorar tu estado de ánimo.

Si no te importa lanzar un enlace a ".... alguien sobre este tema, pues †, ya está en el foro... ", por favor.

 
Sergey Voytsekhovsky:

Si no te importa lanzar un enlace a ".... alguien en un tema como este, pues †, ya en el foro... " por favor.

Y mejor aún, dime si sabes cómo eliminar elementos de un array bidimensional, que ya no son necesarios.

Me rompí la cabeza, el directorio borrado hasta los agujeros. Es una pena que no tenga el cerebro para ello.

 
Sergey Voytsekhovsky:

¿cómo eliminar elementos de un array bidimensional que ya no son necesarios?

ArrayResize();

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

Mejor aún, si sabes cómo eliminar elementos de una matriz bidimensional que ya no son necesarios.

He perdido la cabeza, he borrado el libro de referencia del suelo. Es una pena que no tenga el cerebro para ello.

Copia del array "en sí mismo", comenzando por la posición próxima al borrado y escribiendo a partir del borrado. Y luego cambiar el tamaño como Grigori.S.B sugirió

   int src_data[10];
   //--- Не важно как заполнен массив
   //--- Удалим индекс 4
   ArrayCopy(src_data, src_data, 4, 5);
   ArrayResize(src_data, ArraySize(src_data)-1);
Para una matriz bidimensional, multiplique por 2 el número de línea a eliminar. Para una matriz tridimensional multiplica por 3...
 
Grigori.S.B:

ArrayResize();

Buenos días, gracias por la respuesta.

Supongo que no te has dado cuenta, puedes mirar arriba, todas las preguntas eran sobre MQL5.

Entiendo que la diferencia no es crucial a veces, pero sin embargo. La función que has citado redimensiona el array, tal vez cortando elementos extra si se reduce el tamaño.

Esto no es lo que se necesita. Para eliminar un elemento hay que buscarlo por su valor. Yo también probé esta función, escribí sobre ella en el #23. Gracias de todos modos.