Any questions from newcomers on MQL4 and MQL5, help and discussion on algorithms and codes - page 600

 
Vasiliy Sokolov:

This is not a telepathic club. You haven't attached your code, so it's up to you to decide where to place delete.

Wrong.

Well, here is the code, what else do you need? What if it is incorrect?

Thank you.

 
Artyom Trishkin:

You've got it all mixed up. Incorrect planning of the task is exactly what leads to these consequences.

If objects are created in a class, it must delete them in its destructor upon completion. Other classes, on the other hand, before getting a pointer to an object, should check its validity. And in principle there shouldn't be such an intertwined relationship. It's a bit of a tangle. Complicated doesn't mean quality. Everything should be transparent and traceable. First and foremost - for you.

Let's show the code instead.

Here, I'm reading some data from a file at the program's start.

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));
           }           
        }
     ...
    } 

That is, I create a CCandleCondition *candle_cond object at iteration and then add it to the candles_one_rules collection.

Here is the AddCondition method of the CCandlesOneRules class:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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 is just a container class for conditions. I add conditions to rules and rules to CCandlesOneRules, which in turn to CCandlesOneRules....

But this while loop fails on start and crashes with out of memory error. And there aren't too many of these conditions, only 7 are read before stopping. If we reduce the number of data in the read file, it works, without any errors, undeleted objects and so on.

 
Excuse me. Number of CCandleCondition objects (simple class inherited from CObject) 91831. After that, out of memory.
 
Juer:

Let's have a better show of the code.

I'm starting to lose patience.

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

Where is the definition of Add method?

Judging by the code you have a complete lack of understanding of what you are doing.

 
Vasiliy Sokolov:

I'm starting to lose patience.

Where is the definition of the Add method?

Judging by the code you have a complete misunderstanding of what you are doing.

CCandleOneRules, CCandlesOneRules, CCandleRule are all classes inherited from CArrayObj.

Judging by your generic answers, you just don't understand my questions. On array with CArrayObj you still haven't answered the right way. Once again I will repeat that problem. There is a class, in the class method global objects of the class are added to the array (object of type CArrayObj), which is declared there in this method. In this method some actions are performed in this array. Upon completion, the array object is not needed, the array members are needed. How to get rid of this array object correctly, keeping the array members? If you don't get rid of it, you will get a message like undeleted objects in the log. I gave you my solution; you said it incorrectly. How is it correct? How can I place delete in OnDeinit (or in Deinit method of class which will be called from OnDeinit), if this array object is visible only within class method?

Moreover, if objects are deleted only in OnDeinit, you can also run into out of memory...

 

Hello colleagues.

Please help me with this question. Where should I use the ArraySetAsSeries() function to specify the order of elements numbering in the indicator buffer? In the indicators, which are preinstalled in the terminal, I have often noticed that it is used inside OnCalculate(). But the indicator buffer is declared globally. Isn't it logical to use ArraySetAsSeries() inside OnInit() for a single call in this case? Or because of replenishment of the indicator buffer with new elements the order of numeration can be lost and it is necessary to call ArraySetAsSeries() each time inside OnCalculate()? I want to write an optimal code without unnecessary function calls, when it is not necessary. I will be grateful for help.

 
Oleg Remizov:

Hello colleagues.

Please help me with this question. Where should I use the ArraySetAsSeries() function to specify the order of elements numbering in the indicator buffer? In the indicators, which are preinstalled in the terminal, I have often observed that it is used inside OnCalculate(). But the indicator buffer is declared globally. Isn't it logical to use ArraySetAsSeries() inside OnInit() for a single call in this case? Or because of replenishment of the indicator buffer with new elements the order of numeration can be lost and it is necessary to call ArraySetAsSeries() each time inside OnCalculate()? I want to write an optimal code without unnecessary function calls, when it is not necessary. I will be grateful for help.

IMHO, I would write indicators without these functions at all (if from zero, of course). For buffers - in OnInit(), for timeseries - in OnCalculate().

And to talk about optimal code, you need to know how long this function takes to execute. So, the profiler should go first, and only then performance questions.

 
Alexey Kozitsyn:

IMHO, I would write indicators without these functions at all (if from scratch, of course). But for buffers - in OnInit(), for timeseries - in OnCalculate().

And, in order to talk about optimal code, you need to know how long this function takes to execute. So, the profiler should go first, and only then the performance questions.

That's the conclusion I was leaning towards. Thanks for the tip.

 

Good afternoon. I have a question: why, when I apply the bolinger bars to the MACD, I take the values of the signal line and not the histogram itself?

 
Виктор:

Good afternoon. I have a question: why when I apply the bolinger bars to MACD, I take the values of the signal line and not the histogram itself?

Do you have the possibility to specify which graphical buffer to use for calculation?