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

 
Aleksei Stepanenko :

ArrayCopyRates에 관해서는 Aleksey가 올바르게 말했습니다. 도움말은 다음과 같이 말합니다.

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

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

예, 하나만 필요한 경우 6개의 막대 표시기를 모두 끌 필요가 없습니다. 로우.

그리고 같은 규모(TF)로 깊이 들어가는 것은 이치에 맞지 않습니다. 분기가 끝나면 주, 월로 이동할 수 있으며 132개월은 11년입니다.

일반적으로 전체 차트를 계산하는 것이 의미가 없다는 생각, 과거 데이터 의 양은 본질적으로 무작위입니다. 아마도 70년 또는 2000년부터 다른 도구에서 다른 데이터 공급자가 다르고 논리가 다릅니다. 모든 경우에 대해 동일할 때 항상 더 좋습니다.

 

발레리, 당신 말이 맞아!

이론적으로 다음 히스토리 막대만 필요합니다.


나머지는 배열에서 버릴 수 있습니다. 그럴 때 경제적입니다.

 
Aleksei Stepanenko :

발레리, 당신 말이 맞아!

이론적으로 다음 히스토리 막대만 필요합니다.


나머지는 배열에서 버릴 수 있습니다. 그때가 경제적일 것입니다.

그렇게 그려졌습니다. 아이디어는 아직 TopikStarter에서 발표되지 않았습니다)

TS에 대해 극한값을 찾아 비교하는 것이 필요합니다. 멀리 떨어져 있는 동일한 Lowes가 많이 있습니다. 종종 Open과 Close는 같은 양초에서 동일하며 상당한 거리에서 그날의 최저 가격 에 대해 말할 수 있습니다.

 

주기에서 오류를 발견했습니다. 그리고 그는 비교를 오늘이 아니라 어제로 바꾸었다. 노력하다

 #property version    "1.00"
#property strict

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

long ChartId;
int Window;
string Name= "MiniMax" ;

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)
      {
       if (eTime== 0 ) return ;
       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 (index== 0 )
            {
            max=eHigh;
            time_max=eTime;
            min=eLow;
            time_min=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 (index> 0 )
         {
         max=Arr[index- 1 ].high;
         time_max=Arr[index- 1 ].time_high;
         for ( int i=index- 2 ; i>= 0 ; i--)
            {
             if (Arr[i].high-Arr[index- 1 ].high> 0 )
               {
               max=Arr[i].high;
               time_max=Arr[i].time_high;
               break ;
               }
            }
         }
       //если произошло обновление предыдущего минимума
       if (index> 0 )
         {
         min=Arr[index- 1 ].low;
         time_min=Arr[index- 1 ].time_low;
         for ( int i=index- 2 ; i>= 0 ; i--)
            {
             if (Arr[index- 1 ].low-Arr[i].low> 0 )
               {
               min=Arr[i].low;
               time_min=Arr[i].time_low;
               break ;
               }
            }
         }
      }
      
   double GetHigh() { return (index> 0 ?Arr[index- 1 ].high:Arr[index].high);}
   double GetLow() { return (index> 0 ?Arr[index- 1 ].low:Arr[index].low);}
   } day, month, year;

int OnInit ()
   {
   symbol= Symbol ();
   frame=( ENUM_TIMEFRAMES ) Period ();
   digits=( int ) SymbolInfoInteger (symbol, SYMBOL_DIGITS );
   //идентификатор графика и номер окна индикатора
   ChartId= ChartID ();
   Window= 0 ;
   return ( INIT_SUCCEEDED );
   }

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);
   
   RedrawHLine(ChartId,Window,Name+ " High" ,day.GetHigh(), clrBlue , 1 , DoubleToString (day.GetHigh(),digits),digits);
   RedrawHLine(ChartId,Window,Name+ " Low" ,day.GetLow(), clrBlue , 1 , DoubleToString (day.GetLow(),digits),digits);
   RedrawText(ChartId,Window,Name+ " High_Text" , iTime (symbol,frame, 30 ),day.GetHigh(), "Day 1:  " + DoubleToString (day.GetHigh(),digits), ANCHOR_RIGHT_LOWER , "Arial" , 8 , clrBlue , "" ,digits);
   RedrawText(ChartId,Window,Name+ " Low_Text" , iTime (symbol,frame, 30 ),day.GetLow(), "Day 1:  " + DoubleToString (day.GetLow(),digits), ANCHOR_RIGHT_UPPER , "Arial" , 8 , clrBlue , "" ,digits);

   RedrawHLine(ChartId,Window,Name+ " Max" ,day.max, clrRed , 1 , DoubleToString (day.max,digits),digits);
   RedrawHLine(ChartId,Window,Name+ " Min" ,day.min, clrRed , 1 , DoubleToString (day.max,digits),digits);
   RedrawText(ChartId,Window,Name+ " Max_Text" , iTime (symbol,frame, 30 ),day.max, "Day Max:  " + DoubleToString (day.max,digits), ANCHOR_RIGHT_LOWER , "Arial" , 8 , clrRed , "" ,digits);
   RedrawText(ChartId,Window,Name+ " Min_Text" , iTime (symbol,frame, 30 ),day.min, "Day Min:  " + DoubleToString (day.min,digits), ANCHOR_RIGHT_UPPER , "Arial" , 8 , clrRed , "" ,digits);
   }

//перерисовывает линию по новым координатам, если её нет, то создаёт
void RedrawHLine( long eChartId, int eWindow, string eName, double ePrice, color eColor, int eWidth, string eTooltip, int eDigits)
   {
   if ( ObjectFind (eChartId,eName)==- 1 )
      {
       if (! ObjectCreate (eChartId,eName, OBJ_HLINE ,eWindow, 0 , 0 )) return ;
       ObjectSetInteger (eChartId,eName, OBJPROP_STYLE , STYLE_SOLID );
       ObjectSetInteger (eChartId,eName, OBJPROP_WIDTH ,eWidth);
       ObjectSetInteger (eChartId,eName, OBJPROP_BACK , true );
       ObjectSetInteger (eChartId,eName, OBJPROP_SELECTABLE , false );
       ObjectSetInteger (eChartId,eName, OBJPROP_SELECTED , false );
       ObjectSetInteger (eChartId,eName, OBJPROP_HIDDEN , true );
      }
   if ( ObjectFind (eChartId,eName)==- 1 ) return ;   
   if ( NormalizeDouble ( ObjectGetDouble (eChartId,eName, OBJPROP_PRICE )-ePrice,eDigits)!= 0 ) ObjectSetDouble (eChartId,eName, OBJPROP_PRICE ,ePrice);
   if ( ObjectGetInteger (eChartId,eName, OBJPROP_COLOR )!=eColor) ObjectSetInteger (eChartId,eName, OBJPROP_COLOR ,eColor);
   if ( ObjectGetString (eChartId,eName, OBJPROP_TOOLTIP )!=eTooltip) ObjectSetString (eChartId,eName, OBJPROP_TOOLTIP ,eTooltip);
   }

//перерисовываем текст по новым координатам, если его нет, то создаём
void RedrawText( long eChartId, int eWindow, string eName, datetime eTime, double ePrice, string eText, ENUM_ANCHOR_POINT eAnchor, string eFont, int eSize, color eColor, string eTooltip, int eDigits)
   {
   if ( ObjectFind (eChartId,eName)==- 1 )
      {
       if (! ObjectCreate (eChartId,eName, OBJ_TEXT ,eWindow, 0 , 0 )) return ;
       ObjectSetString (eChartId,eName, OBJPROP_FONT ,eFont);
       ObjectSetInteger (eChartId,eName, OBJPROP_FONTSIZE ,eSize);
       ObjectSetDouble (eChartId,eName, OBJPROP_ANGLE , 0.0 );
       ObjectSetInteger (eChartId,eName, OBJPROP_ANCHOR ,eAnchor);
       //на переднем  плане
       ObjectSetInteger (eChartId,eName, OBJPROP_BACK , false );
       ObjectSetInteger (eChartId,eName, OBJPROP_SELECTABLE , false );
       ObjectSetInteger (eChartId,eName, OBJPROP_SELECTED , false );
       ObjectSetInteger (eChartId,eName, OBJPROP_HIDDEN , true );
       ObjectSetString (eChartId,eName, OBJPROP_TOOLTIP ,eTooltip);
      }
   if ( ObjectFind (eChartId,eName)==- 1 ) return ;
   //координаты метки
   if ( ObjectGetInteger (eChartId,eName, OBJPROP_TIME )!=eTime) ObjectSetInteger (eChartId,eName, OBJPROP_TIME ,eTime);
   if ( NormalizeDouble ( ObjectGetDouble (eChartId,eName, OBJPROP_PRICE )-ePrice,eDigits)!= 0 ) ObjectSetDouble (eChartId,eName, OBJPROP_PRICE ,ePrice);
   if ( ObjectGetInteger (eChartId,eName, OBJPROP_COLOR )!=eColor) ObjectSetInteger (eChartId,eName, OBJPROP_COLOR ,eColor);
   if ( ObjectGetString (eChartId,eName, OBJPROP_TEXT )!=eText) ObjectSetString (eChartId,eName, OBJPROP_TEXT ,eText);
   }
 

모두 환영합니다!!!

출장을 갔다.

프로세스가 한창 진행 중입니다.

 

테스트 완료!

결과는 이것입니다.

Stopped 테스터는 수동으로 기록을 살펴보았습니다. Max_D 값은 여기에서 가져와야 합니다.

 

나는 무엇이 잘못되었는지 이해하지 못했다. 이것은 낮은 라인입니다.

만약을 대비하여 새로운 방식으로 코드를 복사하고 주기적으로 변경했는데 이전 버전이 있을 수 있습니다.

 
Valeriy Yastremskiy :

예, 하나만 필요한 경우 막대의 6개 표시기를 모두 끌 필요가 없습니다. 로우.

그리고 같은 규모(TF)로 깊이 들어가는 것은 이치에 맞지 않습니다. 분기가 끝나면 주, 그 다음 달로 이동할 수 있으며 132개월은 11년입니다.

일반적으로 전체 차트를 계산하는 것이 의미가 없다는 생각, 과거 데이터 의 양은 본질적으로 무작위입니다. 아마도 70년 또는 2000년부터 다른 도구에서 다른 데이터 공급자가 다르고 논리가 다릅니다. 모든 경우에 대해 동일할 때 항상 더 좋습니다.

더 정확하도록 노력하겠습니다.

1. 이것은 아이디어가 아니라 자동화하기로 결정된 작동하고 이미 디버깅된 5년 거래 경험(항상 모니터에 앉아 있는 것이 좋지 않기 때문에 수년 동안 알다시피)

2. 이 라인은 잘못된 브레이크아웃의 신호를 형성하며 앞으로 작동합니다(사용 방법만 알면 됩니다). 나중에는 전혀 표시할 수 없습니다.

3. 2020년 2월 10일, 당신이 그렇게 먼 역사에서 필요하지 않다고 생각하는 이 부정확성을 처음으로 깨달았습니다.

Min_D가 어디에 있는지 , 아마도 1년에 한 번 또는 10년에 한 번 주의하십시오.

그러면 12000점짜리 쇼트의 전개가 보입니다. (이런 움직임을 놓치면 안 된다고 생각합니다.) 이 경우 어레이를 넘어선 이 기회를 놓칠 수 없었습니다.

이것이 오늘날까지 작동하는 방식입니다.   일반적으로 문제를 일으키지 않았습니다


자, 이제 계속해서 MQL4를 배울 시간입니다.


4. 거기에 컴퓨터 또는 다른 것의 로딩에 관해서는 (하루에 한 번 24.00에 계산할 수 있고 금요일 20.00 이후, 평일 23.00에서 3.00 사이에 10 번 계산할 수 있음) 계산하게하십시오.

5.   아이디어는 아직 TopikStarter에 의해 표명되지 않았습니다.

중간이 아니라 게시물의 처음부터 읽으면 모든 것이 명확합니다.

1. Low_D1 및 High_D1(D1 마지막 날), Min_D 및 Max_D(이것은 기록에서 가장 가깝고 정확히 기기에 사용할 수 있는 것) Min_D < Low_D1 및 Max_D > High_D1

2. Low_W1 및 High_W1(모든 것이 위에서 설명한 것과 동일하며 몇 주만)

3. Low_MN1과 High_MN1(여기는 각각 한 달)

 

코드에서 for 루프 // 설명을 읽습니다.

나는 그것을 고치는 방법에 대한 조언을 구하러 왔습니다. 아마도 제가 모르는 것이 있을 것입니다(예: 히스토리가 있는 일부 파일을 업로드하거나 어레이 자체에서 지원하지 않거나 16 기가 아페리티프로는 충분하지 않을 수 있습니다. 그게 질문 자체입니다. ??? 등.)

현재 라인이 값을 변경하지 않을 때 경고만 표시됩니다.

 //+------------------------------------------------------------------+
//|                                                   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;
int       A_C_R;             // возвращает количество скопированных баров D1
//+------------------------------------------------------------------+
//| 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()
{
  A_C_R = 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();
   }
}
 
Aleksei Stepanenko :

나는 무엇이 잘못되었는지 이해하지 못했다. 이것은 낮은 라인입니다.

만약을 대비하여 새로운 방식으로 코드를 복사하고 주기적으로 변경했는데 이전 버전이 있을 수 있습니다.

알았어 다시 해볼게