MQL4、MQL5に関する初心者からの質問、アルゴリズムやコードに関するヘルプ、ディスカッションなど。 - ページ 600

 
Vasiliy Sokolov:

これはテレパシークラブではありません。コードを添付していないので、どこにdeleteを配置するかはあなた次第です。

間違っている。

さて、これがそのコードですが、他に何が必要でしょうか?不正確な場合はどうするのですか?

ありがとうございます。

 
Artyom Trishkin:

ごっちゃになってますね。タスクのプランニングを誤ると、まさにこのような結果になるのです。

クラス内でオブジェクトを生成した場合は、終了時にデストラクタでオブジェクトを削除する必要があります。一方、他のクラスは、オブジェクトへのポインタを取得する前に、その有効性をチェックする必要があります。そして、原則的にそのような絡み合った関係はないはずです。ちょっと絡んでますね。複雑なのは品質ではありません。すべてが透明で、追跡可能であるべきです。まず第一に、あなたのために。

代わりにコードを表示してみましょう。

ここでは、プログラム起動時にファイルからデータを読み込んでいます。

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

つまり、反復処理でCCandleCondition *candle_condオブジェクトを作成し、それをcandles_one_rulesコレクションに追加しているのです。

以下は、CCandlesOneRulesクラスのAddConditionメソッドです。

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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は、条件のコンテナ・クラスに過ぎない。ルールに条件を付け、ルールをCCandlesOneRulesに、さらにCCandlesOneRulesに......といった具合です。

しかし、このwhileループは開始時に失敗し、メモリ不足のエラーでクラッシュします。しかも、この条件はあまり多くなく、停止前に読まれるのは7つだけです。読み込んだファイルのデータ数を減らせば、エラーや削除されていないオブジェクトなどもなく、動作します。

 
失礼します。CCandleConditionオブジェクト(CObjectを 継承した簡易クラス)の数 91831個。その後、メモリ外。
 
Juer:

では、コードをもっとよく見せてもらいましょう。

そろそろ我慢の限界です。

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

Addメソッドの定義はどこにあるのでしょうか?

コードから判断して、あなたは何をやっているのか完全に理解できていないようです。

 
Vasiliy Sokolov:

そろそろ我慢の限界です。

Addメソッドの定義はどこにあるのですか?

コードから判断すると、あなたは完全に誤解しています。

CCandleOneRules, CCandlesOneRules, CCandleRule はすべて CArrayObj から継承されたクラスです。

あなたの一般的な回答から判断すると、あなたは私の質問を理解していないだけです。CArrayObjを使った配列について、まだ正しい答えが得られていないようです。もう一度、その問題を繰り返してみます。クラスがあり、クラスメソッドでそのクラスのグローバルオブジェクトが 配列(CArrayObj型のオブジェクト)に追加され、このメソッドで宣言されています。このメソッドでは、この配列に対していくつかのアクションが実行されます。完了時には、配列オブジェクトは不要であり、配列メンバが必要となります。この配列オブジェクトを、配列のメンバを維持したまま正しく取り除くにはどうしたらよいでしょうか?取り除かないと、ログにundeleted objectsのようなメッセージが表示されます。私は解決策を提示しましたが、あなたは間違ったことを言いました。どのように正しいのか?この配列オブジェクトがクラスメソッド内でしか見えない場合、OnDeinit(またはOnDeinitから呼び出されるクラスのDeinitメソッド)で削除するにはどうすればよいですか?

また、OnDeinitだけでオブジェクトを削除してしまうと、プログラムの実行中やテスト中にメモリ不足になることも...。

 

こんにちは、同僚たち。

この質問についてご教授ください。ArraySetAsSeries()関数を使用して、インジケータバッファの要素番号の順序を指定するには、どこで使用すればよいですか?ターミナルにプリインストールされているインジケーターでは、OnCalculate()の中で使われていることが多いようです。しかし、インジケーターバッファはグローバルに宣言されています。この場合、OnInit()内でArraySetAsSeries() を1回呼び出すのが理にかなっているのでは?それとも、インジケータ・バッファに新しい要素が補充されるため、番号付けの順序が失われ、OnCalculate()内で毎回ArraySetAsSeries()を呼び出す必要があるのでしょうか?不要な時に不要な関数を呼び出すことなく、最適なコードを書きたい。よろしくお願いします。

 
Oleg Remizov:

こんにちは、同僚たち。

この質問についてご教授ください。ArraySetAsSeries()関数を使用して、インジケータバッファの要素番号の順序を指定するには、どこで使用すればよいですか?ターミナルにプリインストールされているインジケーターでは、OnCalculate()の中で使われていることが多いようです。しかし、インジケーターバッファはグローバルに宣言されています。この場合、OnInit()内でArraySetAsSeries() を1回呼び出すのが理にかなっているのでは?それとも、インジケータ・バッファに新しい要素が補充されるため、番号付けの順序が失われ、OnCalculate()内で毎回ArraySetAsSeries()を呼び出す必要があるのでしょうか?不要な時に不要な関数を呼び出すことなく、最適なコードを書きたい。よろしくお願いします。

IMHOでは、これらの関数を全く使わずにインジケータを書きます(もちろんゼロからなら)。バッファの場合は OnInit() で、タイムスケールの場合は OnCalculate() で使用します。

そして、最適なコードを語るには、この関数の実行時間を知る必要があります。ですから、プロファイラが先で、パフォーマンスの質問はその後にすべきなのです。

 
Alexey Kozitsyn:

IMHOでは、これらの機能を全く使わずにインジケータを書くことにしています(もちろん、ゼロからなら)。ただし、バッファの場合はOnInit()で、タイムスリリーの場合はOnCalculate()で行います。

そして、最適なコードを語るには、この関数の実行時間を知る必要があります。ですから、プロファイラが先で、パフォーマンスの質問はその後にすべきなのです。

そういう結論に傾いていたんです。ご指摘ありがとうございます。

 

こんにちは。質問ですが、MACDにボリンジャーバーを適用する際、ヒストグラムそのものではなく、シグナル ラインの値を取るのはなぜでしょうか?

 
Виктор:

こんにちは。質問なのですが、MACDにボリンジャーバーを適用する際、ヒストグラムそのものではなく、シグナル ラインの値を取るのはなぜでしょうか?

計算に使用するグラフィカルバッファを指定することはできますか?