Ошибки, баги, вопросы - страница 3472

 
fxsaber #:

Просьба описать баг. Так и не понял из обсуждения.

как выше верно заметили, теперь это фича :-)

если индикатор из OnInit() возвращает INIT_FAILED , то он всё равно остаётся висеть в списке индикаторов (и в шаблонах, и при смене таймфрейма снова будет вызван OnInit)

к тому-же как выяснилось от этого нефункционирующего индикатора можно получить хендл как от нормального

код индикатора с INIT_FAILED https://www.mql5.com/ru/forum/1111/page3471#comment_51963944

код скрипта берущего хендл вот https://www.mql5.com/ru/forum/1111/page3471#comment_51964451

Ошибки, баги, вопросы
Ошибки, баги, вопросы
  • 2024.01.30
  • www.mql5.com
Общее обсуждение: Ошибки, баги, вопросы
 
fxsaber #:

Просьба описать баг. Так и не понял из обсуждения.

Запускаю индикатор


Гифка у меня на экране как будто пустая, но если по ней кликнуть, то показывает.

Думаю на ней понятна суть проблемы.


Просто подтвердите, что это баг.

К вашим словам разработчики чаще прислушиваются. (ИМХО)

Файлы:
 
Maxim Kuznetsov #:

как выше верно заметили, теперь это фича :-)

Уважаемый, ну мы же с вами про два разных бага рассказываем.

Вы про продолжение работы индикатора после  INIT_FAILED.

Я про продолжение работы индикатора после его удаления с графика.

Давайте не будем путать аудиторию)))


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

 
Aleksandr Slavskii #:

Гифка у меня на экране как будто пустая, но если по ней кликнуть, то показывает.

Не показывает.
 
fxsaber #:
Не показывает.
У меня в смартфоне показывает.
 
fxsaber #:
Не показывает.

В новой вкладке показывает.

 
Aleksandr Slavskii #:

Имеем: Индикатор(код здесь), который получает хэндл на самого себя.

Далее в своей работе он обращается к этому хэндлу и получает какие то данные.

До этого момента всё хорошо.

Проблема возникает при удалении такого индикатора с графика. Он не заходит в OnDeinit и продолжает работать, хотя в списке индикаторов его на графике уже нет.

И удалить такой индикатор с графика получается только перезагрузкой терминала.

Что нужно получить? 

Работающий индикатор с нормальным удалением его с графика.

С помощью ваших рекомендаций, получается добиться только нормального удаления, но при этом индикатор перестаёт работать)

#property indicator_chart_window
#property indicator_plots 0
#property indicator_buffers 1
int indicator_handle = INVALID_HANDLE;
double indBuff[];
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, indBuff, INDICATOR_DATA);
   printf("GetTickCount: %llu", GetTickCount());

   string indicator_shortname = ::MQLInfoString(MQL_PROGRAM_NAME);
   const int wnd_count  = (int)ChartGetInteger(ChartID(), CHART_WINDOWS_TOTAL);
   for(int wndptr = NULL; (wndptr < wnd_count) && (indicator_handle == INVALID_HANDLE); wndptr++)
      for(int ind_cnt = ChartIndicatorsTotal(ChartID(), wndptr) - 1; (ind_cnt >= NULL) && (indicator_handle == INVALID_HANDLE); ind_cnt--)
         indicator_handle = (ChartIndicatorName(ChartID(), wndptr, ind_cnt) == indicator_shortname) ? ChartIndicatorGet(ChartID(), wndptr, indicator_shortname) : indicator_handle;
   printf("Indicator handle: %i", indicator_handle);
   
//   IndicatorRelease(indicator_handle);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//   IndicatorRelease(indicator_handle);
   printf("OnDeInit reason: %i; GetTickCount: %llu", reason, GetTickCount());
  }
//+------------------------------------------------------------------+
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[])
  {
   double buff[];
   indBuff[rates_total - 1] = close[rates_total - 1];
   if(indicator_handle != INVALID_HANDLE)
     {
      CopyBuffer(indicator_handle, 0, 0, 1, buff);
      IndicatorRelease(indicator_handle);
      
      Print(buff[0]);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Maxim Kuznetsov #:

если индикатор из OnInit() возвращает INIT_FAILED , то он всё равно остаётся висеть в списке индикаторов (и в шаблонах, и при смене таймфрейма снова будет вызван OnInit)

int     indicator_handle    = INVALID_HANDLE;
int     indicator_subwnd_id = -1;
string  indicator_shortname = NULL;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
    printf("GetTickCount: %llu", GetTickCount());


    indicator_shortname = ::MQLInfoString(MQL_PROGRAM_NAME);
    const int wnd_count  = (int)ChartGetInteger(ChartID(), CHART_WINDOWS_TOTAL);        
    for(int wndptr = NULL; (wndptr < wnd_count) && (indicator_handle == INVALID_HANDLE); wndptr++)
    {
        for(int ind_cnt = ChartIndicatorsTotal(ChartID(), wndptr) - 1; (ind_cnt >= NULL) && (indicator_handle == INVALID_HANDLE); ind_cnt--)
        { indicator_handle = (ChartIndicatorName(ChartID(), wndptr, ind_cnt) == indicator_shortname) ? ChartIndicatorGet(ChartID(), wndptr, indicator_shortname) : indicator_handle; }
        indicator_subwnd_id = (indicator_handle != INVALID_HANDLE) ? wndptr : indicator_subwnd_id;
    }
    printf("Indicator handle: %i", indicator_handle);
    IndicatorRelease(indicator_handle);
        
    return(INIT_FAILED);
    return((indicator_subwnd_id != -1) ? INIT_SUCCEEDED : INIT_FAILED);
}


void OnDeinit(const int reason)
{
    ChartIndicatorDelete(ChartID(), indicator_subwnd_id, indicator_shortname);
    IndicatorRelease(indicator_handle);

    string text = "Another reason";
    switch(reason)
    {
        case REASON_ACCOUNT:        text="Account was changed";                         break;
        case REASON_CHARTCHANGE:    text="Symbol or timeframe was changed";             break;
        case REASON_CHARTCLOSE:     text="Chart was closed";                            break;
        case REASON_PARAMETERS:     text="Input-parameter was changed";                 break;
        case REASON_RECOMPILE:      text="Program "+__FILE__+" was recompiled";         break;
        case REASON_REMOVE:         text="Program "+__FILE__+" was removed from chart"; break;
        case REASON_TEMPLATE:       text="New template was applied to chart";           break;
    }
    printf("OnDeInit reason: %s; GetTickCount: %llu", text, GetTickCount());
}



//+------------------------------------------------------------------+
//| 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[])
{
    printf("OnCalculate call: %s; GetTickCount: %llu", TimeToString(time[rates_total - 1]), GetTickCount());

    return(rates_total);
}
 
@Aleksandr Slavskii, @Maxim Kuznetsov, копи-пастил чужие коды с мин. добавками, что здесь вчера выкладывались.
 
Aleksandr Slavskii #:

Уважаемый, ну мы же с вами про два разных бага рассказываем.

Вы про продолжение работы индикатора после  INIT_FAILED.

Я про продолжение работы индикатора после его удаления с графика.

Давайте не будем путать аудиторию)))

у вас не вполне баг: просто циклическая ссылка (сам на себя) и поэтому флаг _IsStopped всегда false и OnDeinit() не вызывается. Циклические зависимости между индикаторами не отслеживаются платформой, там просто счётчик ссылок.

Чтобы подобное выгрузить - надо в таймере читать список индикаторов и если ваш оттуда пропал, то вызывать IndicatorRelease;

(не проверял, но) ещё можно ориентироваться по OnChartEvent - эвенты просто перестанут приходить. 

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