Торговые системы: Эксперты на основе популярных торговых систем и алхимия оптимизации торгового робота (Продолжение)

 

период оптимизации в месяцах

а можно задавать период оптимизации, а также тестирования и сдвиг в днях?
 
Добрый день, Николай!

Спасибо Вам огромное за труд, интересные предложения и доходчивые пояснения.

Очень понравилась предлагаемая схема оптимизации советника. И реализация таймсерий оптимизации - хорошая и интересная. Честно-говоря не знал, что такое возможно.

Но есть ряд вопросов.

В частности не совсем понятно - зачем оптимизировать по переменной Opt_Number? На мой взгляд сравниваются соверешенно несвязанные данные, ведь советник на одних и тех же параметрах на разных периодах может дать совершенно разные результаты, а сравнение при оптимизации ведётся по результатам. Так как же можно сравнивать результаты работы советника, да ещё на разных периодах, да ещё при разных параметрах? А если ещё оптимизация ведётся с включением функции ГА - это по крайней мере некорректно и нерезультанивно. Разброс параметров и результатов будет очень большой.

Я ещё не очень глубоко разобрался в MQ-4, поэтому и хотел бы узнать Ваше мнение.

А возможна ли реализация автоматическая-циклическая реализация бэк-тэстинга? Т.е. есть такая идея. Попробую описать.

1-й цикл - Идёт обычная оптимизация по 0-му периоду (т.е. по периоду оптимизации - 3 мес. как это реализовано у Вас). После его окончания - автоматически запускается 2-й цикл.

2-й цикл - Идёт вторичная оптимизация, но уже по периоду тестирования (4-й и 5-й месяцы), и параметры берутся не огульно по ГА, а из результатов первой оптимизации.

Т.е. получится как бы двойной прогон на одних и тех же параметрах.

Возможна ли реализация в MQ-4 такой задачи?

 
У меня ещё есть к Вам одно предложение и один вопрос.

1. В частности не могу понять зачем установлена проверка Timeframe ? Насколько я понимаю этот параметр устанавливается при инициализации советника и в дальнейшем вообще не изменяется, только проверяется. Для чего эта проверка? Почему выбраны именно такие значения этого параметра? Насколько я понял этот параметр связын с периодом валютной пары, на котором работает советник (М1, М5, М30...).

2. При реализации функций открытия ордеров Вы исключили параметр - "коментарии". Видимо Вы этот параметр просто никогда не используете. У меня МТС реализована на основе нескольких торговых логик и мне интересно которая из них сработала, поэтому ордера приходится подписывать. Поэтому я дописал в ваших функциях ещё один параметр - string Name_Order. Мне кажется, что в этом я не одинок.

 

 

 SouthAlex писал(а):



период оптимизации в месяцах

а можно задавать период оптимизации, а также тестирования и сдвиг в днях?



Вот код, который позволяет задавать параметры в днях, для этого необходимо переменную Opt_Period сделать отрицательной, это уже исправленный вариант кода:            

//+X================================================================X+
//|                                            IsBackTestingTime.mqh |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+X================================================================X+
//---- Объявления внешних переменных для бэктестинга
extern datetime Start_Time = D'2007.01.01'; // время старта нулевой 
                                                        //оптимизации
extern int Opt_Period = 3; // период оптимизации в месяцах, если 
   //значение периода меньше нуля, то все параметры измеряются в днях
extern int Test_Period = 2; // период тестирования в месяцах
extern int Period_Shift = 1; //шаг сдвига периода оптимизации в 
                                                             //месяцах
extern int Opt_Number = 0; // номер оптимизации 
//+X================================================================X+
//| IsBackTestingTime()                                              |
//+X================================================================X+
bool IsBackTestingTime()
 {
//----+
  //---- Объявления статических переменных времени
  static datetime OptStart_Time, OptEnd_Time, TestEnd_Time;
  //---- Объявления статических логических переменных
  static bool SecondStart;
  
  if (!SecondStart)
   {
    //----+ БЭКТЕСТИНГ ДЛЯ ДНЕВНЫХ ИНТЕРВАЛОВ  
    if (Opt_Period > 0)
     {  
      //----+ ИНИЦИАЛИЗАЦИЯ КОНСТАНТ ДЛЯ БЭКТЕСТИНГА
      int newmonth, newyear;
      string StartTime, OptDay; 
      //---
      StartTime = TimeToStr(Start_Time, TIME_DATE);
      OptDay = 
         StringSubstr(StartTime, 8, 9);
      newyear = 
         StrToInteger(StringSubstr(StartTime, 0, 4));
      newmonth = 
         StrToInteger(StringSubstr(StartTime, 5, 6));
      //---
      newmonth += Opt_Number * Period_Shift;
      OptStart_Time = 
               CountTime(newmonth, newyear, OptDay);     
      //----
      newmonth += MathAbs(Opt_Period);                      
      OptEnd_Time = 
               CountTime(newmonth, newyear, OptDay);  
      //----
      newmonth += Test_Period;
      TestEnd_Time = 
               CountTime(newmonth, newyear, OptDay);
      SecondStart = true;
     } 
    //----+ БЭКТЕСТИНГ ДЛЯ ЧАСОВЫХ ИНТЕРВАЛОВ 
    if (Opt_Period < 0)
     {
      //----+ ИНИЦИАЛИЗАЦИЯ КОНСТАНТ ДЛЯ БЭКТЕСТИНГА
      OptStart_Time = Start_Time + 
                    Opt_Number  * Period_Shift * 3600 * 24;
      OptEnd_Time = 
           OptStart_Time + MathAbs(Opt_Period) * 3600 * 24;
      TestEnd_Time = OptEnd_Time + Test_Period * 3600 * 24;
      SecondStart = true;
     }                               
   }           
  //----+ ПРОВЕРКА ВЫПОЛНЕНИЯ УСЛОВИЙ БЭКТЕСТИНГА
  //----+ +--------------------------------------------------------+
  datetime TimeCar = TimeCurrent();   
  if (IsOptimization())
      if (TimeCar < OptStart_Time || TimeCar > OptEnd_Time)
                                                     return(false);
  if (!IsOptimization() && IsTesting())
      if (TimeCar < OptEnd_Time || TimeCar > TestEnd_Time)
                                                     return(false);
  //----+ +--------------------------------------------------------+
  return(true);
//----+
 }
//+X================================================================X+
//| CountTime() // Вспомогательная функция для IsBackTestingTime()   |
//+X================================================================X+
datetime CountTime(int& newmonth, int&newyear, string OptDay)
 {
//----+
   string sResaltTime;
   datetime dResaltTime;
   //---
   if (newmonth > 12)
       {
         newyear +=  MathFloor(newmonth / 12.0);
         newmonth = MathMod(newmonth, 12); 
       }
      //---          
   if (newmonth > 9)
       sResaltTime = StringConcatenate
                    (newyear, ".", newmonth, ".", OptDay);
   else
     sResaltTime = StringConcatenate
                   (newyear, ".0", newmonth, ".", OptDay);
   //---                                
   dResaltTime = StrToTime(sResaltTime);
   return(dResaltTime);
//----+
 }
//----+ +---------------------------------------------------------------+
 

Вот нашёл ошибку.

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

Внимательно проанализировал код функции. Действительно - ошибка. Оказалась, что логику функции не реализовывает следующая запись:

      newmonth += Opt_Number * Opt_Period * Period_Shift;     

      ...

 

Если подставить в вышеприведённые формулы абсолютные значения, то получатся следующие результаты.

Первоначальные, установленные автором значения переменных:

//---- Объявления внешних переменных для бэктестинга
extern datetime Start_Time = D'2007.01.01'; // время старта нулевой оптимизации
extern int Opt_Period = 3;                  // период оптимизации в месяцах
extern int Test_Period = 2;                 // период тестирования в месяцах
extern int Period_Shift = 1;                // сдвиг периодрв оптимизации и тестирования в месяцах
extern int Opt_Number = 0;                  // номер оптимизации
Подставляем их в вышепреведённые формулы. Получается:

      newmonth += Opt_Number * Opt_Period * Period_Shift;

      newmonth = 0 + 0*3*1 = 0 ,   // т.е. номер начального месяца оптимизации = 0, т.е. 2007.01.01

 

Теперь попробуем посмотреть оптимизацию под номером 1, т.е. сдвинуть начало оптимизационного периода на один месяц, т.е. параметр Opt_Number = 1 , не меняя при этом остальных параметров. Что получается?

      newmonth += Opt_Number * Opt_Period * Period_Shift;

      newmonth = 0 + 1*3*1 = 3 ,   // т.е. номер начального месяца оптимизации = 3, т.е. 2007.03.01

 

Т.е. начальный месяц у нас сдвинулся не на 1 месяц, а на 3. И т.д. (Opt_Number = 2, newmonht = 6 ...).

Такая же история происходит и при попытказ изменения сдвигов Period_Shift. Т.е. до тех пор пока параметр Opt_Number будет равен нулю оптимизация неизменно будет начинаться с даты "2007.01.01". Если же установить параметр Opt_Number в какое-нибудь другое значение, не равное 0, периоды сразу скачут на величину Opt_Number * Opt_Period * Period_Shift.  В общем Данная задача нереализована.

 

Далее, возвнащаясь к самой схеме бэк-тестирования. Идея делать временной сдвиг, т.е. проецировать так сказать будующее в прошлое, т.е. разделять периоды оптимизации и тестирования на исторических данных - великолепна. Но крайне непонятна идея проводить много уровневая оптимизация. Сам принцип и методы его реализации - понятны, а вот результат - не понятен. Что мы получаем в итоге всех этих действий? Думаю даже достойный ответ - может ли работать советник на реале - и то не получим. Автор упоминал в первой статье, что написать советник и подогнать его под историю, получив при этом просто замечательные результаты - не составляет особого труда. Так что же мы получаем в итоге всех этих манипуляций.

Попробуем проанализировать. При оптимизации система выдаёт разброванные по параметрам результаты. В периоде тестирования - можно найти достойные параметры, которые неплохо работали и на периоде оптимизации и на периоде тестирования. И что сделать с этими параметрами?

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

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

В чём смысл этих манипуляций? Что мы хотим в итоге получить от этих действий? Ответим ли мы на вопрос - способен ли наш советник реально работать в реальном времени в будущем

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

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

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

      newmonth = Opt_Number;     

      либо

      newmonth = Period_Shift;

 
Kadet:

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


А в принципе думаю на это и расчитана эта технология. Т.е. ответить на вопрос действительно ли советник полная лажа или он ещё способен подгоняться под некие параметры.

 

В общем я благодарен Вам, Николай!

Заставили очень сильно и о многом задуматься.

 
О!

И ещё одну закавыку в функции нашёл.

Период тестирования в функции должен находиться внутри периода, установленного на тестере. Т.е. сли на тестере будет установлен период 2008.01.01-2008.04.03, а мы попытаемся функцией протестировать период - 2007.01.01-2007.06.01 - результатов не будет. Выдаст - 0.

 

Kadet! Это просто несерьёзно! Вы только начали изучать язык MQL, по большому счёту его ещё и не понимаете как следует, а абсолютно впустую пытаетесь судить о вешах, которые не понимаете абсолютно и при этом тратите своё и чужое время! Вот код, к которому у вас претензии:

      newmonth = StrToInteger(StringSubstr(StartTime, 5, 6));
      //---
      newmonth += Opt_Number *MathAbs(Opt_Period) * Period_Shift;

Попытаюсь вам его расшифровать (знак равенства стоял с плюсом!!!!!):

      newmonth = StrToInteger(StringSubstr(StartTime, 5, 6));
      //---
      newmonth = newmonth + Opt_Number *MathAbs(Opt_Period) * Period_Shift;
Вы смотрите внимательней на код и проверяйте каждую мелочь! Убирайте ваш словесный хлам, он никому не нужен, вы не правы!
 
GODZILLA:

Kadet! Это просто несерьёзно! Вы только начали изучать язык MQL, по большому счёту его ещё и не понимаете как следует,

...

Вы смотрите внимательней на код и проверяйте каждую мелочь! Убирайте ваш словесный хлам, он никому не нужен, вы не правы!


С MQ-4 я действительно знаком недавно, зато осмелюсь Вам доложить, что с другими языками и программированием вцелом я знаком очень давно и не по наслышке, так, что о работе программных функций судить могу и записи типа -  +=, -=, != и т.д. для меня не в диковинку. В абсолютных значениях я расшифровал как - newmonth = 0 + 1*3*1 = 3 , где первый "0", извините, действительно ошибочен. Там будет соять "1" (т.е. январь 2007).

Попробуйте вручную поменяйте значение переменной Opt_Number и проведите оптимизацию. А затем проверте результаты на тестировании. Особое внимане обратите на даты ордеров. Надеюсь Вы, уважаемый Николай, заметите, что:

- при значении Opt_Number = 0, ордера на тестировании выставляются начиная с 2007.04.01,

- при Opt_Number = 1, ордера на тестировании выставляются начиная с 2007.07.01,

- при Opt_Number = 2, ордера на тестировании выставляются начиная с 2007.10.01,

- при Opt_Number = 3, ордера на тестировании выставляются начиная с 2008.01.01,

- при Opt_Number = 4, ордера на тестировании вообще не вытавляются, потому что тестирование проводится на ещё не существующем периоде истории, т.е. в будущем.

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

Поробуйте, может тогда поймёте о чём это я.

Формула - некорректна. Или так было задумано?

Я у себя убрал лишние заморочки - заработал корректно.

 
Хотел бы повторить свой вопрос.

А возможна ли реализация автоматическая-циклическая реализация бэк-тэстинга? Т.е. есть такая идея. Попробую описать.

1-й цикл - Идёт обычная оптимизация по 0-му периоду (т.е. по периоду оптимизации - 3 мес. как это реализовано у Вас). После его окончания - автоматически запускается 2-й цикл.

2-й цикл - Идёт вторичная оптимизация, но уже по периоду тестирования (4-й и 5-й месяцы), и параметры берутся не огульно по ГА, а из результатов первой оптимизации.

Т.е. получится как бы двойной прогон на одних и тех же параметрах.

Возможна ли реализация в MQ-4 такой задачи?