Тестер: Как реализовать свой критерий оптимизации

 

New article Как реализовать свой критерий оптимизации has been published:

Для стандртного эксперта Moving Average реализован пример оптимизации по критерию прибыль/просадка с выводом результатов в файл.

Время от времени высказываются мнения о необходимости расширения набора критериев оптимизации в тестере MT4. Можно предположить однако, что какие бы критерии не добавлялись разработчиками, всегда будут пользователи и ситуации для которых нужного среди них не найдётся. Есть ли выход из положения в рамках MQL4 и платформы MetaTrader? Да, есть. В предлагаемой статье на примере стандартного советника Moving Average реализовано применение пользовательского критерия оптимизации. В качестве такового выбрано отношение прибыль/просадка.

Author: Nikolai Shevchuk

 

Пример более компактной реализации объявления внешних переменных:

#define STR_SHABLON "<!--D-->"
#define MAX_SIZE 100
 
string  Shablon1 = "Begin = <!--D-->, End = <!--D-->, Step = <!--D-->";
extern string Str1 = "Begin = 0.12, End = 3.45, Step = 1.23";
 
string  Shablon2 = "<!--D-->; Var23 = <!--D-->; Offset = <!--D-->; Maximum = <!--D-->";
extern string Str2 = "78; Var23 = 23.5; Offset = 56; Maximum = 1000";
 
string  Shablon3 = "Seq: <!--D-->, <!--D-->";
extern string Str3 = "Seq: 12, 34.56, 8, 9, 0, 5.68";
 
double Example[MAX_SIZE];
 
int start()
{
  int Count, i;
  
  Count = StrToDoubleS(Str1, Shablon1);
  
  Print(Str1);
  
  for (i = 0; i < Count; i++)
    Print(i + ": " + Example[i]);
 
  Count = StrToDoubleS(Str2, Shablon2);
  
  Print(Str2);
  
  for (i = 0; i < Count; i++)
    Print(i + ": " + Example[i]);
  
  Count = StrToDoubleS(Str3, Shablon3);
 
  Print(Str3);
  
  for (i = 0; i < Count; i++)
    Print(i + ": " + Example[i]);
 
  return(0);
}
Сама функция
int StrToDoubleS( string Str, string Shablon )

берет из строчки соотетствующие числовые значения согласно заданному шаблону.

Возвращает количество взятых чисел.

Исходный текст функции:

int StrToDoubleS( string Str, string Shablon )
{
  string StrTemp;
  int Pos, LengthSh;
  double Sum = 0;
  int Count = 0;
  
  LengthSh = StringLen(STR_SHABLON);
  Pos = StringFind(Shablon, STR_SHABLON);
  
  while (Pos != -1)
  {
    if (Pos != 0)
      StrTemp = StringSubstr(Shablon, 0, Pos);
    else
      StrTemp = "";
      
    Shablon = StringSubstr(Shablon, Pos + LengthSh);
  
    Pos = StringFind(Str, StrTemp);
    
    if (Pos == -1)
      return(Count);
      
    Pos += StringLen(StrTemp);
    Str = StringSubstr(Str, Pos);
 
    Example[Count] = StrToDouble(Str);
    Count++;
 
    Pos = StringFind(Shablon, STR_SHABLON);
  }
 
  Pos = StringFind(Str, StrTemp);
  LengthSh = StringLen(StrTemp);
  
  while(Pos != -1)
  {
    Pos += LengthSh;
    Str = StringSubstr(Str, Pos);
 
    Example[Count] = StrToDouble(Str);
    Count++;
    
    Pos = StringFind(Str, StrTemp);
  }
  
  return(Count);
}
 
getch:

Пример более компактной реализации объявления внешних переменных:

Хороший приём.  Действительно количество необходимых внешних переменных нарастает очень быстро.
 

На форуме был вопрос Gull'а по организации перебора более чем двух параметров. Вроде получается так:

Все возможные наборы параметров представим(мысленно) в виде многомерного массива. Таким образом есть текущие значения индексов i, j, k, l, ... и их диапазоны I, J, K, L, ... . Тогда имеем для двух параметров:

i = (Counter-1) % I

j = (Counter-1) / I

для трёх:

i = (Counter-1) % I

j = (Counter-1) / I % J

k = (Counter-1) / I / J

для четырёх:

i = (Counter-1) % I

j = (Counter-1) / I % J

k = (Counter-1) / I / J % K

l = (Counter-1) / I / J / K

Ну и дальше симметрично можно достраивать. Хотя при большом числе параметров возможно лучше сохранять вектор текущих значений индексов в файл и модифицировать его по ходу оптимизации. Но с ростом числа параметров и полный перебор становится всё менее реалистичной целью.

 
Правильно ли я понимаю, что в данном примере для оптимизации нам придется 200 раз вручную запускать советника?
 
Нет, неправильно, нужно один раз запустить оптимизацию по счётчику, как описано в статье.
 
lna01:
Нет, неправильно, нужно один раз запустить оптимизацию по счётчику, как описано в статье.

Похоже, что мне нужно тестер как следует изучить.
 

Вы привели пример критерия, по которому можно отсортировать полученные результаты... Зачем? Ведь все это можно сделать в том же экселе...

Другое дело, если б ваш критерий мог отсеять, как лишние найденные варианты по заданному значению, не в конце оптимизации, а во время каждого прохода....

Возможен ли такой вариант? Тогда бы время оптимизации значительно сократилось..

Причина обращения: