суббота, 9 мая 2015 г.

Расширения классов в MQL4, MQL5. Или как получить Queue, List, Vector в Metatrader.

Для написания индикатора мне потребовался массив типа очередь. Т.е. чтобы не было необходимости задавать размерность массива, можно было добавлять значения без указания индекса в конец и так далее. В C# и C++ есть такая удобная штука как Queue (с разными методами, но с общим смыслом), а вот в MT4 такого нет.
Я подумал, что уже не первый раз сталкиваюсь с необходимостью такой очереди. Решил дописать несколько функций, которые мне нужны и из простого массива сделать очередь. Когда несколько функций было написано, я вынес все в файл *.mqh и думал куда бы поместить его, чтобы использовать в дальнейшем во всех своих работах. И тут я обнаружил, что в папке MQL4 (в MT5 все аналогично) уже есть папка Include, которая УЖЕ вкючает в себя расширения для массивов (и не только).
Разобрав все, что связано с массивами я  не расстроился, так как тех методов, что мне нужны, я не нашел. Я вынес их отдельно в файлик ArrayDouble_ext.mqh. Добавил три новых функции: нахождение суммы всего массива, поиск максимального и минимального значений массива. Зачем нужны две последние спросите вы? Поясню. Есть стандартная фунция ArrayMaximum:
int  ArrayMaximum(
   const void&   array[],             // массив для поиска
   int           count=WHOLE_ARRAY,   // количество проверяемых
   int           start=0              // с какого индекса начинаем поиск
   );
Как видно из описания, она использует в качестве параметров с какого элемента искать, количество проверяемых. В моем случае это всегда 0 и WHOLE_ARRAY. Еще, стандартная функция не удобна тем, что она возвращяет индекс найденного элемента, а не его значение. А зачем мне нужен индекс? Чтобы после его нахождения получать значение элемента по индексу? Вот я и создал свои функции, которые можно использовать без параметров и которые выдают конечное значение. В стандартном расширении ArrayDouble.mqh уже были функции для поиска максимума и минимума и они возврашали значение, а не индекс, но они также требовали два параметра: с какого элемента искать и сколько элементов проверять. Кроме того, в этом расширении содержалась ошибка.
//+------------------------------------------------------------------+
//| Find maximum of array                                            |
//+------------------------------------------------------------------+
int CArrayDouble::Maximum(const int start,const int count) const
  {
   return(ArrayMaximum(m_data,start,count));
  }
Если внимательно посмотреть на значение, которое возвращает функция, то мы увидим, что перепутаны параметры. ArrayMaximum вторым параметром принимает количество элементов для поиска, а третьим - с какого элемента искать. Я потратил очень много времени, не понимая, почему у меня максимум ищется не правильно. А теперь немного примеров, с использованием расширений (файл-скрипт теста). Код:
#include "..\Include\Arrays\ArrayDouble_Ext.mqh"

void OnStart()
{
   CArrayDoubleExt arr;
   
   //Adding
   arr.Add(10);
   arr.Add(11);
   arr.Add(13);
   arr.Add(16);
   arr.Add(9);
   
   //Deleting
   arr.Delete(0); //Delete first element from the left
      
   
   printf("Size = %d, Max = %f, Min = %f, Summ = %f", arr.Total(), arr.MaxValue(), arr.MinValue(), arr.Summ());
}
Результат:
Size = 4, Max = 16.000000, Min = 11.000000, Summ = 49.000000
Расширений написано уже очень много. Прежде чем искать то, чего вам не хватает, а тем более писать, загляните в папку Include. Удачной торговли!

Комментариев нет:

Отправить комментарий