Obviously bug in indicators OnInit() return value effect

 

It seems return value of indicators is not being respected by terminal. It works for Experts, but not for indicators.


Expert code:

int OnInit()
{
    printf("OnInit() returning: INIT_FAILED: %i", INIT_FAILED);
    return(INIT_FAILED);
}

Result in Terminal Journal:

2024.01.28 11:15:52.140    Experts    expert Playground2 (EURUSD,M1) loaded successfully
2024.01.28 11:15:54.511    Experts    initializing of Playground2 (EURUSD,M1) failed with code 1
2024.01.28 11:15:54.516    Experts    expert Playground2 (EURUSD,M1) removed


Indicator code:

int OnInit()
{
    printf("OnInit() returning: INIT_FAILED: %i", INIT_FAILED);
    return(INIT_FAILED);
}

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[]) 
{
   return(rates_total);
}

Result in Terminal Journal:

2024.01.28 11:17:23.592    Indicators    custom indicator mql5_indicator (EURUSD,M1) loaded succesfully

Step on New Rails: Custom Indicators in MQL5
Step on New Rails: Custom Indicators in MQL5
  • www.mql5.com
I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.
 

I confirm the situation. The indicator is not released from the chart (build 4153).


I also tested with "INIT_PARAMETERS_INCORRECT", but the results were the same—the indicator was not removed from the chart.
 

MT4 Follow-up: build 1403

In MQL4 with "#property strict" it worked correctly ...



So, if it is working correctly on MT4 with "#property strict", then it is a bug in MT5.

PS! I did try add "#property strict" to the MQL5 version, but it had no effect.

Here is the code used for both MQL4 and MQL5 ...
#property strict
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0

int OnInit() {
   PrintFormat( "OnInit() returning: INIT_FAILED: %i", INIT_FAILED );
   return INIT_FAILED;
};

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[]) {
   return rates_total;
};
 
Fernando Carreiro #:

MT4 Follow-up:

I forgot to add "#property strict" to the MQL4 code. When I added it, it worked correctly ...

So, if it is working correctly on MT4 with "#property strict", then it is a bug in MT5.

PS! I did try add "#property strict" to the MQL5 version, but it had no effect.

Thank you for confirming and further verification.

So it's a Bug and not a feature....
 

I took the liberty in reporting it in the Russian section ...

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

Fernando Carreiro, 2024.01.28 14:05

В английском разделе Доминик Эгерт обнаружил ошибку MT5, при которой пользовательские индикаторы не выпускаются, даже если OnInit() возвращает «INIT_FAILED» (или « INIT_PARAMETERS_INCORRECT »).

Я также подтвердил ошибку в МТ5 и обнаружил, что она корректно работает на МТ4.


In the English section, a MT5 bug has been identified by Dominik Egert where Custom Indicators are not released even when OnInit() returns "INIT_FAILED" (or "INIT_PARAMETERS_INCORRECT").

I also confirmed the bug in MT5 and found that it works correctly on MT4.

 
Fernando Carreiro #:

I took the liberty in reporting it in the Russian section ...

That seems a reasonable move. I asked Alexey to take a look at this thread.
 

As responded by MQ on russian forum, it is a feature, not a bug. Please see post here:

https://www.mql5.com/ru/forum/1111/page3465#comment_51950020


But here is a method for making an indicator permanent, unremovable by any means, except for restarting the entire terminal.


int indicator_handle = INVALID_HANDLE;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
    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);
    
    return(INIT_SUCCEEDED);
}


void OnDeinit(const int reason)
{
    IndicatorRelease(indicator_handle);
    printf("OnDeInit reason: %i; GetTickCount: %llu", reason, 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);
}
//+------------------------------------------------------------------+

I am not sure, if this is meant to be that way, I guess not.

Supposedly, it is also not desired to retrieve a handle on the same instance of the indicator. - Questionable.

For now, this is the only generic way to gain access to custom defined buffers within the same indicator. - That actually works.

So in conclusion, it is possible to receive a handle to your own instance of indicator, retrieve its buffer values in a generic way, but you cannot remove the indicator anymore, after retrieving the handle.

Ошибки, баги, вопросы
Ошибки, баги, вопросы
  • 2024.01.29
  • www.mql5.com
Общее обсуждение: Ошибки, баги, вопросы
 
Dominik Egert #: As responded by MQ on russian forum, it is a feature, not a bug. Please see post here: https://www.mql5.com/ru/forum/1111/page3465#comment_51950020

That is absolutely ridiculous (not you, I mean MetaQuotes).

If it works correctly on MT4, then it is not a feature — it is a blatant bug. It is not even explained in the documentation, and it is explained in the way it is practice in the MT4 implementation.

When an EA fails, it is also removed from the chart. Why would an indicator not follow the same procedure.

 
Fernando Carreiro #:

That is absolutely ridiculous (not you, I mean MetaQuotes).

If it works correctly on MT4, then it is not a feature — it is a blatant bug. It is not even explained in the documentation, and it is explained in the way it is practice in the MT4 implementation.

When an EA fails, it is also removed from the chart. Why would an indicator not follow the same procedure. It is is bug.

Also, there is no report in the journal about it, no "InitFailed" with reason xyz... Which I personally think, should be the minimum that is required.

I am on the same page as you, it is very obviously a bug.

 
Dominik Egert #: Also, there is no report in the journal about it, no "InitFailed" with reason xyz... Which I personally think, should be the minimum that is required. I am on the same page as you, it is very obviously a bug.

Yes, absolutely! At the very least a warning message in the log.

As it stands, if it were truely a "feature", then for Indicators it would be mandatory to use the "void OnInit()" version of the handler and the compiler would throw an error (or at least a warning) if you use the "int OnInit()" version.

 

In light of the discussion going on in the Russian section, it seems that this is considered a "feature" and not a bug, unfortunately.

For those wishing for a work around, here are some recommended references ...

Forum on trading, automated trading systems and testing trading strategies

Errors, bugs, questions

fxsaber , 2024.01.29 15:45

Fernando Carreiro # : Thanks for the workaround

On the topic , follow the link below.

Fernando Carreiro # : It would also help if they documented it properly too.
From the Textbook .
Receiving a descriptor from the   ChartIndicatorGet   function increases the internal usage counter for this indicator. The terminal execution system keeps loaded all indicators whose counter is greater than zero. Therefore, an indicator that is no longer needed must be explicitly released using a call to   IndicatorRelease . Otherwise, the indicator will remain idle and consume resources.

Forum on trading, automated trading systems and testing trading strategies

Errors, bugs, questions

fxsaber , 2024.01.29 15:20

You are simply not aware of the architectural feature of indicators - the internal counter. Apparently you need to write this line.

 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 ((indicator_subwnd_id != - 1 ) ? INIT_SUCCEEDED : INIT_FAILED );
}