В одном индикаторе появилась ошибка деления на ноль

 

С начала недели начал тупо виснуть терминал - уже и не знаю, что делать.

В одном индикаторе появилась ошибка деления на ноль - там простая дельта - запрашивается начальная дата и к ней прибавляются секунды и вычитается начальная дата. Индикатор до этого работал пол года стабильно.

Где копать? Как решать?

Код - по умолчанию запускать на TF ниже TimeFrames, рекомендовано M1. 

//+------------------------------------------------------------------+
//|                                                   IndDrafter.mq5 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//----
input int                   IndId =1;                //номер индикатора
input ENUM_TIMEFRAMES  TimeFrames =PERIOD_H1;        //период работы
input bool          UseDeltaPrice =true;             //разрешение использовать для расчета ширины канала индикатор DeltaPrice
input int               HighPoint =1000;             //фиксированная ширина канала для верхней цены, в пунктах
input int                LowPoint =1000;             //фиксированная ширина канала для нижней цены, в пунктах
input int            VariantDraft =6;                //вариант построения графических фигур, 1-8
input int                BarsUsed =100;                //количество отображаемых баров, 0-вся история
input int        PeriodDeltaPrice =3;                //период индикатора DeltaPrice
input bool           UsePriceInfo =true;             //разрешение вывода показаний положения цены
input ENUM_APPLIED_PRICE    Price =PRICE_CLOSE;      //тип цены
input bool        UseVerticalLine =true;             //разрешение вывода вертикальной линии раздела времени
input ENUM_LINE_STYLE  StyleDraft =STYLE_DASH;       //стиль линии графических фигур
input color           ColorDraft1 =clrLimeGreen;     //первый цвет линии графических фигур
input color           ColorDraft2 =clrDarkOrchid;    //второй цвет линии графических фигур
input color           ColorDraft3 =clrDarkTurquoise; //третий цвет линии графических фигур
input ENUM_DRAW_TYPE StyleBuffer =DRAW_LINE;         //стиль линии индикатора положения цены
input color           ColorBuffer =clrRed;           //цвет линии индикатора положения цены
input int             WidhtBuffer =1;                //ширина линии индикатора положения цены
input bool            UseFiboGrid =true;             //разрешение накладывать сеть на графические фигуры
input ENUM_LINE_STYLE StyleFiboUp =STYLE_DOT;        //стиль линий сетки
input color           ColorFiboUp =clrWhite;         //цвет верхней сетки
input int             WidhtFiboUp =1;                //ширина линий верхней Fibo сетки
input double            LevelUp01 =23.6;             //значение первого уровня
input double            LevelUp02 =38.2;             //значение второго уровня
input double            LevelUp03 =50.0;             //значение третье уровня
input double            LevelUp04 =61.8;             //значение четвертого уровня
input double            LevelUp05 =76.4;             //значение пятого уровня
input double            LevelUp06 =100.0;            //значение шестого уровня
input double            LevelUp07 =123.6;            //значение седьмого уровня
input double            LevelUp08 =138.2;            //значение восьмого уровня
input double            LevelUp09 =150.0;            //значение девятого уровня
input double            LevelUp10 =161.8;            //значение десятого уровня
input ENUM_LINE_STYLE StyleFiboDn =STYLE_DOT;        //стиль линий сетки
input color           ColorFiboDn =clrAqua;          //цвет нижней сетки
input int             WidhtFiboDn =1;                //ширина линий нижней Fibo сетки
input double            LevelDn01 =23.6;             //значение первого уровня
input double            LevelDn02 =38.2;             //значение второго уровня
input double            LevelDn03 =50.0;             //значение третье уровня
input double            LevelDn04 =61.8;             //значение четвертого уровня
input double            LevelDn05 =76.4;             //значение пятого уровня
input double            LevelDn06 =100.0;            //значение шестого уровня
input double            LevelDn07 =123.6;            //значение седьмого уровня
input double            LevelDn08 =138.2;            //значение восьмого уровня
input double            LevelDn09 =150.0;            //значение девятого уровня
input double            LevelDn10 =161.8;            //значение десятого уровня
                                                     //input uint              InpCenterTime=12;            //время центральной линии
//----
double ExtBuffer[];
//----
double level_up[10];
double level_dn[10];
//----
int counted_bars;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
   IndicatorSetDouble(INDICATOR_MAXIMUM,2.05);
   IndicatorSetDouble(INDICATOR_MINIMUM,-0.05);
   IndicatorSetString(INDICATOR_SHORTNAME,"Drafter "+IntegerToString(IndId)+" "+IntegerToString(VariantDraft));
//----
   SetIndexBuffer(0,ExtBuffer);
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,StyleBuffer);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,WidhtBuffer);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,ColorBuffer);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   PlotIndexSetString(0,PLOT_LABEL,"var "+IntegerToString(VariantDraft));
//----
   counted_bars=0;
   level_up[0]=LevelUp01;
   level_up[1]=LevelUp02;
   level_up[2]=LevelUp03;
   level_up[3]=LevelUp04;
   level_up[4]=LevelUp05;
   level_up[5]=LevelUp06;
   level_up[6]=LevelUp07;
   level_up[7]=LevelUp08;
   level_up[8]=LevelUp09;
   level_up[9]=LevelUp10;
   level_dn[0]=LevelDn01;
   level_dn[1]=LevelDn02;
   level_dn[2]=LevelDn03;
   level_dn[3]=LevelDn04;
   level_dn[4]=LevelDn05;
   level_dn[5]=LevelDn06;
   level_dn[6]=LevelDn07;
   level_dn[7]=LevelDn08;
   level_dn[8]=LevelDn09;
   level_dn[9]=LevelDn10;
//----
   ObjectsDeleteAll(0,"IndDrafter tline "+IntegerToString(IndId),0);
   ObjectsDeleteAll(0,"IndDrafter triangle "+IntegerToString(IndId),0);
   ObjectsDeleteAll(0,"IndDrafter fibo line "+IntegerToString(IndId),0);
   ObjectsDeleteAll(0,"IndDrafter fibo text "+IntegerToString(IndId),0);
//----
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,"IndDrafter tline "+IntegerToString(IndId),0);
   ObjectsDeleteAll(0,"IndDrafter triangle "+IntegerToString(IndId),0);
   ObjectsDeleteAll(0,"IndDrafter fibo line "+IntegerToString(IndId),0);
   ObjectsDeleteAll(0,"IndDrafter fibo text "+IntegerToString(IndId),0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   if(_Period>=TimeFrames) return(0);
   if(prev_calculated==0) counted_bars=0;
//---
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(ExtBuffer,true);
//----
   int Bars=Bars(_Symbol,TimeFrames);
   int limit=0;
   int pdprice=(UseDeltaPrice?PeriodDeltaPrice:0);
   MqlRates rates_array[];
   if(counted_bars==0)
     {
      if(BarsUsed>0)
         limit=CopyRates(_Symbol,TimeFrames,time[0],BarsUsed+pdprice,rates_array);
      else if(BarsUsed==0)
         limit=CopyRates(_Symbol,TimeFrames,time[0],Bars(_Symbol,TimeFrames,time[rates_total-1],time[0])+pdprice,rates_array);
         //limit=CopyRates(_Symbol,TimeFrames,time[rates_total-1],time[0],rates_array);
      if(limit<=pdprice) return(0);
      ArraySetAsSeries(rates_array,true);
      for(int i=limit-pdprice-1;i>=0;i--)
         CreateFigure(i,time,open,high,low,close,rates_array);
     }
   else
     {
      limit=CopyRates(_Symbol,TimeFrames,0,Bars-counted_bars+pdprice+1,rates_array);
      if(limit<=pdprice) return(0);
      ArraySetAsSeries(rates_array,true);
      for(int i=limit-pdprice-1;i>=0;i--)
         CreateFigure(i,time,open,high,low,close,rates_array);
     }
//----
   counted_bars=Bars;
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CreateFigure(int i,const datetime &Time[],const double &Open[],const double &High[],const double &Low[],const double &Close[],MqlRates &rates[])
  {
   datetime start_time=rates[i].time;
   datetime stop_time=(start_time+PeriodSeconds(TimeFrames));
//---
   int start_index,stop_index,limit;
   datetime vertical_line_time;
//---
   start_index=ArrayBsearch(Time,start_time);
   if(Time[start_index]<start_time) start_index=(start_index>0?start_index-1:start_index);
   start_time=Time[start_index];
   if(i>0)
     {
      stop_index=ArrayBsearch(Time,stop_time);
      if(Time[stop_index]>stop_time) stop_index++;
      stop_time=Time[stop_index];
      limit=start_index-stop_index+1;
      vertical_line_time=Time[start_index-(limit>>1)];
     }
   else
     {
      if(TimeFrames==PERIOD_MN1)
        {
         MqlDateTime mql_time;
         TimeToStruct(start_time+2678400,mql_time);
         int days=32-mql_time.day;
         stop_time=start_time+days*86400;
        }
      else if(TimeFrames==PERIOD_W1) stop_time-=86400;
      vertical_line_time=start_time+(stop_time-start_time)/2;
      limit=(int)(stop_time-start_time)/PeriodSeconds(_Period);
     }
//---
   double center_line_point=rates[i].open;
   double delta_price_high=0.0;
   double delta_price_low=0.0;
//----
   if(UseDeltaPrice==true)
     {
      delta_price_high=center_line_point+HighPoint*_Point;
      delta_price_low=center_line_point-LowPoint*_Point;
     }
//----
   if(UseDeltaPrice==false)
     {
      delta_price_high=center_line_point+HighPoint*_Point;
      delta_price_low=center_line_point-LowPoint*_Point;
     }
//----
   if(UseVerticalLine){};
//----
   if(VariantDraft==6)
     {
      if(UsePriceInfo==true)
        {
         if(limit/2==0)
         {
         //limit=2;
         Print("i=",i," start_time - ",TimeToString(start_time,TIME_DATE|TIME_MINUTES)," stop_time - ",TimeToString(stop_time,TIME_DATE|TIME_MINUTES));
         Print("start_index=",start_index, " stop_index=",stop_index);
         Print("TimeFrames=",PeriodSeconds(TimeFrames));
         //start_index=ArrayBsearch(Time,start_time);
         }
         double d1=(delta_price_high-center_line_point)/((double)limit/2.0);
         double d2=(center_line_point-delta_price_low)/((double)limit/2.0);
         //----
        }
      //----
      if(UseFiboGrid==true)
        {
        }
     }
//----

  }
 
Aleksey Vyazmikin:

С начала недели начал тупо виснуть терминал - уже и не знаю, что делать.

В одном индикаторе появилась ошибка деления на ноль - там простая дельта - запрашивается начальная дата и к ней прибавляются секунды и вычитается начальная дата. Индикатор до этого работал пол года стабильно.

Где копать? Как решать?

Пройтись в отладчике, да поглядеть ?

Очевидно, что при делении - не производится проверки на возможное нулевое значение.

 
Aleksey Vyazmikin:

С начала недели начал тупо виснуть терминал - уже и не знаю, что делать.

В одном индикаторе появилась ошибка деления на ноль - там простая дельта - запрашивается начальная дата и к ней прибавляются секунды и вычитается начальная дата. Индикатор до этого работал пол года стабильно.

Где копать? Как решать?

Когда выпадает такая ошибка - пишется же номер строки и позиция в ней. Посмотрите что там за значение и проверяйте его на 0 перед делением.

 
Georgiy Merts:

Пройтись в отладчике, да поглядеть ?

Очевидно, что при делении - не производится проверки на возможное нулевое значение.

Alexey Kozitsyn:

Когда выпадает такая ошибка - пишется же номер строки и позиция в ней. Посмотрите что там за значение и проверяйте его на 0 перед делением.

Спасибо, это конечно же ясно - проверить деление на ноль! Меня больше волнует, почему же возникать стал этот ноль, при обращении к массиву дат из индикатора.

 
Aleksey Vyazmikin:

Спасибо, это конечно же ясно - проверить деление на ноль! Меня больше волнует, почему же возникать стал этот ноль, при обращении к массиву дат из индикатора.

Пример можете показать? Минимальный код воспроизводимый проблему?

 
Aleksey Vyazmikin:

Спасибо, это конечно же ясно - проверить деление на ноль! Меня больше волнует, почему же возникать стал этот ноль, при обращении к массиву дат из индикатора.

Вот тут Вам и нужно выяснить по коду, чем является знаменатель! И почему он становится нулем... Если обращение к датам, значит какая-то дата зануляется...

 
Aleksey Vyazmikin:

У меня тоже некоторые индикаторы "поплыли" после обновления... надо разбираться в чем дело...

 
Vladimir Karputov:

Пример можете показать? Минимальный код воспроизводимый проблему?

Индикатор писался на заказ - там хитро всё закручено, сам пытаюсь вытащить причину, но пока не получается...

Вот limit становится нулем. TimeFrames==PERIOD_H1

double d1=(delta_price_high-center_line_point)/(limit/2);
void CreateFigure(int i,const datetime &Time[],const double &Open[],const double &High[],const double &Low[],const double &Close[],MqlRates &rates[])
  {
   datetime start_time=rates[i].time;
   datetime stop_time=(start_time+PeriodSeconds(TimeFrames));

   int start_index,stop_index,limit;
   datetime vertical_line_time;

   start_index=ArrayBsearch(Time,start_time);
   if(Time[start_index]<start_time) start_index=(start_index>0?start_index-1:start_index);
   start_time=Time[start_index];
   if(i>0)
     {
      stop_index=ArrayBsearch(Time,stop_time);
      if(Time[stop_index]>stop_time) stop_index++;
      stop_time=Time[stop_index];
      limit=start_index-stop_index+1;
      vertical_line_time=Time[start_index-(limit>>1)];
     }
   else
     {
      if(TimeFrames==PERIOD_MN1)
        {
         MqlDateTime mql_time;
         TimeToStruct(start_time+2678400,mql_time);
         int days=32-mql_time.day;
         stop_time=start_time+days*86400;
        }
      else if(TimeFrames==PERIOD_W1) stop_time-=86400;
      vertical_line_time=start_time+(stop_time-start_time)/2;
      limit=(int)(stop_time-start_time)/PeriodSeconds(_Period);
     }
//--вырезано
}
 
Aleksey Vyazmikin:

Индикатор писался на заказ - там хитро всё закручено, сам пытаюсь вытащить причину, но пока не получается...

Вот limit становится нулем. TimeFrames==PERIOD_H1

Нужен минимальный код воспроизводимый проблему. А не кусок кода.

 
Alexey Kozitsyn:

Вот тут Вам и нужно выяснить по коду, чем является знаменатель! И почему он становится нулем... Если обращение к датам, значит какая-то дата зануляется...

Да, надо выяснить - пол дня принтавал вчера даты - было все нормально, потом отключил принт и почти сразу словил ошибку - аномалии...

Выше выложил код, можете по нему подсказать куда копать?


Alexey Kozitsyn:

У меня тоже некоторые индикаторы "поплыли" после обновления... надо разбираться в чем дело...

Мда, представляю, каково это тем, кто к примеру вообще не разбирается в коде.