도움이 필요한 배열이 범위를 벗어났습니다. - 페이지 8

 
Aleksei Stepanenko :

여기에 잠시 앉았다.

불필요한 순환을 피하기 위해 노력해야 합니다. 우리는 스트림에서 오는 인용문을 가지고 있으며 나중에 기록을 탐구하고 컴퓨터 리소스를 낭비하지 않도록 필요한 항목을 즉시 작성해야 합니다.

벌써 42세인데도 1등급이 된 기분이다.

 
Dark Kchlyzov :

벌써 42세인데도 1등급이 된 기분이다.

이것은 좋은 것입니다. 그래서 모든 것이 앞서 있습니다.

 
Алексей Тарабанов :

이것은 좋은 것입니다. 그래서 모든 것이 앞서 있습니다.

가장 중요한 결과!

 
Dark Kchlyzov :

3.47 나는 자러 간다.

내일 모두 해결해 드리겠습니다. 궁금한 점이 있으면 알려주세요!

모두 정말 감사합니다!!!

옴스크?

 
Aleksei Stepanenko :

여기에 잠시 앉았다.

불필요한 순환을 피하기 위해 노력해야 합니다. 우리는 스트림에서 오는 인용문을 가지고 있으며 나중에 기록을 탐구하고 컴퓨터 리소스를 낭비하지 않도록 필요한 항목을 즉시 작성해야 합니다.

코드를 실행했습니다.

여기에 약간 잘못된 것이 있습니까?

 #property version    "1.00"
#property strict

//символ и таймфрейм текущего графика
string symbol;
ENUM_TIMEFRAMES frame;
datetime time;
   

struct BarData
   {
   struct Elem
      {
       int       number;     //порядковый номер периода (дня, месяца или года)
       double    high;       //максимум периода
       double    low;         //минимум периода
       datetime time_high;   //время максимума
       datetime time_low;   //время минимума
      } Arr[];             //массив периода
   int index;               //текущий индекс массива
   double    max;           //последнее максимальное значение периода
   double    min;           //последнее минимальное значение периода
   datetime time_max;       //время максимума
   datetime time_min;       //время минимума

   //при создании структуры указываем, что массив пустой
   BarData(){index=- 1 ;}    
   
   //функция записывает текущие экстремумы
   void WriteBar( int eNumber, string eSymbol, ENUM_TIMEFRAMES eFrame, datetime eTime)
      {
       int eShift= iBarShift (eSymbol,eFrame,eTime);
       double eHigh= iHigh (eSymbol,eFrame,eShift);
       double eLow= iLow (eSymbol,eFrame,eShift);
       //если элементов ещё нет или период сменился
       if (index< 0 || eNumber!=Arr[index].number)
         {
         ArrayResize (Arr,++index+ 1 );
         Arr[index].number=eNumber;
         Arr[index].high=eHigh;
         Arr[index].low=eLow;
         Arr[index].time_high=eTime;
         Arr[index].time_low=eTime;
         }
       //если произошло обновление текущего максимума
       if (eHigh-Arr[index].high> 0 )
         {
         Arr[index].high=eHigh;
         Arr[index].time_high=eTime;
         }
       //если произошло обновление текущего минимума
       if (Arr[index].low-eLow> 0 )
         {
         Arr[index].low=eLow;
         Arr[index].time_low=eTime;
         }
       //если произошло обновление предыдущего максимума
       if (eHigh-max> 0 )
         {
         for ( int i=index+ 1 ; i>= 0 ; i--)
            {
             if (Arr[index].high-eHigh> 0 )
               {
               max=Arr[index].high;
               time_max=Arr[index].time_high;
               break ;
               }
            }
         }
       //если произошло обновление предыдущего минимума
       if (min-eLow> 0 )
         {
         for ( int i=index+ 1 ; i>= 0 ; i--)
            {
             if (eLow-Arr[index].low> 0 )
               {
               min=Arr[index].low;
               time_min=Arr[index].time_low;
               break ;
               }
            }
         }
      }
   } day, month, year;

int OnInit ()
   {
   symbol= Symbol ();
   frame=( ENUM_TIMEFRAMES ) Period ();
   return ( INIT_SUCCEEDED );
   }

void OnTick ()
   {
   //текущее время закрытого бара
   time= iTime (symbol,frame, 1 );
   
   MqlDateTime date; 
   TimeToStruct (time,date);
   
   //делаем записи каждого периода
   day.WriteBar(date.day,symbol,frame,time);
   month.WriteBar(date.mon,symbol,frame,time);
   year.WriteBar(date.year,symbol,frame,time);
   
   //теперь имеем значения   
   Comment ( TimeToString (day.time_max)+ " : " + DoubleToString (day.max)+ " : " + DoubleToString (day.Arr[day.index].high)+ "\n" + TimeToString (day.time_min)+ " : " + DoubleToString (day.Arr[day.index].low)+ " : " + DoubleToString (day.min));
   }


이와 같은 아이디어

1) 전일 Low_D1 레벨

2) Min_D 역사상 가장 가까운 일일 최저가



 //+------------------------------------------------------------------+
//|                                                   Test_Level.mq4 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link        "https://www.mql5.com"
#property version    "1.00"
#property strict
double    Bar_data_D1 [][ 6 ]; // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров D1
double    Low_D1_Level;       // Возвращает значение минимальной цены бара  D1
double    Min_D_Level ;       // ближайшей минимальный  D уровень
datetime   Time_Day;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit ()
  {
   Level();
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason)
  {

   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick ()
  {
  On_Timer();
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                        Функция Level 
//+------------------------------------------------------------------+
void Level()
{
 ArrayCopyRates(Bar_data_D1, _Symbol , PERIOD_D1 ); // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров

 Low_D1_Level   = iLow ( _Symbol , PERIOD_D1 , 1 );   // Возвращает значение минимальной цены бара  D1
    
//--- Min_D_Leve  
 //for(int i = 1; i<ArrayRange(Bar_data_D1,0) ;i++)
 for ( int i = 1 ; ;i++)
    {
     Print ( " i = " ,i, " Bar_data_D1 [i][2] = " ,Bar_data_D1 [i][ 2 ]);
     if (Bar_data_D1 [i][ 2 ]>= 0 )
       {
         if ( Bar_data_D1 [i][ 2 ] < Low_D1_Level)
          {
           Min_D_Level = Bar_data_D1 [i][ 2 ]; break ;
          }
       }   
    } 

 //+-------------------------Low_D1_Level----------------------------+ 
 if ( ObjectFind ( "Low_D1" )!=Low_D1_Level) 
   {
     ObjectDelete ( "Low_D1" );
     if ( ObjectFind ( "Low_D1" )!= 0 )
      {
       ObjectCreate ( "Low_D1" , OBJ_HLINE , 0 , Time[ 0 ],Low_D1_Level);
       ObjectSet( "Low_D1" , OBJPROP_COLOR , clrMaroon );
       ObjectSet( "Low_D1" , OBJPROP_WIDTH , 1 );
      }
   } 
   
 if ( ObjectFind ( "Low_D1_label" )!=Low_D1_Level)
   {
     ObjectDelete ( "Low_D1_label" ); 
     if ( ObjectFind ( "Low_D1_label" ) != 0 )
      {
       ObjectCreate ( "Low_D1_label" , OBJ_TEXT , 0 , Time[ 13 ], Low_D1_Level);
       ObjectSetText( "Low_D1_label" , "Low_D1: " + DoubleToStr(Low_D1_Level, _Digits ), 8 , "Verdana" , Brown);
      }
   } 
   
 //+-------------------------Min_D_Level----------------------------+ 
 if ( ObjectFind ( "Min_D" )!= Min_D_Level) 
   {
     ObjectDelete ( "Min_D" );
     if ( ObjectFind ( "Min_D" )!= 0 )
      {
       ObjectCreate ( "Min_D" , OBJ_HLINE , 0 , Time[ 0 ],Min_D_Level);
       ObjectSet( "Min_D" , OBJPROP_COLOR , clrMaroon );
       ObjectSet( "Min_D" , OBJPROP_WIDTH , 1 );
      }
   } 
   
 if ( ObjectFind ( "Min_D_label" )!=Min_D_Level)
   {
     ObjectDelete ( "Min_D_label" ); 
     if ( ObjectFind ( "Min_D_label" ) != 0 )
      {
       ObjectCreate ( "Min_D_label" , OBJ_TEXT , 0 , Time[ 30 ], Min_D_Level);
       ObjectSetText( "Min_D_label" , "Min_D: " + DoubleToStr(Min_D_Level, _Digits ), 8 , "Verdana" , Brown);
      }
   }  
 
}
//+------------------------------------------------------------------+
//|        функция удаление всех объектов созданных советником
//+------------------------------------------------------------------+
void DestroyObject()
{
 int tot= ObjectsTotal ();
 for ( int i=tot; i>= 0 ; i--)
    {
     
     if ( ObjectName (i)== "Low_MN1" ){ ObjectDelete ( 0 , "Low_MN1" ); Print ( "<< Объект Low_MN удалён >>" );}
     if ( ObjectName (i)== "Low_MN1_label" ){ ObjectDelete ( 0 , "Low_MN1_label" ); Print ( "<< Объект Low_MN1_label удалён >>" );}
     

     if ( ObjectName (i)== "Min_D" ){ ObjectDelete ( 0 , "Min_D" ); Print ( "<< Объект Min_D удалён >>" );}
     if ( ObjectName (i)== "Min_D_label" ){ ObjectDelete ( 0 , "Min_D_label" ); Print ( "<< Объект Min_D_label удалён >>" );}


   }
}
//+-------------------------------------------------------------------------+   
//                         функция Timer                    
//+-------------------------------------------------------------------------+
void On_Timer()
{

     
 if (Day()!= Time_Day)
   {
    Level();
    Time_Day = Day();
   }
}
 
Valeriy Yastremskiy :

옴스크?

 
Dark Kchlyzov :

+3에는 도시가 거의 없습니다)

알고리즘은 항상 의도한 대로가 아니라 작성된 대로 그려지고 계산됩니다. 의도한 대로 쓰기는 일반적으로 어렵습니다.

그림에서 당신은 저점을 정확히 보여주었고, 조건에서 당신은 일간 저가 바의 최저 가격 을 가지고 있습니다. 그리고 알고리즘은 추세 영역에서 그것을 찾았고 적어도 2개의 인접한 막대 사이에 있지 않습니다.

 
Dark Kchlyzov :

코드를 실행했습니다.

여기서 약간 잘못된?

첫 번째 뉘앙스는 알고리즘이 테스터 기록의 시작부터 계산되지 않고 시작된 순간부터 계산된다는 것입니다. 따라서 날짜 1970.01.01, 즉 0이 나타납니다.

히스토리의 시작 부분부터 계산하려면 OnTick에 주기를 삽입해야 합니다. 이와 같이:

 datetime time=0, current;


void OnTick ()
   {
   //текущее время закрытого бара
   current= iTime (symbol,frame, 1 );

   do
      {   
       MqlDateTime date; 
       TimeToStruct (time,date);
   
       //делаем записи каждого периода
      day.WriteBar(date.day,symbol,frame,time);
      month.WriteBar(date.mon,symbol,frame,time);
      year.WriteBar(date.year,symbol,frame,time);
   
       if (time<current) {time= iTime (symbol,frame,( iBarShift (symbol,frame,time)- 1 ));} else break ;
      }
   while (time<=current);

   //теперь имеем значения   
   Comment ( TimeToString (day.time_max)+ " : " + DoubleToString (day.max)+ " : " + DoubleToString (day.Arr[day.index].high)+ "\n" + TimeToString (day.time_min)+ " : " + DoubleToString (day.Arr[day.index].low)+ " : " + DoubleToString (day.min));
   }

막대 녹음 기능에서 제로 날짜 확인을 추가하십시오.

   //функция записывает текущие экстремумы
   void WriteBar( int eNumber, string eSymbol, ENUM_TIMEFRAMES eFrame, datetime eTime)
      {
       if (eTime== 0 ) return ;
       int eShift= iBarShift (eSymbol,eFrame,eTime);

둘째, day.Arr[day.index].high에서 현재 날짜입니다. 어제가 필요하면 이전 요소에 있습니다.

 if (day.index> 0 )
   {
   printf (day.Arr[day.index- 1 ].high);
   }

아마도 이제 논리가 정확해야 합니다. 많이 테스트해보진 않았지만 맞는것 같습니다.

 
Dark Kchlyzov :

벌써 42세인데도 1등급이 된 기분이다.

:) 그것은 모두 경험과 함께 제공되며, 나는 또한 많은 것을 이해하지 못하고 그 과정에서 배웁니다. 이론적으로 우리는 구조가 아니라 클래스를 가져야 합니다. OOP에 거의 다 왔습니다. 내가 아직도 수영하고 있는 곳.
 

ArrayCopyRates 의 경우 Aleksey가 올바르게 말했습니다. 도움말은 다음과 같이 말합니다.

Копирует в двумерный массив вида double RateInfo[][6] данные баров указанного графика и возвращает количество скопированных баров.

따라서 다음을 작성해야 합니다.

 int total=ArrayCopyRates(Bar_data_D1, _Symbol , PERIOD_D1 ); // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров

 Low_D1_Level   = iLow ( _Symbol , PERIOD_D1 , 1 );   // Возвращает значение минимальной цены бара  D1
    
 for ( int i = 1 ; i<total ;i++)
    {
    

그러나 이것은 낭비적인 코드입니다.