Затык (переполнение стека)?

 

Работа в индикаторе с графическим объектом OBJ_REGRESSION.

Терминал:

2019.07.31 11:07:35.736 MetaTrader 5 x64 build 2093 started (MetaQuotes Software Corp.)
2019.07.31 11:07:35.737 Windows 10 (build 18362) x64, IE 11, UAC, Intel Core i3-3120M  @ 2.50GHz, Memory: 4058 / 8077 Mb, Disk: 99 / 415 Gb, GMT+2
2019.07.31 11:07:35.737 C:\Users\barab\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075

Настройки графиков в терминале:

Настройки графиков в терминале

Индикатор в OnCalculate при prev_calculated==0 создаёт графический объект OBJ_REGRESSION.

Далее перемещает обе точки графического объекта.


После перемещения делается попытка получить цены графического объекта (точка привязки "0" и точка привязки "1"). В тестере работает, а на графике получаю цены для обоих точек привязки равные "0.0" - при этом ObjectGetDouble и GetLastError ошибок не возвращают.


Код OnCalculate:

//+------------------------------------------------------------------+
//| 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[])
  {
/*
   time[0]              -> D'2018.01.02 00:00:00'
   time[rates_total-1]  -> D'2018.12.31 22:00:00'
*/
//---
   if(rates_total<InpChannelBars)
      return(0);

   int limit=prev_calculated-1;
   if(prev_calculated==0)
     {
      limit=InpChannelBars-1;
      for(int i=0;i<limit;i++)
         ChannelBuffer[i]=0.0;
      //---
      RegressionCreate(0,InpName,0,time[limit-(InpChannelBars-1)],time[limit],InpColor,InpStyle,InpWidth,
                       InpFill,InpBack,InpSelection,false,false,InpHidden,InpZOrder);
     }
   for(int i=limit;i<rates_total;i++)
     {
      if(RegressionPointChange(0,InpName,0,time[i-(InpChannelBars-1)]) && 
         RegressionPointChange(0,InpName,1,time[i]))
        {
         double price_point_0=0.0;
         double price_point_1=0.0;
         int error=0;
         //--- Point 0
         ResetLastError();
         if(!ObjectGetDouble(0,InpName,OBJPROP_PRICE,0,price_point_0))
           {
            error=GetLastError();
            Comment("Point 0 ERROR#"+IntegerToString(error));
            ChannelBuffer[i]=0.0;
            continue;
           }
         if(price_point_0==0.0)
           {
            error=GetLastError();
            Comment("Point 0 price "+DoubleToString(price_point_0,0));
            ChannelBuffer[i]=0.0;
            continue;
           }
         //--- Point 1
         ResetLastError();
         if(!ObjectGetDouble(0,InpName,OBJPROP_PRICE,1,price_point_1))
           {
            error=GetLastError();
            Comment("Point 1 ERROR#"+IntegerToString(error));
            ChannelBuffer[i]=0.0;
            continue;
           }
         if(price_point_1==0.0)
           {
            error=GetLastError();
            Comment("Point 1 price "+DoubleToString(price_point_1,0));
            ChannelBuffer[i]=0.0;
            continue;
           }
         ChannelBuffer[i]=(price_point_1-price_point_0)/Point();
        }
      else
        {
         Comment("");
         ChannelBuffer[i]=0.0;
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
Файлы:
 

Что обнаружил: индикатор установлен в терминале и продолжает выдавать цены обоих точек привязки для графического объекта (который и был создан этим индикатором) как "0.0".


Но если на этот график бросить такой скрипт:

//+------------------------------------------------------------------+
//|                                                            1.mq5 |
//|                              Copyright © 2019, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2019, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
#property script_show_inputs
input string            InpName        = "Regression";   // Channel name 
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   double price_point_0=ObjectGetDouble(0,InpName,OBJPROP_PRICE,0);
   double price_point_1=ObjectGetDouble(0,InpName,OBJPROP_PRICE,1);
   Comment(price_point_0,"\n",price_point_1);
//---
  }
//+------------------------------------------------------------------+

то скрипт при помощи ObjectGetDouble  возвращает цены обоих точек привязки правильно.

Файлы:
1.mq5  3 kb
 

Изменил индикатор: теперь он НЕ СОЗДАЕТ графический объект "Канал Регрессии" и не передвигает его - а только пытается получить значение цен для точек привязки

//+------------------------------------------------------------------+
//|                                         Trend OBJ_REGRESSION.mq5 |
//|                              Copyright © 2019, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2019, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"
#property indicator_separate_window
#property indicator_buffers 0
#property indicator_plots   0
//--- input parameters
input string            InpName="Regression";   // Channel name 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int  OnCalculate(
                 const int        rates_total,       // size of input time series 
                 const int        prev_calculated,   // number of handled bars at the previous call 
                 const datetime&  time[],            // Time array 
                 const double&    open[],            // Open array 
                 const double&    high[],            // High array 
                 const double&    low[],             // Low array 
                 const double&    close[],           // Close array 
                 const long&      tick_volume[],     // Tick Volume array 
                 const long&      volume[],          // Real Volume array 
                 const int&       spread[]           // Spread array 
                 )
  {
   double price_point_0=0.0;
   double price_point_1=0.0;
   int error=0;
//--- Point 0
   ResetLastError();
   if(!ObjectGetDouble(0,InpName,OBJPROP_PRICE,0,price_point_0))
     {
      error=GetLastError();
      Comment("Point 0 ERROR#"+IntegerToString(error));
      return(rates_total);
     }
   if(price_point_0==0.0)
     {
      error=GetLastError();
      Comment("Point 0 price "+DoubleToString(price_point_0,0));
      return(rates_total);
     }
//--- Point 1
   ResetLastError();
   if(!ObjectGetDouble(0,InpName,OBJPROP_PRICE,1,price_point_1))
     {
      error=GetLastError();
      Comment("Point 1 ERROR#"+IntegerToString(error));
      return(rates_total);
     }
   if(price_point_1==0.0)
     {
      error=GetLastError();
      Comment("Point 1 price "+DoubleToString(price_point_1,0));
      return(rates_total);
     }
   Comment((price_point_1-price_point_0)/Point());
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

и этот вариант работает! То есть если индикатор не создавал и не двигал графический объект - то индикатор через ObjectGetDouble корректно получает цены точек привязки.

Файлы:
 

Вероятно причина - переполнение очереди?

Из справки по ObjectGetDouble:

Примечание

Функция использует синхронный вызов – это означает, что функция дожидается выполнения всех команд, которые были помещены в очередь графика перед её вызовом, и поэтому данная функция может быть затратной по времени. Нужно иметь это обстоятельство в виду, если ведется работа с большим количеством объектов на графике.


НО в таком случае индикатор должен зависнуть, правильно? Или в индикаторах ObjectGetDouble возвращает "0.0" если очередь графика переполнена?

Причина обращения: