Features of the mql5 language, subtleties and tricks - page 33

 
Artyom Trishkin:

Highlighted can return 0. I ran into them at BCS.

Yeah, crooked brokers. They would also put negative numbers there.

It would be good if developers had a limit of possible values range for each parameter when brokers set symbols.

 
Artyom Trishkin:

What exactly is wrong? That was the question - what am I doing wrong to get indicator data from a non-native timeframe?

Example: The indicator is running on М1, while data from АO should be obtained from М5. So, while we have limit>1 (history needs to be recalculated), AO from M5 returns zeros with absence of data error. As soon as the history is calculated (limit==0), the data starts to arrive from AO with M5.

To begin with - you don't need to make such entries:

periodForWork=PeriodForWork;

I first thought that you were assigning to a variable its own value.

Next:

size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);

There is no need to copy during initialization. Initialization is not for this purpose. Moreover, this record will not be meaningful when data request from older TFs, which at the moment of request from OnInit() won't be calculated yet.

ArraySetAsSeries(BufferAO,true);

But this record is enough to be done just once at initialization stage.

Further ... um... subjectively, that's not how I would do it.

I like to break the program into:

1. First run (history analysis);

2. Subsequent runs:

2.1 Each tick;

2.2 Formed bar;

I.e:

if( prev_calculated > 0 )             // Не первый запуск
{
 if( rates_total <= prev_calculated ) // Новый бар не сформирован
  {
  }
 else                                 // Новый бар сформирован
  {
  }
}
else                                  // Первый запуск
{
}

And only after - the main cycle (function) of calculations.

Your copy-functions give out uninformative errors. Just the code is not very good.

There is no check of synchronization of the data of the older TF.

And the most important thing here is to understand the sequence. I advise you to create a test indicator, so it would only request the data of the major TF at the first start and to understand how the copying is made. I.e. to remove this from the beginning of the code:

ArraySetAsSeries(array_ao,true);

And to unset the first and the last element of the array. And only then, if necessary, change the direction of indexing.

 
Anyway, start there:
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
input   ENUM_TIMEFRAMES inpTimeframe=PERIOD_M5;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int _handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   _handle=iAO(_Symbol,inpTimeframe);
   if(_handle==INVALID_HANDLE)
     {
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),"! Хэндл индикатора iAO ТФ "+EnumToString(inpTimeframe)+" не получен!");
      return( INIT_FAILED );
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//--- Массив-приемник значений индикатора
   double ao[];
//---
   if(prev_calculated>0)
     {

     }
   else                                        // Если первый запуск
     {
      //--- Количество просчитанных баров старшего ТФ
      int bars;
      if(( bars=BarsCalculated(_handle))<0 || !(bool)SeriesInfoInteger(_Symbol,inpTimeframe,SERIES_SYNCHRONIZED))
         return( 0 );
      //--- 
      int num=CopyBuffer(_handle,0,0,bars,ao);
      //---
      if(num<0)
        {
         Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Запрашиваемая таймсерия еще не построена!");
         return( 0 );
        }
      else if(num!=bars)
        {
         Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Скопированы не все данные (",num," из ",bars,")");
         return( 0 );
        }
      //---
      Print(__FUNCTION__,": Успех! Скопировано ",num," из ",bars," значение индикатора АО ТФ "+EnumToString(inpTimeframe));
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
 
Alexey Kozitsyn:

For starters, you don't need to make such entries:

I first thought you were assigning a variable its own value.

Next:

There is no need to copy during initialization. Initialization is not for this purpose. Moreover, this record will not be meaningful when data request from older TFs, which at the moment of request from OnInit() won't be calculated yet.

But this record is enough to be done just once at initialization stage.

Further ... um... subjectively, that's not how I would do it.

I like to break the program into:

1. First run (history analysis);

2. Subsequent runs:

2.1 Each tick;

2.2 The bar formed;

I.e:

And only after - the main cycle (function) of calculations.

Your copy-functions give out uninformative errors. Just the code is not very good.

There is no check of synchronization of the data of the older TF.

And the most important thing here is to understand the sequence. I advise you to create a test indicator, so it would only request the data of the major TF at the first start and to understand how the copying is made. I.e. to remove this from the beginning of the code:

And to unset the first and the last element of the array. And only then, if necessary, change direction of indexing.

I make variables in such a way that they are clear to me at a glance. If you don't understand them, make them in a way that you do ;)

I always start to write non-global variables with a small letter - the reason is simple: case sensitive intelligence...

This is the test code, as not test code is big enough, and on MT4 it flies when switching the TF, and there are no errors of missing data - everything is always there. In MT5, however, when switching the trader only half a minute loads the history, and then also does not work with the data is not his trader - says about their absence.

I have never had a chance to try it before. It turned out that it is necessary to request the data for all used TFs in the initis. I think that if you do not know in advance the estimated number of phones used, then you need to ask them all. Only one by half a minute counts. There are 21 of them in total...

Am I thinking something wrong again?

 
This is very important for me:

In MT5 it takes half a minute to download the history


wrote about it

я правильно понимаю тогда, что подготовив кэш,терминал при последующих обращениях (начиная со 2 обращения) затрачивает на порядки меньше времени?

можно ли как-то уменьшить время первого обращения после перезагрузки терминала,чтобы было как в МТ4?
Теперь выводы:

    Разница только в скорости начальной инициализации кеша чарта 0.6 мс МТ4 против 113 мс у МТ5

more details here

https://www.mql5.com/ru/forum/1111/page1871#comment_4866969

https://www.mql5.com/ru/forum/1111/page1871#comment_4867939

This is and will be. The more TF or symbols it will request, the slower the start of work will be.

Ошибки, баги, вопросы
Ошибки, баги, вопросы
  • www.mql5.com
Форум алго-трейдеров MQL5
 
kaus_bonus:


wrote about it

more details here

https://www.mql5.com/ru/forum/1111/page1871#comment_4866969

https://www.mql5.com/ru/forum/1111/page1871#comment_4867939

This is and will be. The more TFs or characters will be requested, the more retarded the start will be.

It would be good if only at the first start of the indicator. I have, however, at each switch of the timeframe history is loaded for half a minute. I know it shouldn't be like that, but... I'm doing something wrong... I'm trying to access a non-native timeframe with only one indicator.
 
Artyom Trishkin:
It would be good if only when I start the indicator for the first time. I have half a minute loading history every time I switch timeframe. I know it shouldn't be like that, but... I'm doing something wrong... I'm trying to access a non-native timeframe in only one indicator.

Well, measure the speed of copying data from another timeframe and see where the bottleneck is.
 
Artyom Trishkin:

If you need to use several indicators from different TFs for calculations - you need to get the handle of each TF.

If you want everything to be calculated faster - reduce the size of the history in the terminal.

Have you run my test indicator? Is it collecting data?

 
Alexey Kozitsyn:

If you need to use several indicators from different TFs for calculations - you need to get the handle of each TF.

If you want everything to be calculated faster - reduce the size of the history in the terminal.

Have you run my test indicator? Is it collecting data?

No, I haven't.

It turns out that if you need ALL timeframes, you have to create 21 AO indicator handles? Isn't it wasteful?

 
Artyom Trishkin:

No, I haven't run it yet.

It turns out that if you need ALL timeframes, you need to create 21 AO indicator handles? Isn't it wasteful?

How else can I get the data from the right symbol/TF? CopyBuffer works only with handles.
Reason: