Особенности языка mql5, тонкости и приёмы работы - страница 288

 
Функция получения списка всех чартов и функция закрытия чарта.
// List of all charts, including CHART_IS_OBJECT.
int GetCharts( long &Charts[], long Chart = 0 )
{
  if (Chart)
    for (uint i = ObjectsTotal(Chart, -1, OBJ_CHART); (bool)i--;)
    {  
      const long NewChart = ObjectGetInteger(Chart, ObjectName(Chart, i, -1, OBJ_CHART), OBJPROP_CHART_ID);
      
      if (NewChart)
      {
        Charts[ArrayResize(Charts, ArraySize(Charts) + 1) - 1] = NewChart;
        
        GetCharts(Charts, NewChart);      
      }
    }
  else
  {
    ArrayFree(Charts);
    
    for (long Chart = ChartFirst(); Chart != -1; Chart = ChartNext(Chart))
    {
      long Tmp;
      
      if (!ChartGetInteger(Chart, CHART_IS_OBJECT, -1, Tmp))
        ResetLastError();
      else if (!Tmp) 
      {
        Charts[ArrayResize(Charts, ArraySize(Charts) + 1) - 1] = Chart;
        
        GetCharts(Charts, Chart);
      }
    }
  }
  
  return(ArraySize(Charts));
}

// Closes and CHART_IS_OBJECT charts.
bool ChartCloseFull( long chart_id = 0, long Chart = 0 )
{
  bool Res = false;
  long Tmp;
  
  if (Chart)  
    for (uint i = ObjectsTotal(Chart, -1, OBJ_CHART); !Res && (bool)i--;)
    {
      const string Name = ObjectName(Chart, i, -1, OBJ_CHART);      
      const long NewChart = ObjectGetInteger(Chart, Name, OBJPROP_CHART_ID);
      
      ResetLastError();
      Res = ((NewChart == chart_id) && (ObjectDelete(Chart, Name) ||
                                        (_LastError == ERR_OBJECT_ERROR) ||
                                        (_LastError == ERR_OBJECT_NOT_FOUND))) ||
            ChartCloseFull(chart_id, NewChart);
    }
  else if (!ChartGetInteger(chart_id, CHART_IS_OBJECT, -1, Tmp) || Tmp)
  {
    ResetLastError();
    
    if (!chart_id)
      chart_id = ChartID();
    
    for (long Chart = ChartFirst(); !Res && (Chart != -1); Chart = ChartNext(Chart))
      if (!ChartGetInteger(Chart, CHART_IS_OBJECT, -1, Tmp))
        ResetLastError();
      else if (!Tmp)
        Res = ChartCloseFull(chart_id, Chart);
  }
  else
    Res = ChartClose(chart_id);
  
  return(Res);
}


Пример.

long CreateChart( const long Chart = 0 )
{
  const string Name = (string)MathRand();
  
  return(ObjectCreate(Chart, Name, OBJ_CHART, 0, 0, 0) ?  ObjectGetInteger(Chart, Name, OBJPROP_CHART_ID) : -1);
}

void OnStart()
{  
  long NewCharts[];
  const int Size = ArrayResize(NewCharts, 9);
  
  for (int i = 0; i < Size; i++)
  {
    NewCharts[i] = CreateChart((bool)(i %3) ? NewCharts[i - 1] : 0);
    
    Sleep(100);
  }
  
  Print("\nCreated charts:");
  ArrayPrint(NewCharts);

  long Charts[];
  
  Print("\nList of all charts:");
  GetCharts(Charts);
  ArrayPrint(Charts);

  for (int i = Size; (bool)i--;)
  {
    Print("\nDelete " + (string)NewCharts[i] + " - " + (string)ChartCloseFull(NewCharts[i]));
    
    Sleep(100);
    
    Print("List of all charts:");
    GetCharts(Charts);
    ArrayPrint(Charts);
  }  
}


Результат.

Created charts:
[0] 132503570123939383 132503570123939384 132503570123939385 132503570123939386 132503570123939387
[5] 132503570123939388 132503570123939389 132503570123939390 132503570123939391

List of all charts:
[0] 132503570123939382 132503570123939386 132503570123939387 132503570123939388 132503570123939389
[5] 132503570123939390 132503570123939391 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939391 - true
List of all charts:
[0] 132503570123939382 132503570123939386 132503570123939387 132503570123939388 132503570123939389
[5] 132503570123939390 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939390 - true
List of all charts:
[0] 132503570123939382 132503570123939386 132503570123939387 132503570123939388
[4] 132503570123939389 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939389 - true
List of all charts:
132503570123939382 132503570123939386 132503570123939387 132503570123939388 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939388 - true
List of all charts:
132503570123939382 132503570123939386 132503570123939387 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939387 - true
List of all charts:
132503570123939382 132503570123939386 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939386 - true
List of all charts:
132503570123939382 132503570123939383 132503570123939384 132503570123939385

Delete 132503570123939385 - true
List of all charts:
132503570123939382 132503570123939383 132503570123939384

Delete 132503570123939384 - true
List of all charts:
132503570123939382 132503570123939383

Delete 132503570123939383 - true
List of all charts:
132503570123939382
 

Использую такую универсальную конструкцию задания вкл/выкл Common-папки через название файла.

int FileOpen2( string file_name, int open_flags,
               const short delimiter = '\t', const uint codepage = CP_ACP )
{
  open_flags |= ::StringReplace(file_name, "*", NULL) ? FILE_COMMON : 0;
  
  return(::FileOpen(file_name, open_flags, delimiter, codepage));
}                       

Если название файла содержит в себе звездочу, то откроется в Common-папке, иначе - как задано.

 

Кто знает, как такое заставить работать ?

// тестовый класс
class Foo {
public:
   Foo() { payload=MathRand(); }
   ~Foo() {}
public:
   int payload;   
};

int CompareByPayload(Foo *one,Foo *two)
{
   return two.payload - one.payload; 
}

/* // КСТАТИ, если раскоментить, будет "fatal error" компилятора
template <typename T>
int CompareByPayload(T *one,T *two)
{
   return two.payload - one.payload; 
}
*/

// ШАБЛОННАЯ СОРТИРОВКА
// для массива с указателями на объекты
template <typename T>
typedef int (*CompareFunction)(T *,T *);

template <typename T>
int Sort(T *&_arr[],CompareFunction _cmp)
{
   // тут какая-то сортировка
   return 0;
}

Foo *arr[];
void OnStart()
{
   ArrayResize(arr,100);

   for(int i=0;i<100;i++)
      arr[i]=new Foo();

   Sort(arr,CompareByPayload);

   for(int i=0;i<100;i++) {
      Print("payload=%d",arr[i].payload);
      delete arr[i];
   }
}

чтобы получился шаблон Sort ( массив_указателей, функция_сравнения )

 
Maxim Kuznetsov #:

Кто знает, как такое заставить работать ?

чтобы получился шаблон Sort ( массив_указателей, функция_сравнения )

Шаблонные указатели на функции не работают в MQL5.

 
fxsaber #:

Шаблонные указатели на функции не работают в MQL5.

печально это.. :-(

значит пока не появится и не будет указателя на член-функцию (слово то какое ойё) про человечий ОО в MQL говорить преждевременно

 
Maxim Kuznetsov #:

про человечий ОО в MQL говорить преждевременно

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

Нужно ли в MQL множественное наследование интерфейсов?

Koldun Zloy, 2025.01.23 14:29

возможность, без которой легко можно обойтись.

Ни какие руки она ни кому не развяжет.

И к развитию не имеет ни малейшего отношения.

 
fxsaber #:

Современный язык на котором нельзя сделать шаблонный Sort() ?

PS/ в отличии от множественного наследования это можно по уродски сделать через #define SORT(arr,func). Но это убожество из 80-х годов. Почему нет в шаблонах, для меня загадка
 
fxsaber #:

Шаблонные указатели на функции не работают в MQL5.

Есть хорошее решение для преодоления этого ограничения MQL . Хитрость заключается в том, чтобы передать шаблонную CompareFunc в общую функцию сортировки как указатель на функцию +параметртипа T.

Этот трюк помогает компилятору разрешить параметры typename .

GenericSortTemplated.mq5

// templated class
template <typename T>
class Foo {
public:
   Foo() { payload=(T)10*MathRand()/MathRand(); }
   ~Foo() {}
public:
   T payload;
};

// templated compare function for different types of payloads
template <typename T>
bool CompareByPayload(T one, T two)
{

   return one.payload < two.payload;
}

//--------------------------------------------------------------------------------------------
// TEMPLATE SORTING
// function is templated for any type of array (e.g., int[], double[], pointers to objects[]).
// The CompareFunc type is a pointer to comparison function that can accept different types.
//--------------------------------------------------------------------------------------------
template <typename T, typename CompareFunc>
void GenericSort(T &a[], CompareFunc compare)
{
   for(int i=1; i < ArraySize(a); ++i)
      for(int j=i; j>0 && compare( a[j], a[j-1] ); j--)
      {
         T tmp=a[j]; a[j]=a[j-1]; a[j-1]=tmp;
      }
}

// custom sort function for different types of payloads
template< typename T >
void Sort(T& a[])
{
   typedef bool (*CompareFunc)( T, T );

   GenericSort< T,  CompareFunc >( a, CompareByPayload< T > );
}

Foo<int>   *arr[];
Foo<float> *flt[];

void OnStart()
{
   int n = 7;
   ArrayResize(arr,n);
   ArrayResize(flt,n);

   for(int i=0;i<n;i++) {
      arr[i]=new Foo<int>();
      flt[i]=new Foo<float>();
   }

   Sort(arr);
   Sort(flt);

   for(int i=0;i<n;i++) {
      printf("%d. payload=%s",i,(string)arr[i].payload);
      delete arr[i];
   }

   for(int i=0;i<n;i++) {
      printf("%d. payload=%s",i,(string)flt[i].payload);
      delete flt[i];
   }
}

Функция сортировки является шаблонизированной. Функция сравнения также является шаблонизированной. Выделенные цвета показывают, как специализируются и разрешаются параметры typename .

вывод:

GenericSort (EURUSD,H1) 0. payload=1
GenericSort (EURUSD,H1) 1. payload=5
GenericSort (EURUSD,H1) 2. payload=6
GenericSort (EURUSD,H1) 3. payload=7
GenericSort (EURUSD,H1) 4. payload=10
GenericSort (EURUSD,H1) 5. payload=30
GenericSort (EURUSD,H1) 6. payload=230

GenericSort (EURUSD,H1) 0. payload=1.2722387313842773
GenericSort (EURUSD,H1) 1. payload=2.1265437602996826
GenericSort (EURUSD,H1) 2. payload=2.4967143535614014
GenericSort (EURUSD,H1) 3. payload=4.115740776062012
GenericSort (EURUSD,H1) 4. payload=7.864346981048584
GenericSort (EURUSD,H1) 5. payload=11.456646919250488
GenericSort (EURUSD,H1) 6. payload=18.580562591552734
 
Привет всем.
Я создал WPF приложение, используя .net. Пока я читал документацию об импорте на https://www.mql5.com/en/book/advanced/libraries/libraries_import, там четко сказано:
Functions are imported from compiled MQL5 modules (*.ex5 files) and from Windows dynamic library modules (*.dll files). 

Проводя некоторые тесты, я попробовал собрать свое приложение как .exe вместо .dll и импортировал его в мой mql5 EA и увидел, что компилятор не выдает мне никаких ошибок, а также я могу использовать статические функции внутри программы.

Поскольку я не смог найти в документации ничего об импорте программ в формате .exe, мне стало интересно, подразумевает ли это что-то, о чем я теперь знаю. Влияет ли это на жизненный цикл советника? Управляет ли терминал импортом .exe как-то иначе, чем .dll?

Спасибо за уделенное время.

 

Насильный перевод терминала в portable-режим.

  1. В терминале нажать CTRL+SHIFT+D. Если в открывшемся окне отсутствует terminal64.exe, то терминал запущен не в portable-режиме.
  2. Закрыть терминал. И перенести все файлы из папки п.1. в папку, откуда запускаете terminal64.exe.
  3. Запустить terminal64.exe с ключом /portable.
ЗЫ Смог установить терминал не в portable-режиме только на VPS. На рабочей машине всегда сам устанавливается в portable.