MQL4 및 MQL5에 대한 초보자 질문, 알고리즘 및 코드에 대한 도움말 및 토론 - 페이지 600

 
Vasiliy Sokolov :

이것은 텔레파시 클럽이 아닙니다. 코드를 첨부하지 않았으므로 삭제할 위치를 생각하세요.

옳지 않다.

여기 코드가 있습니다. 더 필요한 것은 무엇입니까? 틀리면 옳은 것은?

고맙습니다.

 
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은 조건에 대한 컨테이너 클래스일 뿐입니다. 규칙에 조건을 추가하고 CCandleOneRules의 규칙을 차례로 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 유형의 개체)에 추가됩니다. 이 방법에서는 이 배열에서 일부 작업이 수행됩니다. 완료되면 배열 개체가 필요하지 않으며 배열 구성원이 필요합니다. 배열 구성원을 유지하면서 이 배열 객체를 제거하는 올바른 방법은 무엇입니까? 제거하지 않으면 로그에 삭제되지 않은 개체와 같은 메시지가 표시됩니다. 나는 내 솔루션을 주었다, 당신은 잘못 말했다. 어때요? 주어진 배열 객체가 클래스 메서드 내에서만 표시되는 경우 OnDeinit(또는 OnDeinit에서 호출될 Deinit 클래스 메서드)에 삭제를 배치하려면 어떻게 해야 합니까?

또한 OnDeinit에서만 개체를 삭제하면 프로그램 실행/테스트 중에 메모리 부족에 빠질 수도 있습니다...

 

안녕 동료들.

이 문제를 해결하도록 도와주세요. ArraySetAsSeries() 함수를 사용하여 표시기 버퍼 요소의 번호 지정 순서를 지정하는 것이 가장 합리적인 위치는 어디입니까? 터미널에 미리 설치된 표시기에서 OnCalculate() 내부에서 사용되는 것을 종종 보았습니다. 그러나 표시기 버퍼는 전역적으로 선언됩니다. 이 경우 단일 호출에 대해 OnInit() 함수 내에서 ArraySetAsSeries()를 한 번 사용하는 것이 논리적이지 않습니까? 또는 새 요소로 표시기 버퍼를 보충하기 때문에 번호 매기기 순서가 손실될 수 있으며 OnCalculate() 내부에서 매번 ArraySetAsSeries()를 호출해야 합니까? 필요하지 않을 때 추가 함수 호출이 없는 최적의 코드를 작성하고 싶습니다. 도움을 주시면 감사하겠습니다.

 
Oleg Remizov :

안녕 동료들.

이 문제를 해결하도록 도와주세요. ArraySetAsSeries() 함수를 사용하여 표시기 버퍼 요소의 번호 지정 순서를 지정하는 것이 가장 합리적인 위치는 어디입니까? 터미널에 미리 설치된 표시기에서 OnCalculate() 내부에서 사용되는 것을 종종 보았습니다. 그러나 표시기 버퍼는 전역적으로 선언됩니다. 이 경우 단일 호출에 대해 OnInit() 함수 내에서 ArraySetAsSeries()를 한 번 사용하는 것이 논리적이지 않습니까? 또는 새 요소로 표시기 버퍼를 보충하기 때문에 번호 매기기 순서가 손실될 수 있으며 OnCalculate() 내부에서 매번 ArraySetAsSeries()를 호출해야 합니까? 필요하지 않을 때 추가 함수 호출이 없는 최적의 코드를 작성하고 싶습니다. 도움을 주시면 감사하겠습니다.

IMHO, 나는 이러한 기능이 전혀 없는 표시기를 작성할 것입니다(물론 처음부터). 그리고 - 버퍼의 경우 - OnInit(), 시계열의 경우 - OnCalculate().

그리고 최적의 코드에 대해 이야기하려면 이 함수가 실행되는 데 걸리는 시간을 알아야 합니다. 따라서 프로파일러가 먼저 수행되어야 하고 그 다음에 성능 질문이 있어야 합니다.

 
Alexey Kozitsyn :

IMHO, 나는 이러한 기능이 전혀 없는 표시기를 작성할 것입니다(물론 처음부터). 그리고 - 버퍼의 경우 - OnInit(), 시계열의 경우 - OnCalculate().

그리고 최적의 코드에 대해 이야기하려면 이 함수가 실행되는 데 걸리는 시간을 알아야 합니다. 따라서 프로파일러가 먼저 수행되어야 하고 그 다음에 성능 질문이 있어야 합니다.

나는 그 결론을 향해 몸을 기울였다. 팁 고마워.

 

안녕하세요. 다음 질문이 생겼습니다. MACD에 볼린저 밴드를 적용할 때 히스토그램 자체가 아닌 신호선의 값을 취하는 이유는 무엇입니까?

 
Виктор :

안녕하세요. 다음 질문이 생겼습니다. MACD에 볼린저 밴드를 적용할 때 히스토그램 자체가 아닌 신호선의 값을 취하는 이유는 무엇입니까?

계산에 사용할 그래픽 버퍼를 지정할 수 있습니까?