Un errore di divisione per zero è apparso in un indicatore

 

Dall'inizio della settimana, il terminale ha iniziato a bloccarsi stupidamente: non so più cosa fare.

In un indicatore è apparsa una divisione per zero errori - c'è un semplice delta - viene richiesta la data iniziale e vengono aggiunti i secondi e viene sottratta la data iniziale. Prima di allora, l'indicatore ha funzionato stabilmente per sei mesi.

Dove scavare? Come decidere?

Codice: per impostazione predefinita, eseguito su TF al di sotto di TimeFrames, consigliato da 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:

Dall'inizio della settimana, il terminale è bloccato - non so cosa fare.

In un indicatore è apparso un errore di divisione per zero - c'è un semplice delta - viene richiesta una data di inizio e i secondi vengono aggiunti ad essa e la data di inizio viene sottratta. L'indicatore ha funzionato bene per mezzo anno prima.

Dove devo scavare? Come risolvere il problema?

Passare attraverso il debugger e vedere?

Ovviamente, la divisione non controlla un possibile valore nullo.

 
Aleksey Vyazmikin:

Dall'inizio della settimana, il terminale è bloccato - non so cosa fare.

In un indicatore è apparso un errore di divisione per zero - c'è un semplice delta - viene richiesta una data di inizio e i secondi vengono aggiunti ad essa e la data di inizio viene sottratta. L'indicatore ha funzionato bene per mezzo anno prima.

Dove scavare? Come risolvere il problema?

Quando si verifica un tale errore, si vede il numero di linea e la posizione in esso. Controlla quale valore c'è e controllalo a 0 prima di dividere.

 
Georgiy Merts:

Andare al debugger e vedere?

Ovviamente, quando si divide - non c'è nessun controllo per un possibile valore zero.

Alexey Kozitsyn:

Quando si verifica questo errore, vi si scrive il numero di linea e la posizione. Vedi che valore c'è e controlla che sia 0 prima di dividere.

Grazie, questo è certamente chiaro - controlla la divisione per zero! Sono più preoccupato del perché questo zero ha iniziato a verificarsi, quando si accede all'array di date dall'indicatore.

 
Aleksey Vyazmikin:

Grazie, questo è certamente chiaro - controlla la divisione per zero! Mi preoccupa di più il motivo per cui si verifica questo zero, quando si accede all'array di date dall'indicatore.

Può mostrarmi un esempio? Problema riproducibile del codice minimo?

 
Aleksey Vyazmikin:

Grazie, questo è certamente chiaro - controlla la divisione per zero! Mi preoccupa di più il motivo per cui si verifica questo zero, quando si accede all'array di date dall'indicatore.

È qui che devi scoprire dal codice qual è il denominatore! E perché diventa zero... Se è un riferimento a una data, allora qualche data viene azzerata...

 
Aleksey Vyazmikin:

Ho anche avuto alcuni indicatori che "galleggiano" dopo l'aggiornamento... bisogno di capire cosa c'è che non va...

 
Vladimir Karputov:

Può mostrare un esempio? Problema riproducibile del codice minimo?

L'indicatore è stato scritto su ordinazione - tutto è complicato lì, sto cercando di ottenere la ragione da solo, ma finora non posso...

Qui il limite diventa zero.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:

L'indicatore è stato scritto su ordinazione - è tutto complicato, sto cercando di ottenere la causa da solo, ma finora non riesco...

Qui il limite diventa zero.TimeFrames==PERIOD_H1

Serve un problema riproducibile con codice minimo. Non un pezzo di codice.

 
Alexey Kozitsyn:

È qui che devi scoprire dal codice qual è il denominatore! E perché diventa zero... Se si riferisce alle date, allora qualche data è azzerata...

Sì, devo scoprirlo - ho stampato date per mezza giornata ieri - tutto andava bene, poi ho spento la stampante e quasi immediatamente ho avuto un errore - anomalie...

Sopra ha postato il codice, puoi dirmi dove scavare?


Alexey Kozitsyn:

Ho anche alcuni indicatori che "galleggiano" dopo l'aggiornamento... bisogno di capire cosa c'è che non va...

Sì, posso immaginare come deve essere per quelli che, per esempio, non capiscono affatto il codice.