Работа с результатами оптимизации - страница 5

 

Ну,вот и исправили. В билде 2190 фреймы с массивами стали работать правильно. С файлами - не пробовал. Стратегия - прежняя. В OnTester() проверяем признак форварда MQLInfoInteger(MQL_FORWARD) и пишем в поле значения фрейма. От форварда мне полезно только значение прибыли, но для унификации пишу переменнные для бэка и форварда одинаково. В OnTesterDeinit()  ищем фрейм бэк-теста с лучшим критерием оптимизации. Фильтруем фреймы по полю значения frm_val. Читаем его номер прохода и по нему ищем фрейм среди форвардов. Результаты в таблицу. Вот код:

double OnTester()
  {
   double stat_profit=TesterStatistics(STAT_PROFIT);
   double dr_dw=TesterStatistics(STAT_EQUITYDD_PERCENT);
   if(dr_dw==0)dr_dw=0.01;
   double res_1=MathPow(TesterStatistics(STAT_TRADES),0.5)*stat_profit*5/dr_dw;
   double res_2 = stat_profit;
//--
   if(print_report == true)
     {
      static long pass_calk;
      pass_calk++;
      //---Переменные для фрейма
      string fram_name = "back_test";
      double pass_result[2];//Результат оптимизации [0]-польз. [1]-прибыль
      pass_result[0] = res_1;
      pass_result[1] = res_2;
      double frame_val = 0; //Значение фрейма
      if(MQLInfoInteger(MQL_FORWARD) == 1)
        {
         fram_name = "forward";
         frame_val = 1;
        }// MQL_FORWARD
      FrameAdd(fram_name,pass_calk,frame_val,pass_result);
     }//print_report==true
   return res_1;
  }//OnTester()
//=====================================================================//
void OnTesterDeinit()
  {
   if(print_report == true)
     {
      //--Набор переменных для обработки фреймов
      ulong pass_num = 0; // получение номера прохода из фрейма
      string fr_name = ""; // публичное имя/метка из фрейма
      long publ_id = 0; //публичный id из фрейма
      double frm_val = 0; // значение  из фрейма
      double forv_profit = 0; //Результат из форварда
      ulong res_pass = 0; //Фиксируем номер прохода результата
      double rep_data[2];// массив приёма результата
      ArrayInitialize(rep_data,0);
      double test_result = 0; //Лучший результат теста
      double test_prof = 0; //Значение профита
      string inp_param[];//Массив для приёма инп. параметров
      //ArrayResize(inp_param,3);
      uint inp_count = 0; //Получение числа параметров
      //--
      //--Максимальный результат бэк-теста
      ResetLastError();
      FrameFirst();
      bool first_frame = true;
      double prof_count = 0;//Проходы с профитом
      double al_count = 0; //Всего проходов
      bool forv_det=false;//Наличие форв.-фреймов
      //--Обработка фреймов бэктэста
      while(FrameNext(pass_num,fr_name,publ_id,frm_val,rep_data) == true)
        {
         if(frm_val == 0)
           {
            al_count++;
            if(rep_data[1] > 0)
               prof_count++;
            if(rep_data[0] > test_result || first_frame == true)
              {
               first_frame = false;
               //Print(" запись данных бэк-тэст ",calk_back);
               test_result = rep_data[0];
               test_prof = rep_data[1];
               res_pass = pass_num;
               FrameInputs(pass_num,inp_param,inp_count);
              }//rep_data[0]>max_result
           }//frm_val == 0
           else
             {
              if(frm_val==1)forv_det=true;
             }//frm_val != 0
        }//while
      //--Обработка фреймов форварда
      if(forv_det==true && res_pass > 0)
        {
         ResetLastError();
         FrameFirst();
         while(FrameNext(pass_num,fr_name,publ_id,frm_val,rep_data) == true)
           {
            if(frm_val == 1)
              {
               if(pass_num == res_pass)
                 {
                  forv_profit=rep_data[1];
                 }//rep_data[0]>max_result
              }//frm_val == 0
           }//while
        }// res_pass>0
      //--Создаём файл отчёта
      ResetLastError();
      string subfolder = "Opt_reports";
      string rep_name = "\\Rep_EXP.csv";
      double prf_ind = prof_count / al_count; //Индекс профитности пары
      string terminal_data_path = TerminalInfoString(TERMINAL_DATA_PATH);
      //--Создаём новый файл
      int filehandle = FileOpen(subfolder + rep_name,FILE_READ | FILE_WRITE | FILE_CSV);
      if(filehandle != INVALID_HANDLE)
        {
         //string per_nam=(string)PeriodSeconds();
         FileSeek(filehandle,0,SEEK_END);//Курсор в конец файла
         FileWrite(filehandle,Period(),_Symbol,"польз",DoubleToString(test_result,2),"профит",DoubleToString(test_prof,2),"prf_ind",DoubleToString(prf_ind,2),"forv_profit",DoubleToString(forv_profit,2),inp_param[0],inp_param[1],inp_param[2],inp_param[3]);
         FileClose(filehandle);
        }
      else
         Print("Операция FileOpen неудачна, ошибка ",GetLastError());
     }//print_report==true
   ChartClose();//Закрыть чарт оптимизации
  }//OnTesterDeinit()

Обратите внимание на параметр оптимизации res_1. Он хорошо работает при отборе результатов с наименьшей просадкой. Коэффицент 5 - это по сути просадка, которую я желаю видеть в идеале. Если уменьшить - просадка будет влиять сильней , но это - оптимум. Работает намного лучше фактора восстановления.

Индекс профитности - это доля сетов с профитом выше 0. Чем больше - тем вероятней будет профитным и форвард.

Пример применения чуть позже.

Типы оптимизации - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
Типы оптимизации - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
  • www.metatrader5.com
В данном режиме происходит полный перебор всех возможных комбинаций значений входных переменных, выбранных для оптимизации на соответствующей вкладке. Быстрая (генетический алгоритм) В основу данного типа оптимизации заложен генетический алгоритм подбора наилучших значений входных параметров. Данный тип оптимизации значительно быстрее полного...
Причина обращения: