Array out of range in Нужна Помощь - страница 9

 
Aleksei Stepanenko:

По поводу ArrayCopyRates Алексей правильно говорил. В справке написано:

Значит нужно писать:

Но это неэкономный код.

Да, смысла тащить все 6 показателей бара нет, если нужен только один. Лоу.

И нет смысла вглубь глубоко идти на одном масштабе (ТФ). После квартала можно перейти на недели, потом на месяцы, а 132 месяца, это 11 лет.

В общем мысль, что нет смысла считать на всем графике, количество исторических данных по сути случайно, может быть с 70 года, а может с 2000, на разном инструменте у разных поставщиков данных разное, а логика всегда лучше, когда она едина для всех случаев. 

 

Валерий, точно говорите!

По идее нам нужны только эти бары истории:


Остальное можно выкинуть из массива. Вот тогда это будет экономично.

 
Aleksei Stepanenko:

Валерий, точно говорите!

По идее нам нужны только эти бары истории:


Остальное можно выкинуть из массива. Вот тогда это будет экономично.

Так было нарисовано. Идея пока ТопикСтартером не озвучена)

Надо найти значимые для ТС экстремумы и сравнить их. Одинаковых Лоу на расстоянии много. Достаточно часто Опен и Клоз на одной свече равны, а что говорить про минимальные цены дня на значительном расстоянии.

 

Заметил ошибку в циклах. И изменил сравнение не с текущим днём, а вчерашним. Попробуйте

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

Приветствую Всех !!!

Отлучался по делам .

Процесс полным ходом .

 

Протестировал !

Результат такой. 

Остановил тестер пошли по истории вручную. Значение Max_D должен браться от сюда.

 

 

Я не понял, что не так. Это линия минимумов.

На всякий пожарный, скопируйте код по-новой, я там менял периодически, возможно, у Вас старая версия

 
Valeriy Yastremskiy:

Да, смысла тащить все 6 показателей бара нет, если нужен только один. Лоу.

И нет смысла вглубь глубоко идти на одном масштабе (ТФ). После квартала можно перейти на недели, потом на месяцы, а 132 месяца, это 11 лет.

В общем мысль, что нет смысла считать на всем графике, количество исторических данных по сути случайно, может быть с 70 года, а может с 2000, на разном инструменте у разных поставщиков данных разное, а логика всегда лучше, когда она едина для всех случаев. 

   Попробую изъяснится точнее. 

   1. Это не идея а рабочий и уже отлаженный 5 летний опыт торговли который решено было автоматизировать (так как сидень у монитора постоянно это не очень, понимаешь с годами )

   2. По этим линия формируется сигнал ложных пробоев и это работает (просто нужно знать как их применять) в дальнейшем их можно вообще не выводить .

   3. В 2020 г 10 февраля впервые заметил эту не неточность которая как вы думаете не нужна из такой далекой истории  

   обратите внимание где где находится Min_D  и может быть раз в год а то и в 10лет.(как пойдёт)

 

далее вы видим развитее событий 12000 пунктов шорт ( думаю не допустимо пропускать такие движение) В данном случаи выход за массив и не дал мне упустить эту возможность.

   

   Вот так это и работает по сей день   в общем не доставляло особых проблем 

   


   Ну а сей час пришло время двигается дальше и изучать MQL4


   4. Что касается загрузки компа или еще чего там (то раз в сутки в 24.00 можно и пересчитать и 10 раз не торгую в пятницу после 20.00 , и в будни с 23.00 до 3.00) пусть себе считает.

   5.   Идея пока ТопикСтартером не озвучена .

         Если читать с начала поста а не с середины все понятно.

         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:

Я не понял, что не так. Это линия минимумов.

На всякий пожарный, скопируйте код по-новой, я там менял периодически, возможно, у Вас старая версия

Ок Ща попробую еще раз