Errors, bugs, questions - page 2652

 
Алексей Тарабанов:

Why are you fighting? Why don't we do something useful together?

Stanislav posted a fantastically useful script in KB. It easily creates archives with MQL-files and resources.

I have an EA with hundreds of mqh-files. Using the script I can now easily transfer my EA to the source code, control the versions and share with others.

MQL5 Program Packer
MQL5 Program Packer
  • www.mql5.com
This script allows you to assemble a zip-file of your MQL5-program with all dependencies automatically. The dependencies are: included source files via #include directive (both modes of absolute () and relative ("") references are supported); icons linked by #property icon directive; resources (images, sounds, and other types) embedded by...
 
 
Vladislav Andruschenko:
Thank you. I'll try to break it down and check the options with chart events.

Have a look at the thread, recently dealt with the issue in detail -https://www.mql5.com/ru/forum/327888

EventChartCustom => indicator is too slow
EventChartCustom => indicator is too slow
  • 2019.12.06
  • www.mql5.com
Использую в советнике для получения тиков с других инструментов "индикатор-шпион": Периодически в журнале появляются записи "indicator is too slow...
 
Anton Shpilyuk:

2) Циклом-перебором до тех пор пока дата не будет совпадать(минус - скорость работы)

 это так?

On the subject of "get bar index by time copyrates"

Horror, it really is! The task was to get the bars of M1 timeframe in the indicator, although the indicator itself works on M5 timeframe.

1. we had to initialize the desired timeframe in OnCalculate() to load it before the start of the indicator (after the initialization the FirstStartFlag = false;). Remember, in indicators, if it is not loaded, it will give -1 or not fully loaded, so we check how much is loaded, if not enough, we go to the beginning ofreturn(0);

declare array MqlRates rates[]; at the beginning, wherecnt_bars*5; - recalculate the number of bars M5 in M1

//--- загрузка данных М1 таймфрейма для поминутной экспирации в оптимизаторе   
   if(FirstStartFlag) 
      {
         int count = cnt_bars*5;
         int copied=CopyRates(_Symbol,PERIOD_M1,0,count,rates);
         if(copied>0) 
            {
               if(debug) Print("Скопировано баров: "+IntegerToString(copied)+", надо было "+IntegerToString(count)); 
               if(copied<count)
                  {
                      Print("Не удалось получить достаточно исторических данных, ждем");
                      return(0);
                  }
                
            }
         else  
            {
               Print("Не удалось получить исторические данные, ждем");
               return(0);
            } 
         ArraySetAsSeries(rates,true);  
      }

After that, we update the historical data on M1 in the body of the required function every time we perform calculations:

//--- загрузка актуальных данных М1 таймфрейма для поминутной экспирации в оптимизаторе    
   int count = cnt_bars*5;
   copied=CopyRates(_Symbol,PERIOD_M1,0,count,rates);
   if(copied>0) 
      {
         Print("cnt_Statist() Скопировано баров: "+IntegerToString(copied)+", надо было "+IntegerToString(count)); 
         if(copied<count)
            {
                Print("cnt_Statist() Не удалось получить достаточно исторических данных");
            }
          
      }
   else  
      {
         Print("cnt_Statist() Не удалось получить исторические данные"); 
      } 
   ArraySetAsSeries(rates,true);  

Further, in the loop of M5 bars, we do an embedded loop of searching for the index of the corresponding M1 bar,time[s] being the current M5 bar of the timeframe under calculation:

                          for(h=copied-1;h>0;h--)
                              {
                                 if(rates[h].time == time[s])
                                    {
                                       IndexRates = h;
                                       break;
                                    }
                              }

And then we use this index to find the necessary M1 bar data, in my case it is rates[IndexRates-5].time and rates[IndexRates-k-4].close

Thank goodness this nested loop goes through the bars quickly, even on a 90-day history. But I would like to be able to search for bar indexes in the rates[].time array like a binary search using the ArrayBsearch function

Документация по MQL5: Константы, перечисления и структуры / Торговые константы / Информация об исторических данных по инструменту
Документация по MQL5: Константы, перечисления и структуры / Торговые константы / Информация об исторических данных по инструменту
  • www.mql5.com
Константы, перечисления и структуры / Торговые константы / Информация об исторических данных по инструменту - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
What are the differences for the compiler of the following lines?
Print("123" "456");
Print("123" + "456");
Print("123", "456");
 
MQLs are demoralising little by little:
#ifdef __cplusplus
    #include<iostream>
    #include<stdio.h>
#endif

class input_iterator_tag  {};
class output_iterator_tag {};
class forward_iterator_tag       : public input_iterator_tag         {};
class bidirectional_iterator_tag : public forward_iterator_tag       {};
class random_access_iterator_tag : public bidirectional_iterator_tag {};

struct MyIterator{
public:
   int index;
   class iterator_category : public random_access_iterator_tag{};
   
   MyIterator(int __index = 0):index(__index){}
   
   bool operator!=(MyIterator &it){
      return index != it.index;
   }
   
   int operator-(MyIterator &it){
      return index - it.index;
   };
   
   MyIterator operator++(){
      index+=1;
#ifdef __cplusplus
      return *this;
#else
      return this;
#endif 
   } 
};

template <typename _InputIter>
int __distance(_InputIter &__first, _InputIter &__last, input_iterator_tag*){
    int __r=0;
    for (; __first != __last; ++__first)
        ++__r;
    return __r;
}

template <typename _RandIter>
int __distance(_RandIter &__first, _RandIter &__last, forward_iterator_tag*){
    return __last - __first;
}


//+------------------------------------------------------------------+
//| MQL realization                                                  |
//+------------------------------------------------------------------+
#ifdef __MQL5__
// Bypass the bug (https://www.mql5.com/ru/forum/1111/page2648#comment_15015191)
template <typename _InputIter>
int __distance(_InputIter &__first, _InputIter &__last, forward_iterator_tag* __category){
   return __distance(__first, __last, (input_iterator_tag*) __category);
};

template <typename _InputIter>
int __distance(_InputIter &__first, _InputIter &__last, random_access_iterator_tag* __category){
   return __distance(__first, __last, (bidirectional_iterator_tag*) __category);
};


// Bypass Compilation ERROR: '_InputIter' - struct undefined    
template<typename T>
class GetStructType{
public:
   struct type : public T{};
};


template <typename _InputIter>
int distance_mql(_InputIter &__first, _InputIter &__last){
   //_InputIter::iterator_category category;                      //Compilation ERROR: '_InputIter' - struct undefined  
   GetStructType<_InputIter>::type::iterator_category category;
   GetStructType<_InputIter>::type::iterator_category* ptr = &category;
   
   // Bypass the bug (https://www.mql5.com/ru/forum/1111/page2648#comment_15015191)
   random_access_iterator_tag* ptr_ra = dynamic_cast<random_access_iterator_tag*>(ptr);
   if(ptr_ra != NULL){
      return __distance(__first, __last, ptr_ra);
   };
   
   bidirectional_iterator_tag* ptr_bd = dynamic_cast<bidirectional_iterator_tag*>(ptr);
   if(ptr_bd != NULL){
      return __distance(__first, __last, ptr_bd);
   };
   
   forward_iterator_tag* ptr_fw = dynamic_cast<forward_iterator_tag*>(ptr);
   if(ptr_fw != NULL){
      return __distance(__first, __last, ptr_fw);
   };
   
   input_iterator_tag* ptr_in = dynamic_cast<input_iterator_tag*>(ptr);
   if(ptr_in != NULL){
      return __distance(__first, __last, ptr_in);
   };
   
   //TODO RAISE EXCEPTION
   return -1;
}

void OnStart(){
   MyIterator it1(1);
   MyIterator it2(5);
   printf("result:%d", distance_mql(it1, it2));            
}
#endif 


//+------------------------------------------------------------------+
//|  C++ realization, online: https://onlinegdb.com/S1tcVt9XU 	     |
//+------------------------------------------------------------------+
#ifdef __cplusplus
template <typename _InputIter>
int distance_cplusplus(_InputIter &__first, _InputIter &__last){
    return __distance(__first, __last, (typename _InputIter::iterator_category*)(NULL));
}

int main(){
   MyIterator it1(1);
   MyIterator it2(5);
   printf("result:%d", distance_cplusplus(it1, it2)); 
   
   return 0;
}
#endif 

Brief gist of the bug:
When there is class inheritance A <= B <= C <= D
and two overloading functions are implemented, for example, one with parameter A* and one with parameter B*,
. When passing a C* or D* object into such a function, the MQL causes a "ambiguous call to overloaded function" compilation error.

Question: Is there a more sensible workaround to this idiotic bug than the one presented above?
 
Here we go with more "Why MQL != C++" sheets...
 
Сергей Таболин:
Here we go with more "Why MQL != C++"...

Why comment on something if you haven't got to the bottom of it?

 
Sergey Dzyublik:

Why comment on something if you haven't got to the bottom of it?

Because I have long ago opened a topic for such clarifications (because no one like you could do it yourself).

And then that the difference in languages has nothing to do with errors or bugs!

MQL v C++. Что хотелось бы, чего нет, что не так, куда копать.
MQL v C++. Что хотелось бы, чего нет, что не так, куда копать.
  • 2019.08.02
  • www.mql5.com
Общую тему багов и вопросов просто уже снасильничали такими разборками. Предложил открыть специализированную ветку, никто не чешется...
 
Sergey Dzyublik:
The MQL is demoralising little by little:

Brief gist of the bug:
When there is class inheritance A <= B <= C <= D
and two functions are implemented, for example, one for A* and one for B*,
. When passing a C* or D* object to such a function, the MQL causes a "ambiguous call to overloaded function" compilation error.

Question: Is there a more sensible workaround to this idiotic bug than the one presented above?

Well, STL is not transposed one-to-one. You have to look closely at the specifics here. The easiest way is to write all the possible functionality in the abstract methods in a base class or interface, and in the descendants - either implementation or =delte. In this case, you need to pass pointers or references of the same type to the methods of the base class. Although there is an unavoidable evil in the form of a virtual table, but it's better to arrange the architecture in such a way that there won't be expensive dynamic_cast branching anywhere.