MQL4 - automated forex trading   /  

Статьи

Cтатьи  Тестер  Автоматическая оптимизация торгового робота в процессе реальной торговли Авторизуйтесь или зарегистрируйтесь , чтобы добавить новую статью


Эта статья о возможностях
MetaTrader 4

Мобильный трейдинг!
Купите лицензию и торгуйте мобильно

Автоматическая оптимизация торгового робота в процессе реальной торговли [ en ]



Введение

Есть предположение, что эксперт с подогнанными под историю параметрами будет первое время, пусть и достаточно недолгое, прибыльно торговать. Косвенные свидетельства в пользу этого предположения появились после наблюдений за чемпионатом по автотрейдингу в разделе Automated Trading Championship 2006 текущего сайта. В начале работы чемпионата прибыльных советников было значительно больше, а по прошествии небольшого промежутка времени многие из них отсеялись. Отсюда и появилось предположение о том, что большинство из отсеявшихся советников были просто подогнаны под историю.


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


Для реализации этой идеи решено было взять готовый советник MACD Sample из клиентского терминала MetaTrader 4 и вставить в него свою функцию автоматической оптимизации. Через некоторое время код автооптимизатора был готов и выложен на форуме в разделе автооптимизатор. По прошествии еще некоторого времени в ветке автооптимизатор появились и первые подтверждения идеи. В дальнейшем, после внесения некоторых изменений для более удобного использования, автооптимизатор был переделан в mqh-библиотеку.



Установка автооптимизатора

Для выполнения задачи нужно:

  • скопировать MACD Sample_1.mq4 в папку expert установленного и подключенного к интернету терминала MetaTrader.
  • сделать копию папки с установленным в ней терминалом MetaTrader в новое место.

Для удобства оригинал будем называть - Терминалом, а копию - Терминал-тестером. Проверочный тест будем проводить на инструменте EURUSD с периодом H1 с помощью входящего в комплект поставки MT4, но слегка измененного советника MACD Sample_1.mq4.

Подготовка Терминал-тестера.

Не забудьте в Терминал-Тестере откомпилировать советник MACD Sample_1.mq4. Для начала запустим клиентский терминал, затем - тестер стратегий и выполним настройку, как показано на скриншоте.


Оптимизацию будем проводить за трое суток. Этого для проверки автооптимизатора вполне достаточно. Дату начала оптимизации выберем по формуле - текущая дата минус три дня назад. За период оптимизации должна быть закачана необходимая история по выбранному инструменту, в данном случае по EURUSD.


Для тех, кто выполняет оптимизацию эксперта впервые, порядок подготовки и проведения оптимизации можно прочитать в меню справки клиентского терминала MetaTrader 4 <Справка - Вызов справки F1 - Автотрейдинг - Оптимизация советников - Настройка>, а также можно почитать статью Тестирование экспертов в клиентском терминале MetaTrader 4. Взгляд изнутри.


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



Автооптимизация ограничена четырьмя переменными, но нам для проверки в целях сокращения времени оптимизации достаточно и трех. После того как переменные выбраны, сохраним установленные настройки оптимизации в set-файл с именем MACD Sample_1.set. Этот файл должен быть сохранен в папку tester Терминал-Тестера. Далее запустим предварительную оптимизацию и запомним время старта. Это нужно, чтобы можно было вычислить время,
необходимое для автооптимизации с установленными параметрами. После окончания оптимизации вычислим необходимое время ожидания. Затем этот терминал нужно закрыть, так как иначе мы не сможем запустить его программно.

Подготовка эксперта, находящегося в Терминале.
Для этого откроем в редакторе MetaEditor проверочный эксперт MACD Sample_1.mq4 и выполним соответствующие настройки.
- установим время запуска автооптимизации, например в 00:01 каждые сутки.
        datetime SetHour    = 0;  // Час старта оптимизации; 
        datetime SetMinute  = 1;  // Минута старта оптимизации.

- установим количество дней для оптимизации (должно совпадать с количеством дней предварительной оптимизации):

        int TestDay = 3;

- установим время ожидания окончания оптимизации в минутах, которое мы вычислили ранее, например 4 минуты.

        int TimeOut = 4;

- впишем имя советника:

        string NameMTS = "MACD Sample_1";  // Имя советника

- впишем имя set-файла с настройками:

        // Имя Set файла с установками
        string NameFileSet = "MACD Sample_1.set"; 

- впишем путь к папке с установленным "терминал-тестером", например:

        // Путь к тестеру        
        string PuthTester = "D:\Program Files\Forex Best Trade Station";

- установим очередность фильтрации:

        // Сортировка по Максимальной прибыли
        int Gross_Profit = 1;                      
        // Сортировка по Максимальной прибыльности        
        int Profit_Factor = 2;     
        // Сортировка по Максимальному матожиданию
        int Expected_Payoff = 3;

- запишем имена переменных для оптимизации:

        string Per1 = "FastEMA";
        string Per2 = "SlowEMA";
        string Per3 = "SignalSMA";
        string Per4 = "";

- далее скопируем приложенный файл auto_optimization.mqh в папку "include";
- подключим файл библиотеки в эксперте:

//--- Подключение библиотеки автооптимизатора
#include <auto_optimization.mqh>

- осталось скопировать указанный ниже код в начало функции start() вашего эксперта. В MACD Sample_1.mq4 он уже есть.


// При тестировании и оптимизации не запускать   
  if(!IsTesting() && !IsOptimization())
    {                
      // Сравнение текущего часа с установленным для запуска
      if(TimeHour(TimeLocal()) == SetHour)
        {
          // Защита от повторного запуска
          if(!StartTest)
            {
              // Сравнение диапазона минут с установленной для запуска
              // минутой
              if(TimeMinute(TimeLocal()) > SetMinute - 1)
                {     
                  // диапазон нужен в случае если по каким-то причинам 
                  // долго нет нового тика
                  if(TimeMinute(TimeLocal()) < SetMinute + 1)
                    {  
                      // Флаг запуска тестера
                      StartTest    = true;
                      TimeStart    = TimeLocal();
                      Tester(TestDay, NameMTS, NameFileSet, PuthTester, 
                             TimeOut, Gross_Profit, Profit_Factor, 
                             Expected_Payoff, Per1, Per2, Per3, Per4);
                    
                    }
                }
            }
        }
    }
    
                        
   FastEMA      = GlobalVariableGet(Per1);
   SlowEMA      = GlobalVariableGet(Per2);
   SignalSMA    = GlobalVariableGet(Per3);
   TrailingStop = GlobalVariableGet(Per4);  
// Если флаг запуска тестера установлен  
  if(StartTest)
    {                                        
      // Если с момента запуска прошло больше установленного времени 
      // ожидания тестирования
      if(TimeLocal() - TimeStart > TimeOut*60)
        {            
          // Обнулим флаг
          StartTest = false;                              
        }
    }

Вот и все. После перекомпиляции автооптимизатор можно запускать, причем запускать нужно на том же инструменте и на том же периоде, на котором проводилась предварительная оптимизация, в данном случае на EURUSD периода H1. Для проверки автооптимизатора можно вставить указанный ниже код в функцию int init (), тогда автооптимизатор запустится сразу в момент старта советника.


Tester(TestDay,NameMTS,NameFileSet,PuthTester,TimeOut, Gross_Profit,Profit_Factor, 
       Expected_Payoff, Per1,Per2,Per3,Per4);

Принцип работы автооптимизатора

Принцип работы автооптимизатора заключается в использовании Терминал-тестера для оптимизации параметров советника, установленного на график в Терминале. Для этого программа пересылает в Терминал-Тестер файл с параметрами оптимизации (optimise.ini) и запускает Терминал-Тестер в режиме оптимизации. Потом копирует полученные результаты "FileReport........htm" обратно в Терминал и отфильтровывает из полученных результатов лучшие значения.



Подробнее о работе автооптимизатора.
В установленное время, например, в 00.01, запускается автооптимизатор. Переменные заполняются значениями.
 // Путь к терминалу 
string PuthTerminal = TerminalPath() + "\experts\files";
// Имя ini файла для тестера
string FileOptim    = "optimise.ini";
string FileOptim1   = "\optimise.ini";                                  
// Расчет даты старта
datetime DayStart   = TimeLocal()-86400*TestDay;
// Дата начала оптимизации
string DateStart    = TimeToStr(DayStart,TIME_DATE);
// Дата окончания оптимизации
string DateStop     = TimeToStr(TimeLocal(),TIME_DATE);
// Имя файла отчета тестера
string FileReport   = "FileReport_" + Symbol() + "_" + DateStop + ".htm";
string FileReport1  = "\FileReport_" + Symbol() + "_" + DateStop + ".htm";
// Ограничение на минимальное количество сделок в день
double MinTr        = TestDay - 2;
// Ограничение на максимальное количество сделок в день
double MaxTr        = (60 / Period()*TestDay) + 2;
// Количество попыток скопировать файл отчета
int    KvoPptk      = 10;
// Количество строк для сортировки
int    StepRes      = 12;

Далее в строковый массив записываются параметры ini-файла.

// Подготовим ini-файл для оптимизации
ArrayOpttim[0] = ";optimise strategy tester";             
// Вкл/Выкл эксперты
ArrayOpttim[1] = "ExpertsEnable = false";
// Наименование файла эксперта
ArrayOpttim[2] = "TestExpert=" + NameMTS;
// Наименование файла с параметрами
ArrayOpttim[3] = "TestExpertParameters=" + NameFileSet;
// Инструмент
ArrayOpttim[4] = "TestSymbol=" + Symbol();
// Период
ArrayOpttim[5] = "TestPeriod=" + Period();
// Режим моделирования
ArrayOpttim[6] = "TestModel=" + 0;
// Пересчитать
ArrayOpttim[7] = "TestRecalculate=false";
// Оптимизация
ArrayOpttim[8] = "TestOptimization=true";
// Использовать дату
ArrayOpttim[9] = "TestDateEnable=true";
// Дата начала тестирования
ArrayOpttim[10] = "TestFromDate=" + DateStart;
// Дата окончания тестирования
ArrayOpttim[11] = "TestToDate=" + DateStop;
// Имя файла отчета
ArrayOpttim[12] = "TestReport=" + FileReport;
// Перезапись файла отчета
ArrayOpttim[13] = "TestReplaceReport=true";
// Закрыть терминал по завершению
ArrayOpttim[14] = "TestShutdownTerminal=true";

Из массива параметры оптимизации переписываются в ini-файл. О формировании ini-файла также можно прочитать в справке клиентского терминала MetaTrader 4 в разделе <Справка - Вызов справки F1 - Сервис - Конфигурация при старте>.

// Запишем данные в ini-файл                
// Выясним размер массива
OptimArraySize = ArraySize(ArrayOpttim);
// Откроем фал для записи
opttim = FileOpen(FileOptim, FILE_CSV|FILE_WRITE, 0x7F);
if(opttim > 0)
  {
    for(int i = 0; i < OptimArraySize; i++)
      {
        // из массива в переменную
        ini = ArrayOpttim[i];                                     
        // из переменной в файл
        FileWrite(opttim, ini);
      } 
    // закроем файл
    FileClose(opttim);
  }
else
  {
    Print("Не удалось записать данные в ini-файл. Ошибка № ", 
          GetLastError());
    return(0);
  }

После записи параметров в ini-файл подключается входящая в состав Windows библиотека shell32.dll и запускается функция ShellExecuteA.

#import  "shell32.dll"               //Подключим dll (входит в состав windows)       
  int ShellExecuteA(int hwnd,string Operation,string 
                    File,string Parameters,string Directory,int ShowCmd); 
#import

Файл с параметрами пересылается в папку Терминал-тестера.

// скопируем ini-файл в песочницу тестера 
copyini = ShellExecuteA(0,"Open","xcopy", "\"" + PuthTerminal + 
                        FileOptim1 + "\" \"" + PuthTester + "\" /y", 
                        "", 3);
// подождем, пока скопируется файл
Sleep(1200);                                                    
if(copyini < 0)
  {
    Print("Не удалось скопировать ini-файл");
    return(0);
  }

Далее запускается тестер и начинает оптимизацию заданных переменных. Пока идет оптимизация, эксперт находится в состоянии ожидания.

// Запустим Тестер 
start = ShellExecuteA(0, "Open", "terminal.exe", FileOptim,
                      PuthTester, 3);
if(start < 0)
  {
    Print("Не удалось запустить тестер");
    return(0);
  }
Comment("Ожидаем окончания оптимизации");
// подождем окончания оптимизации
Sleep(60000*TimeOut);

После завершения оптимизации тестер автоматически записывает результаты в файл отчета. Этот файл копируется в папку с терминалом.

 for(Pptk = 0; Pptk < KvoPptk; Pptk++)
  {                    
    //Запустим цикл попыток копирования файла отчета
    Comment("Попытка № " + Pptk + " скопировать файл отчета");
    ShellExecuteA(0, "Open", "xcopy", "\"" + PuthTester + FileReport1 + 
                  "\" \"" + PuthTerminal + "\" /y", "", 3);
    // подождем, пока скопируется файл
    Sleep(1200);
    // Попытаемся открыть файл отчета
    file = FileOpen(FileReport, FILE_READ, 0x7F);
    if(file < 0)
      {
        // если не удалось, ещё подождем и попробуем снова
        Sleep(60000);
      }                    
    else 
        break;             
  }
if(file < 0)
  {
    Print("Не удалось скопировать файл отчета");
    return(0);
  }

Затем данные из файла отчета заносятся в строковый массив для дальнейшей обработки.

// Чтение из файла в массив
// Пока не наступил конец файла - цикл
while(FileIsEnding(file) == false)
  {                 
    // Прочитаем строку из файла отчета
    FileLine = FileReadString(file);
    // Найдем нужную строку и установим точку отсчета
    index = StringFind(FileLine, "title", 20);
    if(index > 0)
      {
        // Увеличиваем размер массива
        ArrayResize(ArrayStrg, NumStr + 1);
        // Записываем в массив строки из файла
        ArrayStrg[NumStr] = FileLine;
        NumStr++;
      }
  }
// Закроем файл
FileClose(file);
// Удалим файл, чтоб не плодить копии
FileDelete(FileReport);
// Установим размер массива по количеству считанных из файла
ArrayResize(ArrayData, NumStr); строк
    
.

Далее происходит выборка нужных значений из массива

  for(text = 0; text < NumStr; text++)
     {
      select = ArrayStrg[text]; 
    //-------------------------------------------------------------------------
    //   Обработка текста отчета  (Отделяем мух от котлет)                    | 
    //-------------------------------------------------------------------------
    // Позиция Проход 
    ClStep=StringFind(select, "; \">",20)+4;
    // Найдем конец позиции
    ClStepRazm = StringFind(select, "td>", ClStep);
    // Считаем значение
    CycleStep = StringSubstr(select, ClStep, ClStepRazm - ClStep);
    // Позиция Прибыль 
    // Найдем начало позиции
    GrProf = StringFind(select, "", ClStepRazm);
    // Найдем конец позиции
    GrProfRazm = StringFind(select, "td>", GrProf);
    // Считаем значение
    GrossProfit = StringSubstr(select, GrProf+4, GrProfRazm - (GrProf + 4));
    // Позиция Всего Сделок
    // Найдем начало позиции
    TotTrad = StringFind(select, "", GrProfRazm);
    // Найдем конец позиции
    TotTradRazm = StringFind(select, "td>", TotTrad);
    // Считаем значение
    TotalTrades = StringSubstr(select, TotTrad+4, TotTradRazm - 
                               (TotTrad + 4));
    // Позиция Прибыльность
    // Найдем начало позиции
    ProfFact = StringFind(select, "", TotTradRazm);
    // Найдем конец позиции
    ProfFactRazm = StringFind(select, "td>", ProfFact);
    // Считаем значение
    ProfitFactor = StringSubstr(select, ProfFact + 4, ProfFactRazm - 
                                (ProfFact + 4));
    // Позиция Мат Ожидание 
    // Найдем начало позиции
    ExpPay = StringFind(select, "", ProfFactRazm);
    // Найдем конец позиции
    ExpPayRazm=StringFind(select, "td>", ExpPay);
    // Считаем значение
    ExpectedPayoff = StringSubstr(select, ExpPay+4, ExpPayRazm - 
                                  (ExpPay + 4));
    // Позиции переменных-начиная со второй
    // Найдем начало позиции
    P1 = StringFind(select, Per1, 20);
    // Найдем конец позиции
    P1k = StringFind(select, ";", P1);
    // Считаем Переменную
    Perem1 = StringSubstr(select, P1 + StringLen(Per1) + 1, P1k - 
                          (P1 + 1 + StringLen(Per1)));
    // Найдем начало позиции
    P2 = StringFind(select, Per2, 20);
    // Найдем конец позиции
    P2k = StringFind(select, ";", P2); 
    // Считаем Переменную
    Perem2 = StringSubstr(select, P2 + StringLen(Per2) + 1, P2k - 
                          (P2 + 1 + StringLen(Per2)));
    // Найдем начало позиции
    P3 = StringFind(select, Per3, 20);
    // Найдем конец позиции
    P3k = StringFind(select, ";", P3);
    // Считаем Переменную
    Perem3 = StringSubstr(select, P3 + StringLen(Per3) + 1, P3k - 
                          (P3 + 1 + StringLen(Per3)));
    // Найдем начало позиции
    P4 = StringFind(select, Per4, 20);
    // Найдем конец позиции
    P4k = StringFind(select, ";", P4);
    // Считаем Переменную 
    Perem4 = StringSubstr(select, P4 + StringLen(Per4) + 1, P4k - 
                          (P4 + 1 + StringLen(Per4)));
    Comment("Идет анализ полученных результатов");


После этого полученные значения перед переводом их в числовой формат фильтруются по минимальному и максимальному количеству сделок. Ноль в значениях прибыльности (Profit_Factor) заменяется на 1000 для правильной сортировки и последующего отсеивания.

// Переведем в числовой формат
TotalTradesTransit = StrToDouble(TotalTrades);
GrossProfitTransit = StrToDouble(GrossProfit);
ExpectedPayoffTran = StrToDouble(ExpectedPayoff);
nodubl = true;
if(MinTr < TotalTradesTransit && MaxTr > TotalTradesTransit)
  {                    
    // Отфильтруем по количеству сделок
    PrFactDouble = StrToDouble(ProfitFactor);
    // Убираем 0 в прибыльности для правильного анализа
    if(PrFactDouble == 0)
      {
        PrFactDouble = 1000;
      }

Далее значения фильтруются на наличие дубликатов.

// Отфильтруем данные с одинаковыми значениями
for(Dubl = 0; Dubl <= ResizeArayNew; Dubl++)
  {                    
    // Запустим цикл поиска одинаковых значений
    if(GrossProfitTransit == ArrayData[Dubl][1])
      {          
        // проверим совпадения результатов по максимальной прибыли
        if(TotalTradesTransit == ArrayData[Dubl][2])
          {       
            // проверим совпадения результатов по количеству сделок
            if(PrFactDouble == ArrayData[Dubl][3])
              {          
                // проверим совпадения результатов по прибыльности
                if(ExpectedPayoffTran == ArrayData[Dubl][4])
                  { 
                    // проверим совпадения результатов по матожиданию
                    nodubl=false;                              
                    // Если все совпало, то поставим флаг совпадения
                  }
              }
          }
      }
  }

Далее подготовленные для сортировки значения записываются в массив.


// Запишем отфильтрованные данные в массив
if(nodubl)
  {
    ArrayData[text][1] = GrossProfitTransit;                                
    ArrayData[text][2] = TotalTradesTransit;
    ArrayData[text][3] = PrFactDouble;
    ArrayData[text][4] = ExpectedPayoffTran;
    ArrayData[text][5] = StrToDouble(Perem1);
    ArrayData[text][6] = StrToDouble(Perem2);
    ArrayData[text][7] = StrToDouble(Perem3);
    ArrayData[text][8] = StrToDouble(Perem4);
    ResizeArayNew++; 
  }

Далее начинается анализ данных в порядке очередности, установленной ранее. Анализ происходит так:

  • запускается цикл, и при первом проходе выполняется сортировка значений по первому параметру, например, по максимальной прибыли; выбирается несколько лучших значений (по умолчанию 12), остальные отсекаются;
  • при втором проходе происходит сортировка по второму параметру, например, по прибыльности; также выбираются несколько лучших значений, половина после первой сортировки, остальные отсекаются;
  • при третьем проходе происходит последняя сортировка по третьему параметру, например, по матожиданию; так же выбирается половина значений, но уже после второй сортировки, остальные отсекаются.
// Анализатор
// Принцип анализа - последовательная проверка максимальных 
// значений согласно заданному приоритету фильтрации   
ArrayResize(ArrayTrans, ResizeArayNew - 1);
for(int PrioStep = 1; PrioStep < 4; PrioStep++)
  {
    for(PrCycle = 0; PrCycle < ResizeArayNew; PrCycle++)
      {
        Sort     = ArrayData[PrCycle][0];
        Prior1   = ArrayData[PrCycle][1];             
        transit  = ArrayData[PrCycle][2];
        Prior2   = ArrayData[PrCycle][3];             
        Prior3   = ArrayData[PrCycle][4];             
        transit1 = ArrayData[PrCycle][5];
        transit2 = ArrayData[PrCycle][6];
        transit3 = ArrayData[PrCycle][7];
        transit4 = ArrayData[PrCycle][8]; 
           
        if(PrioStep == 1)
          {
            //Подготовимся к 1 сортировке
            if(Gross_Profit ==1)
              {
                SortTrans = Prior1;
              }
            if(Profit_Factor == 1)
              {
                SortTrans = Prior2;
              }
            if(Expected_Payoff == 1)
              {
                SortTrans = Prior3;
              }
          }
        if(PrioStep == 2)
          {
            // Восстановимся
            if(Gross_Profit ==1)
              {
                Prior1 = Sort;
              }
            if(Profit_Factor == 1)
              {
                Prior2 = Sort;
              }
            if(Expected_Payoff == 1)
              {
                Prior3 = Sort;
              } 
            //Подготовимся ко 2 сортировке
            if(Gross_Profit == 2)
              {
                SortTrans = Prior1;
              }
            if(Profit_Factor == 2)
              {
                SortTrans = Prior2;
              }
            if(Expected_Payoff == 2)
              {
                SortTrans = Prior3;
              }
          }
        if(PrioStep == 3)
          {
            // Восстановимся
            if(Gross_Profit == 2)
              {
                Prior1 = Sort;
              }
            if(Profit_Factor == 2)
              {
                Prior2 = Sort;
              }
            if(Expected_Payoff == 2)
              {
                Prior3 = Sort;
              } 
            //Подготовимся к 3 сортировке
            if(Gross_Profit ==3)
              {
                SortTrans = Prior1;
              }
            if(Profit_Factor == 3)
              {
                SortTrans = Prior2;
              }
            if(Expected_Payoff == 3)
              {
                SortTrans = Prior3;
              }
          }          
        ArrayTrans[PrCycle][0] = SortTrans;
        ArrayTrans[PrCycle][1] = Prior1;
        ArrayTrans[PrCycle][2] = transit;
        ArrayTrans[PrCycle][3] = Prior2;
        ArrayTrans[PrCycle][4] = Prior3;
        ArrayTrans[PrCycle][5] = transit1;
        ArrayTrans[PrCycle][6] = transit2;
        ArrayTrans[PrCycle][7] = transit3;
        ArrayTrans[PrCycle][8] = transit4;
      }
    ArraySort(ArrayTrans,StepRes, 0, MODE_DESCEND); // Отсортируем массив
    ArrayResize(ArrayTrans, StepRes);               // Обрежем лишнее
    for(int CopyAr = 0; CopyAr < StepRes; CopyAr++)
      {
        ArrayData[CopyAr][0] = ArrayTrans[CopyAr][0];
        ArrayData[CopyAr][1] = ArrayTrans[CopyAr][1];
        ArrayData[CopyAr][2] = ArrayTrans[CopyAr][2];
        ArrayData[CopyAr][3] = ArrayTrans[CopyAr][3];
        ArrayData[CopyAr][4] = ArrayTrans[CopyAr][4];             
        // Per1    Переменная 1
        ArrayData[CopyAr][5] = ArrayTrans[CopyAr][5];              
        // Per2    Переменная 2
        ArrayData[CopyAr][6] = ArrayTrans[CopyAr][6];
        // Per3    Переменная 3
        ArrayData[CopyAr][7] = ArrayTrans[CopyAr][7];
        // Per4    Переменная 4
        ArrayData[CopyAr][8] = ArrayTrans[CopyAr][8];
      }
   StepRes = StepRes / 2;
  }

Отфильтрованные таким образом значения записываются в глобальные переменные. Из глобальных переменных значения подставляются в советник.

     // Запишем полученные данные в переменные
   double Peremen1 = ArrayTrans[0][5];                         
   double Peremen2 = ArrayTrans[0][6];
   double Peremen3 = ArrayTrans[0][7];
   double Peremen4 = ArrayTrans[0][8];
   // Если имя переменной указано, то запишем результат в 
   // глобальные переменные
   if(Per1 != "")
     {
       GlobalVariableSet(Per1, Peremen1);
     }             
   if(Per2 != "")
     {
       GlobalVariableSet(Per2,Peremen2);
     }
   if(Per3 != "")
     {
       GlobalVariableSet(Per3,Peremen3);
     }
   if(Per4 != "")
     {
       GlobalVariableSet(Per4,Peremen4);
     }
   Comment(Per1, " ", Peremen1, "  | ", Per2, " ", Peremen2, "  | ", Per3, 
           " ", Peremen3, "  | ", Per4, " ", Peremen4);
   Print(Per1, " ", Peremen1, "  | ", Per2, " ", Peremen2, "  | ", Per3, 
         " ", Peremen3,"  | ",Per4," ",Peremen4);
  }  // Конец функции Все, на этом автооптимизация завершена.


Результат работы автооптимизатора

Результат работы автооптимизатора можно отслеживать по сообщениям появляющимся в верхнем левом углу графика, как показано на скриншоте:



Расчетное время окончания оптимизации.


Анализ полученных после оптимизации значений.


Итоговые значения переменных.

Появление результатов оптимизации в сообщении говорит о том, что оптимизация завершена и данные получены.

Для самостоятельной оценки работы автооптимизатора можно посмотреть сохраненные в процессе работы файлы с промежуточными данными. Тестер сохраняет данные в файл с названием "FileReport_EURUSD_2007.03.12.htm", где символ инструмента и дата подставляются в название файла в зависимости от выбранного инструмента и текущей даты оптимизации. Находится этот файл в папке Терминал-тестера. Эти файлы с отчетами автоматически не удаляются и по ним можно отслеживать изменение параметров.



Следующий файл FileTest1.csv сохраняется после фильтрации значений по количеству сделок и удалению дубликатов. Файл сохраняется в папку: D:\Program Files\имя папки терминала\experts\files



Далее в файл FileTest2.csv сохраняются значения после каждого шага отсеивания. Файл также сохраняется в папку: D:\Program Files\имя папки терминала\experts\files



Из вышеприведенных таблиц видно, как происходит фильтрация полученных значений. Порядок фильтрации был установлен по умолчанию: 1- Gross_Profit, 2- Profit_Factor, 3- Expected_Payoff.

В коде автооптимизатора даны подробные комментарии и при необходимости вы можете сами подобрать подходящие для вас параметры переменных. Например, вы хотите оптимизировать не за последние дни, а за какой то другой промежуток времени, или предполагаете увеличить или уменьшить количество сделок за период оптимизации. Для этого вам достаточно изменить соответствующие переменные непосредственно в библиотеке auto_optimization.mqh.
 // Ограничение на минимальное количество сделок в день
double MinTr   = TestDay - 2; 
// Ограничение на максимальное количество сделок в день
double MaxTr   = (60 / Period()*TestDay) + 2;
// Количество попыток скопировать файл отчета
int    KvoPptk = 10;
// Количество строк для сортировки
int    StepRes = 12;

Заключение

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

Кроме того, желательно не устанавливать период автооптимизации слишком большим. Предположим, эксперт будет каждые сутки оптимизироваться по 6 - 12 часов. Тогда возникает вопрос, а когда он будет торговать? Иначе говоря, оптимизация не должна быть ради самой оптимизации. Устанавливать периодичность (имеется в виду периодичность запуска автооптимизатора) проведения оптимизации желательно с учетом периода, на котором предполагается торговля советника. То есть, нужно учитывать, что во время запуска Терминал-Тестера происходит подкачка исторических данных и у брокера может просто не быть нужных исторических данных за установленный период. Для проверки описанной в начале статьи гипотезы необходимо наличие круглосуточно подключенного к интернету компьютера и стабильного интернета.


Разработанные программы автоматической оптимизации расположены в прикрепленных файлах: auto_optimization.mqh - непосредственно сама библиотека, MACD Sample_1.mq4 - слегка измененный советник, входящий в состав клиентского терминала MetaTrader 4.


Прикрепленные файлы:
auto_optimization.mqh (20.6 Kb)
MACD Sample_1.mq4 (8.0 Kb)
Создана: 16.04.2007  Автор: Igor Malcev
Предупреждение: все права на данные материалы принадлежат MetaQuotes Software Corp. Полная или частичная перепечатка запрещена.
Как не попасть в ловушки оптимизации?
Как не попасть в ловушки оптимизации?

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

Визуализация тестирования. Графики состояния счета.
Визуализация тестирования. Графики состояния счета.

Погрузитесь в процесс тестирования с графиками, отображающими состояние счета - теперь вся необходимая информация всегда на виду!

121 комментарий: 1 2 3 4 5 6 7 8 9 10 11 12 13   Авторизуйтесь или зарегистрируйтесь
xeon писал(а):
CDR писал(а):
привет Павел (Paha)!
Здравтсвуйте уважаемые!
Хорошую вещь по-моему сделали. Спасибо.
Павел. я чсас добавлю это все в ссоветника Ai только оптимизировать буду 5 параметров х1, х2,хч3,х4 и sl. Потом тебе скину.
А для такого дела я заведу счета специально и буду давать автору историю раз в неделю. Для меня Очень актуальна автооптимизация.
Спасибо еще раз.



Спасибо за посильную помощь, думаю многим пригодится подобная статистика.
Надеюсь у вас не возникнет проблем с подключением автооптимизатора.
Привет CDR (не знаю по имени)!
Очень рад видеть тебя в этой ветке. Спасибо за Аi (зарание) Не далее как вчера начал его тестирование в онлайне на 5 мин. Пока судить рано. Как у тебя дела с установкой расчета позиций? Получил письмо?
Актуальна данная проблема была есть и будет у многих. И если Уважаемому автору удалось ее решить - это будет очень и очень. .. Сам пробовал систему в которой переоптимизация и ставки делаются только в 00.01 по гринвичу.(правда очень давно). Досидеть до этого времени ух и тяжело, тем более что утром на работу.
Чем смогу помогу автору. Еще раз спасибо ему.
С уважением Павел.
20.04.2007 21:49 Paha
н-да.. добавить все получилось просто. вот только выдало мне в журнал таку штуку
2007.04.20 20:34:18 ArtificialIntelligence_LAO GBPUSD,M1: function 'ShellExecuteA' call from dll 'shell32.dll' not confirmed

Как справится с этим? Я не умею  и не понимаю. Помогите пожалуйста.



20.04.2007 21:41 CDR
CDR писал(а):
привет Павел (Paha)!
Здравтсвуйте уважаемые!
Хорошую вещь по-моему сделали. Спасибо.
Павел. я чсас добавлю это все в ссоветника Ai только оптимизировать буду 5 параметров х1, х2,хч3,х4 и sl. Потом тебе скину.
А для такого дела я заведу счета специально и буду давать автору историю раз в неделю. Для меня Очень актуальна автооптимизация.
Спасибо еще раз.



Спасибо за посильную помощь, думаю многим пригодится подобная статистика.
 Надеюсь у вас не возникнет проблем с подключением автооптимизатора.
20.04.2007 21:25 xeon
привет Павел (Paha)!
Здравтсвуйте уважаемые!
Хорошую вещь по-моему сделали. Спасибо.
Павел. я чсас добавлю это все в ссоветника Ai только оптимизировать буду 5 параметров х1, х2,хч3,х4  и sl. Потом тебе скину.
А для такого дела я заведу счета специально и буду давать автору историю раз в неделю. Для меня Очень актуальна автооптимизация.
Спасибо еще раз.


20.04.2007 21:14 CDR
xeon писал(а):
Paha писал(а):

'lot lib'


а какие переменные вы хотите оптимизировать?

Я добавил немного текста в предыдущем коментарии. Или чего-то упустил?
19.04.2007 23:21 Paha
Paha писал(а):

'lot lib'


а какие переменные вы хотите оптимизировать?
19.04.2007 22:16 xeon
xeon писал(а):
Paha писал(а):
Спасибо за понимание!
С удовольствием помогу и Вам и себе в том числе. Прошу прощения, но хочу оговориться (просто не хочу быть пустозвоном), Тестирование советников на демосчете в круглосуточном онлайне смогу начать только недели через 2-3, по определенным причинам. Только после успешного их тестирования, буду загонять на реал. А выкладывать результаты тестирования не проблемма, тем боллее 1 раз в неделю. Еще один вопрос на тестере по истории, ваш автоматизатор, тоже справляется? Если его прогнать по истории? На сегоднешний день есть два советника, которые буду гонять в онлайне круглосуточно: MAKD sempl от Коmpostera, о котором я упоминал ранее и AI от г-на Решетова. (Если бы в него добавить управление размером позиций от Кompostera и Ваш автооптимизатор, получилось бы очень неплохо.) Перепробовал множество разных советников, но на данный момент только у этих двух нашел неплохие закономерности, кстати подтверждающие на 90 процентов Ваши приедположения. В первом случае при тестировании эффект проэкции на будущее работает на 2- 3 дня (EURUSD - 5 мин) при предварительной прогонке в прошлое на 2 недели в том же таймфрейме, во втором случае эффект длится 2, максимум 3 недели (EURUSD - 30 мин) при предворительной прогонке на 1 год в прошлое в том же таймфрейме, по ценам открытия. После чего советники нужно переоптимизировать заново.
Еще раз спасибо! Если Вас ситуация не смущает, буду очень рад поработать на благо...:-).
С уважением! Павел.
Ну и отлично, кидайте сюда своего эксперта, укажите какие параметры должны оптимизироватся автоматически и я в ближайшее время подключу к нему библиотеку автооптимизатора.

Добрый вечер! Если не трудно скачайте Все по нижеуказанной ссылке. Это не из за лени , а для полноты информации. А параметры оптимизации следующие: Оптимизируемый параметр- Баланс (с использованием генетического алгоритма); сумма нач депо 3000. Оптимизация должна иметь выбор по модели оптимизации - на всех наименьших тиках и т.д (короче все как всегда). Оптимизации подвергаются следующие параметры: Таке profit 10-5-100; Stoploss 50-10-200; TreylingStop 5-5-80; MakdOpen 1-1-10 MakdClose 1-1-10; MATrendPeriod 10-2-40; Lot size variant 0-1-2; StartLot 0. 1-0. 1-3; ADD lot 0. 1-0. 1-0. 6; True profit points 10-100-600; Минимальный уровень маржи 30, Максимальная просадка 30. Цифры привел на всякий случай. Надеюсь в советнике можно будет их менять( я так понимаю в тестовом варианте.) Некоторые наблюдения, которые могут быть интересны: неплохие результаты получаются если переоптимизацию проводить по ценам открытия (быстрый метод), а тестировать или играть на наименьших тиках. Пригодится это, Вам, или нет ? Незнаю. 'lot lib'
Во втором советнике 'AI' - Artificiallntelligence оптимизируемые параметры - х1;х2;х3;х4;sl;lots. Но я думаю наглостью будет просить и в него встроить Вашу функцию. Отказ приму как надлежащее. Кстати возможность тестировать в онлайне уже появилась. Правда инет у нас странноватый. Каждый день в 23.59 вырубается, а затем примерно через минуту - две возобновляет свою работу. Из за этого даже банки которые оказывают услуги по доступу на Forex (а может и по другой причине) все открытые позиции закрывыают 23.59 и открывают заново в 00.01. При етом Метотрейдер настроен так, что делает записи про своп операции. Все как положено. У другого оператора Forex все наоборот: показывает что разрыва связи не было, а свопы учитывает по окончанию сделки в отдельной колонке. Вот и не совсем понятно будут ли советники адекватно работать в таких условиях? Хотелось бы узнать Ваше мнение.
Спасибо! И удачи! Павел.
PS. В данной ветке бываю только по вечерам.


19.04.2007 22:07 Paha
Paha писал(а):
Спасибо за понимание!
С удовольствием помогу и Вам и себе в том числе. Прошу прощения, но хочу оговориться (просто не хочу быть пустозвоном), Тестирование советников на демосчете в круглосуточном онлайне смогу начать только недели через 2-3, по определенным причинам. Только после успешного их тестирования, буду загонять на реал. А выкладывать результаты тестирования не проблемма, тем боллее 1 раз в неделю. Еще один вопрос на тестере по истории, ваш автоматизатор, тоже справляется? Если его прогнать по истории? На сегоднешний день есть два советника, которые буду гонять в онлайне круглосуточно: MAKD sempl от Коmpostera, о котором я упоминал ранее и AI от г-на Решетова. (Если бы в него добавить управление размером позиций от Кompostera и Ваш автооптимизатор, получилось бы очень неплохо.) Перепробовал множество разных советников, но на данный момент только у этих двух нашел неплохие закономерности, кстати подтверждающие на 90 процентов Ваши приедположения. В первом случае при тестировании эффект проэкции на будущее работает на 2- 3 дня (EURUSD - 5 мин) при предварительной прогонке в прошлое на 2 недели в том же таймфрейме, во втором случае эффект длится 2, максимум 3 недели (EURUSD - 30 мин) при предворительной прогонке на 1 год в прошлое в том же таймфрейме, по ценам открытия. После чего советники нужно переоптимизировать заново.
Еще раз спасибо! Если Вас ситуация не смущает, буду очень рад поработать на благо...:-).
С уважением! Павел.
Ну и отлично, кидайте сюда своего эксперта, укажите какие параметры должны оптимизироватся автоматически и я в ближайшее время подключу к нему библиотеку автооптимизатора.

19.04.2007 19:45 xeon
HIDDEN писал(а):
Это даст свой результат если эксперт при тесте использует историю других валютных пар.


по поводу подкачки историидругих валютных пар - согласен :-)
19.04.2007 19:39 xeon
xeon писал(а):
Paha писал(а):
Уважаемый XEON!
Огромное спасибо за статью, уверен будет пользоваться большим спросом. Особенно у тех, кому приходиться переоптимизировать советников, скажем, в 23,59 по гринвичу.(у каждого своя стратегия), и неважно один раз в сутки или 1 раз в неделю.
Прошу прощения за невежество, но в кодах я не разбираюсь обсолютно. Тревиальный вопрос: Есть у меня советник (тот-же МАКD sampl), но с установленным блоком управления размерами позиций (lot_lib.mqh, MACD Sample.mq4 от Kompostera?, ему отдельное спасибо. выложен на этом-же сайте в разделе - библиотеки). Приходиться отимизировать его каждые трое суток, с периодом переоптимизации 2 недели, на 5 минутах, EURUSD. Можно-ли будет к Вам обратиться, (не безвозмездно) доработать именно этот советник?
Спасибо!
С уважением! Павел.

Уважаемый Paha я готов бесплатно сделать то что вы просите, но у меня к вам будет ответная просьба: для проверки гипотезы описанной в начале статьи нехватает статистики, немогли-бы вы примерно 1 раз в неделю выкладывать сюда отчеты о работе экспертов, 1 - без автоматической оптимизации параметров, 2 - с автоматической оптимизацией параметров. Думаю такая статистика пригодилась бы многим.
С уважением xeon



Спасибо за понимание!
С удовольствием помогу и Вам и себе в том числе. Прошу прощения, но хочу оговориться (просто не хочу быть пустозвоном), Тестирование советников на демосчете в круглосуточном онлайне смогу начать только недели через 2-3, по определенным причинам. Только после успешного их тестирования, буду загонять на реал. А выкладывать результаты тестирования не проблемма, тем боллее 1 раз в неделю. Еще один вопрос на тестере по истории, ваш автоматизатор, тоже справляется? Если его прогнать по истории? На сегоднешний день есть два советника, которые буду гонять в онлайне круглосуточно: MAKD sempl от Коmpostera, о котором я упоминал ранее и AI от г-на Решетова. (Если бы в него добавить управление размером позиций от Кompostera и Ваш автооптимизатор, получилось бы очень неплохо.) Перепробовал множество разных советников, но на данный момент только у этих двух нашел неплохие закономерности, кстати подтверждающие на 90 процентов Ваши приедположения. В первом случае при тестировании эффект проэкции на будущее работает на 2- 3 дня (EURUSD - 5 мин) при предварительной прогонке в прошлое на 2 недели в том же таймфрейме, во втором случае эффект длится 2, максимум 3 недели (EURUSD - 30 мин) при предворительной прогонке на 1 год в прошлое в том же таймфрейме, по ценам открытия. После чего советники нужно переоптимизировать заново.
Еще раз спасибо! Если Вас ситуация не смущает, буду очень рад поработать на благо...:-).
С уважением! Павел.
18.04.2007 22:46 Paha
121 комментарий: 1 2 3 4 5 6 7 8 9 10 11 12 13