Tutte le domande dei nuovi arrivati su MQL4 e MQL5, aiuto e discussione su algoritmi e codici - pagina 600

 
Vasiliy Sokolov:

Questo non è un club telepatico. Non hai allegato il tuo codice, quindi sta a te decidere dove mettere la cancellazione.

Sbagliato.

Bene, qui c'è il codice, di cos'altro avete bisogno? E se non è corretto?

Grazie.

 
Artyom Trishkin:

Hai confuso tutto. Una pianificazione errata del compito è esattamente ciò che porta a queste conseguenze.

Se vengono creati oggetti in una classe, essa deve cancellarli nel suo distruttore al termine. Le altre classi, invece, prima di ottenere un puntatore a un oggetto, dovrebbero controllarne la validità. E in linea di principio non dovrebbe esserci una relazione così intrecciata. È un po' un groviglio. Complicato non significa qualità. Tutto dovrebbe essere trasparente e tracciabile. Prima di tutto - per voi.

Mostriamo invece il codice.

Qui, sto leggendo alcuni dati da un file all'inizio del programma.

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

Cioè, creo un oggetto CCandleCondition *candle_cond all'iterazione e poi lo aggiungo alla collezione candles_one_rules.

Ecco il metodo AddCondition della classe 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 è solo una classe contenitore per le condizioni. Aggiungo condizioni alle regole e regole a CCandlesOneRules, che a sua volta a CCandlesOneRules....

Ma questo while loop fallisce all'avvio e si blocca con un errore di esaurimento della memoria. E non ci sono molte di queste condizioni, solo 7 vengono lette prima di fermarsi. Se riduciamo il numero di dati nel file letto, funziona, senza errori, oggetti non cancellati e così via.

 
Mi scusi. Numero di oggetti CCandleCondition (classe semplice ereditata da CObject) 91831. Dopo di che, fuori dalla memoria.
 
Juer:

Mostriamo meglio il codice.

Sto cominciando a perdere la pazienza.

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

Dov'è la definizione del metodo Add?

A giudicare dal codice avete una completa mancanza di comprensione di ciò che state facendo.

 
Vasiliy Sokolov:

Sto cominciando a perdere la pazienza.

Dov'è la definizione del metodo Add?

A giudicare dal codice avete un completo fraintendimento di ciò che state facendo.

CCandleOneRules, CCandlesOneRules, CCandleRule sono tutte classi ereditate da CArrayObj.

A giudicare dalle tue risposte generiche, semplicemente non capisci le mie domande. Sull'array con CArrayObj non hai ancora risposto nel modo giusto. Ancora una volta ripeterò questo problema. C'è una classe, nel metodo class gli oggetti globali della classe sono aggiunti all'array (oggetto di tipo CArrayObj), che è dichiarato in questo metodo. In questo metodo vengono eseguite alcune azioni in questo array. Al termine, l'oggetto array non è necessario, i membri dell'array sono necessari. Come sbarazzarsi correttamente di questo oggetto array, mantenendo i membri dell'array? Se non ve ne sbarazzate, otterrete un messaggio come oggetti non cancellati nel log. Ti ho dato la mia soluzione; l'hai detta in modo errato. Come è corretto? Come posso mettere la cancellazione in OnDeinit (o nel metodo Deinit della classe che sarà chiamato da OnDeinit), se questo oggetto array è visibile solo nel metodo della classe?

Inoltre, se gli oggetti vengono cancellati solo in OnDeinit, si può anche incorrere nell'esaurimento della memoria...

 

Salve colleghi.

Per favore, aiutatemi con questa domanda. Dove dovrei usare la funzione ArraySetAsSeries() per specificare l'ordine di numerazione degli elementi nel buffer dell'indicatore? Negli indicatori, che sono preinstallati nel terminale, ho osservato spesso che viene utilizzato all'interno di OnCalculate(). Ma il buffer dell'indicatore è dichiarato globalmente. Non è logico usare ArraySetAsSeries() dentro OnInit() per una singola chiamata in questo caso? O a causa del riempimento del buffer dell'indicatore con nuovi elementi l'ordine di numerazione può essere perso ed è necessario chiamare ArraySetAsSeries() ogni volta dentro OnCalculate()? Voglio scrivere un codice ottimale senza chiamate di funzioni inutili, quando non è necessario. Sarò grato per l'aiuto.

 
Oleg Remizov:

Salve colleghi.

Per favore, aiutatemi con questa domanda. Dove dovrei usare la funzione ArraySetAsSeries() per specificare l'ordine di numerazione degli elementi nel buffer dell'indicatore? Negli indicatori, che sono preinstallati nel terminale, ho osservato spesso che viene utilizzato all'interno di OnCalculate(). Ma il buffer dell'indicatore è dichiarato globalmente. Non è logico usare ArraySetAsSeries() dentro OnInit() per una singola chiamata in questo caso? O a causa del riempimento del buffer dell'indicatore con nuovi elementi l'ordine di numerazione può essere perso ed è necessario chiamare ArraySetAsSeries() ogni volta dentro OnCalculate()? Voglio scrivere un codice ottimale senza chiamate di funzioni inutili, quando non è necessario. Sarò grato per l'aiuto.

IMHO, scriverei indicatori senza queste funzioni (se da zero, ovviamente). Per i buffer - in OnInit(), per le serie temporali - in OnCalculate().

E, per parlare di codice ottimale, è necessario sapere quanto tempo impiega questa funzione ad essere eseguita. Quindi, il profilatore dovrebbe andare per primo, e solo dopo le domande sulle prestazioni.

 
Alexey Kozitsyn:

IMHO, scriverei indicatori senza queste funzioni (se da zero, ovviamente). Ma per i buffer - in OnInit(), per le serie temporali - in OnCalculate().

E, per parlare di codice ottimale, è necessario sapere quanto tempo impiega questa funzione ad essere eseguita. Quindi, il profilatore dovrebbe andare per primo, e solo dopo le domande sulle prestazioni.

Questa è la conclusione a cui tendevo. Grazie per il suggerimento.

 

Buon pomeriggio. Ho una domanda: perché, quando applico le barre di bolinger al MACD, prendo i valori della linea del segnale e non l'istogramma stesso?

 
Виктор:

Buon pomeriggio. Ho una domanda: perché quando applico le barre di bolinger al MACD, prendo i valori della linea del segnale e non l'istogramma stesso?

Avete la possibilità di specificare quale buffer grafico utilizzare per il calcolo?