Cualquier pregunta de los recién llegados sobre MQL4 y MQL5, ayuda y discusión sobre algoritmos y códigos - página 600

 
Vasiliy Sokolov:

Esto no es un club de telepatía. No has adjuntado tu código, por lo que debes decidir dónde colocar el borrado.

No es así.

Bueno, aquí está el código, ¿qué más necesitas? ¿Y si es incorrecto?

Gracias.

 
Artyom Trishkin:

Lo tienes todo mezclado. La planificación incorrecta de la tarea es exactamente lo que conduce a estas consecuencias.

Si se crean objetos en una clase, ésta debe eliminarlos en su destructor al finalizar. Otras clases, en cambio, antes de obtener un puntero a un objeto, deben comprobar su validez. Y en principio no debería haber una relación tan entrelazada. Es un poco de un enredo. Complicado no significa calidad. Todo debe ser transparente y rastreable. Lo primero y más importante: para usted.

En su lugar, mostremos el código.

Aquí, estoy leyendo algunos datos de un archivo al inicio del programa.

CCandlesOneRules candles_one_rules;

while(!FileIsEnding(file_handle))
     {
      CCandleCondition *candle_cond=new CCandleCondition();
      string_num++;      
      string str=FileReadString(file_handle);
      int len=StringLen(str);
      if(len<=0)
         continue;
      string cand_num_str="";
      string rule_str="";
      string rule_descr="";
      string shift_str="";
      string value_int_str="";
      string value_enum_str="";
      string status_str="";
      int start_ind=0;
      int status_ind=-1;
      //--- status
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         status_str+=CharToString((uchar)ch);
         status_ind=i;
        }      
      int status=(int)StringToInteger(status_str);
      if(!init_flag && status!=0)
         continue;
      //--- candle number
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         cand_num_str+=CharToString((uchar)ch);
        }      
      //--- rule    
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         rule_str+=CharToString((uchar)ch);
        }
      //--- shift
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         shift_str+=CharToString((uchar)ch);
        }
      //--- value
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         value_int_str+=CharToString((uchar)ch);
        }
      //--- rule description
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         rule_descr+=CharToString((uchar)ch);
        }
      //--- enum value 
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         value_enum_str+=CharToString((uchar)ch);
        }                  
      int candN=(int)StringToInteger(cand_num_str);
      int ruleN=(int)StringToInteger(rule_str);
      int shift=(int)StringToInteger(shift_str);
      candle_cond.Create(candN,ruleN,shift,value_int_str,rule_descr);
      if(CheckPointer(candle_cond))
        {
         if(candles_one_rules.AddCondition(GetPointer(candle_cond)))
           {
            if(StringToInteger(value_int_str)>0)
              {
               Print(__FUNCTION__+": candle one #: ",candle_cond.GetCandNumber(),", rule: ",candle_cond.GetRuleNumber(),", shift: ",candle_cond.GetShift(),", description: ",candle_cond.GetDescription(),", value: ",candle_cond.GetValueStr());
              }
            Print(__FUNCTION__+": size of condition: ",sizeof(candle_cond));
           }           
        }
     ...
    } 

Es decir, creo un objeto CCandleCondition *candle_cond en la iteración y luego lo añado a la colección candles_one_rules.

Aquí está el método AddCondition de la clase CCandlesOneRules:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CCandlesOneRules::AddCondition(CCandleCondition *cond)
  {
   for(int i=0;i<Total();i++)
     {
      CCandleOneRules *candle_one_r=At(i);
      if(!CheckPointer(candle_one_r))
         continue;
      if(cond.GetCandNumber()!=candle_one_r.GetCandOneNumber())
         continue;
//--- if candle one rules object with the same candle one number as the new condition is found         
      for(int j=0;j<candle_one_r.Total();j++)
        {
         CCandleRule *candle_rule=candle_one_r.At(j);
         if(!CheckPointer(candle_rule))
            continue;            
         if(candle_rule.GetRuleNumber()!=cond.GetRuleNumber())
            continue;
//--- if candle rule with the same rule number as the new condition is found            
         for(int k=0;k<candle_rule.Total();k++)         
           {
            CCandleCondition *rule_cond=candle_rule.At(k);
            if(!CheckPointer(rule_cond))
               continue;
            if(rule_cond.GetShift()!=cond.GetShift())
               continue;
//--- if rule condition with the same shift as the new condition is found
//--- update rule condition               
            return candle_rule.Update(k,GetPointer(cond));
           }
//--- if rule condition with the same shift as the new condition not found
//--- add the new condition
         return candle_rule.Add(GetPointer(cond));
        }
//--- if rule with the same rule number as the new condition not found        
//--- create new rule
      CCandleRule *new_rule=new CCandleRule(cond.GetCandNumber(),cond.GetRuleNumber());
      new_rule.Add(GetPointer(cond));
      return candle_one_r.Add(GetPointer(new_rule));
     }
//--- if candle one rules object with the same candle one number as the new condition not found
//--- create new candle one rule object
   if(cond.GetCandNumber()>m_candles_one_total)
      m_candles_one_total=cond.GetCandNumber();
   CCandleOneRules *new_cand_one_r=new CCandleOneRules(cond.GetCandNumber());
   CCandleRule *new_rule=new CCandleRule(cond.GetCandNumber(),cond.GetRuleNumber());
   new_rule.Add(GetPointer(cond));
   new_cand_one_r.Add(GetPointer(new_rule));
   return Add(GetPointer(new_cand_one_r));
//--- 
  }

CCandleRule es sólo una clase contenedora de condiciones. Agrego condiciones a las reglas y reglas a CCandlesOneRules, que a su vez a CCandlesOneRules....

Pero este bucle while falla en el inicio y se bloquea con un error de falta de memoria. Y no hay demasiadas de estas condiciones, sólo se leen 7 antes de parar. Si reducimos el número de datos en el archivo de lectura, funciona, sin errores, objetos no borrados, etc.

 
Discúlpeme. Número de objetos CCandleCondition (clase simple heredada de CObject) 91831. Después de eso, fuera de la memoria.
 
Juer:

Vamos a ver mejor el código.

Estoy empezando a perder la paciencia.

new_cand_one_r.Add(GetPointer(new_rule));
return Add(GetPointer(new_cand_one_r));

¿Dónde está la definición del método Add?

A juzgar por el código tienes una completa falta de comprensión de lo que estás haciendo.

 
Vasiliy Sokolov:

Estoy empezando a perder la paciencia.

¿Dónde está la definición del método Add?

A juzgar por el código tienes un completo malentendido de lo que estás haciendo.

CCandleOneRules, CCandlesOneRules, CCandleRule son todas clases heredadas de CArrayObj.

A juzgar por tus respuestas genéricas, no entiendes mis preguntas. Sobre el array con CArrayObj todavía no has contestado de la manera correcta. Una vez más voy a repetir ese problema. Hay una clase, en el método de la clase se añaden objetos globales de la clase al array (objeto de tipo CArrayObj), que se declara allí en este método. En este método se realizan algunas acciones en esta matriz. Al finalizar, el objeto del array no es necesario, se necesitan los miembros del array. ¿Cómo deshacerse de este objeto array correctamente, manteniendo los miembros del array? Si no te deshaces de él, recibirás un mensaje como objetos no eliminados en el registro. Te he dado mi solución; lo has dicho mal. ¿Cómo es correcto? ¿Cómo puedo colocar el borrado en OnDeinit (o en el método Deinit de la clase que será llamado desde OnDeinit), si este objeto array es visible sólo dentro del método de la clase?

Además, si los objetos se eliminan sólo en OnDeinit, también puede encontrarse con la falta de memoria...

 

Hola colegas.

Por favor, ayúdenme con esta pregunta. ¿Dónde debo utilizar la función ArraySetAsSeries() para especificar el orden de numeración de los elementos en el buffer del indicador? En los indicadores, que están preinstalados en el terminal, he observado a menudo que se utiliza dentro de OnCalculate(). Pero el búfer del indicador se declara globalmente. ¿No es lógico utilizar ArraySetAsSeries() dentro de OnInit() para una sola llamada en este caso? ¿O debido a la reposición del buffer del indicador con nuevos elementos se puede perder el orden de numeración y es necesario llamar a ArraySetAsSeries() cada vez dentro de OnCalculate()? Quiero escribir un código óptimo sin llamadas a funciones innecesarias, cuando no es necesario. Agradeceré la ayuda.

 
Oleg Remizov:

Hola colegas.

Por favor, ayúdenme con esta pregunta. ¿Dónde debo utilizar la función ArraySetAsSeries() para especificar el orden de numeración de los elementos en el buffer del indicador? En los indicadores, que están preinstalados en el terminal, he observado a menudo que se utiliza dentro de OnCalculate(). Pero el búfer del indicador se declara globalmente. ¿No es lógico utilizar ArraySetAsSeries() dentro de OnInit() para una sola llamada en este caso? ¿O debido a la reposición del buffer del indicador con nuevos elementos se puede perder el orden de numeración y es necesario llamar a ArraySetAsSeries() cada vez dentro de OnCalculate()? Quiero escribir un código óptimo sin llamadas a funciones innecesarias, cuando no es necesario. Agradeceré la ayuda.

En mi opinión, yo escribiría indicadores sin estas funciones en absoluto (si desde cero, por supuesto). Para los buffers - en OnInit(), para las series de tiempo - en OnCalculate().

Y, para poder hablar de código óptimo, es necesario saber cuánto tiempo tarda esta función en ejecutarse. Por lo tanto, el perfilador debe ir en primer lugar, y sólo entonces las cuestiones de rendimiento.

 
Alexey Kozitsyn:

En mi opinión, yo escribiría indicadores sin estas funciones en absoluto (si es desde cero, por supuesto). Pero para los buffers - en OnInit(), para las series de tiempo - en OnCalculate().

Y, para poder hablar de código óptimo, es necesario saber cuánto tiempo tarda esta función en ejecutarse. Por lo tanto, el perfilador debe ir primero, y sólo después las preguntas de rendimiento.

Esa es la conclusión por la que me inclinaba. Gracias por el consejo.

 

Buenas tardes. Tengo una pregunta: ¿por qué cuando aplico las barras de bolinger al MACD, tomo los valores de la línea de señal y no el propio histograma?

 
Виктор:

Buenas tardes. Tengo una pregunta: ¿por qué cuando aplico las barras de bolinger al MACD, tomo los valores de la línea de señal y no el propio histograma?

¿Existe la posibilidad de especificar el búfer gráfico que se utilizará para el cálculo?

Razón de la queja: