Жидкий график

17 ноября 2014, 11:58
Serhii Shevchuk
33
8 239

Введение

Однажды я обратил внимание на то, что у разных брокеров по-разному выглядят графики с периодом H4 и выше. Причиной тому были разные часовые пояса. В некоторых случаях определенные участки графиков существенно отличались даже при незначительной разнице часовых поясов. На одном был четко виден разворотный паттерн, а на другом в этом месте было что-то неопределенное.

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

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



1. Принцип построения

Для начала определимся с терминологией.

Смещение или сдвиг - это разница во времени, на которую цены открытия баров полученного графика отличаются от цен открытия баров исходного графика.

Текущий период - это период исходного графика.

Базовый период - это период, по ценам которого мы будем формировать бары результирующего графика.

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

Существует три типа построения.

  • График с постоянным смещением (Static Shift или SS).
  • График с динамическим смещением, режим открытия (Dynamic Shift, just Open или DSO).
  • График с динамическим смещением, режим закрытия (Dynamic Shift, expected Close или DSC).

В режиме с постоянным смещением времена открытия баров смещены на заданное время. Динамическое смещение в режиме открытия дает тот эффект, будто бар только что открылся, а в режиме закрытия - как будто бар скоро закроется.

Разберем это более детально.


1.1. График с постоянным смещением

В этом режиме время открытия каждого бара будет смещено на число минут, эквивалентное заданному количеству базовых периодов, которое будем называть смещением или сдвигом. Таким образом, если задано смещение 0, то график будет повторять исходный. Смещение 1 при условии, что базовый период 15 минут, будет равно 15 минутам. Смещение 2 будет равно 30 минутам, и так далее.

Смещение не может быть больше (k-1), где k - отношение текущего периода к базовому периоду. Это значит, что при текущем периоде H1 и базовом M1 максимально допустимым будет смещение 60/1 - 1 = 59 базовых периодов, то есть 59 минут. Если базовый период будет M5, то максимально допустимым будет смещение 60/5 - 1 = 11 базовых периодов, то есть 55 минут.

Времена открытия баров, на примере текущего периода H1 и смещения 15 минут, будут иметь значения 00:15, 01:15, 02:15 и так далее. Для текущего периода M15 и смещения 1 минута, времена открытия баров будут 00:16, 00:31, 00:46, 01:01 и так далее.

При смещениях, которые близки к граничным значениям, такой график редко отличается от исходного графика. Существенные отличия наблюдаются при значениях смещения, близкого к середине допустимого диапазона.

График со статическим смещением

Рис. 1. Пример образования часовых баров, исходя из базового периода M15 со смещением 1


1.2. График с динамическим смещением, режим открытия

В данном режиме смещение пересчитывается каждый раз при появлении нового бара базового периода. При этом смещение рассчитывается таким образом, чтобы время существования бара в конце графика (самые свежие цены) не превышало значения базового периода. На примере текущего периода H1 и базового M5, это будет выглядеть так, как будто самый правый бар открылся не более пяти минут назад.

График с динамическим смещением, начало бара

Рис. 2. Пример образования часовых баров, исходя из базового периода M15, с динамическим смещением в режиме открытия


1.3. График с динамическим смещением, режим закрытия

В данном режиме смещение также пересчитывается каждый раз при появлении нового бара базового периода. Отличие лишь в том, что смещение рассчитывается таким образом, чтобы время существования бара в конце графика (самые свежие цены) было больше или равно разнице между текущим и базовым периодом. На примере текущего периода H1 и базового M5, это будет выглядеть так, как будто самый правый бар должен закрыться не позже, чем через пять минут.

График с динамическим смещением, завершение бара

Рис. 3. Пример образования часовых баров, исходя из базового периода M15, с динамическим смещением в режиме закрытия


2. Преобразование данных

Для преобразования исторических данных с учетом заданного сдвига была написана функция GetRatesLC(). Она получает модифицированные исторические данные в массив структур типа MqlRates, аналогично функции CopyRates().

int GetRatesLC(
   int             start_pos    // откуда копировать
   int             len,         // сколько копировать
   MqlRates&       rates[],     // массив, куда будут скопированы данные
   ENUM_TIMEFRAMES base_period, // базовый период
   int&            shift        // сдвиг
   );

Параметры

  start_pos

   [in]  Номер первого элемента в текущем периоде, с которого начнется преобразование и копирование в буфер.

  len

   [in]  Количество копируемых элементов.

  rates[]

   [out]  Массив типа MqlRates.

  base_period

   [in]  Базовый период. 

  shift

   [in] [out]  Сдвиг. Может принимать следующие значения:

ЗначениеОписание
 -2
 Рассчитать сдвиг в режиме открытия (начало формирования бара)
 -1
 Рассчитать сдвиг в режиме закрытия (завершение формирования бара)
 0 ... N
 Применить указанный сдвиг. Может принимать значения от 0 до N.
 N = Tcur/Tbase - 1. Где Tcur - текущий период, Tbase - базовый период.

Табл. 1. Допустимые значения параметра shift

При успешном выполнении функции в shift будет положено значение рассчитанного сдвига, если было передано значение -2 или -1.

Возвращаемое значение

Количество скопированных элементов или код ошибки:

КодОписание
 -1
 Неверно задан базовый период
 -2
 Неверно задан сдвиг

Табл. 2. Возвращаемые коды ошибок

Ниже приведен код функции GetRatesLC() из файла liquidchart.mqh.

int GetRatesLC(int start_pos,int len,MqlRates &rates[],ENUM_TIMEFRAMES base_period,int& shift)
  {
   //--- сколько базовых периодов помещается в текущем периоде  
   int k=PeriodSeconds()/PeriodSeconds(base_period);
   if(k==0)
      return(-1);//неверно задан базовый период
   //---
   MqlRates r0[];
   ArrayResize(rates,len);
   if(CopyRates(_Symbol,_Period,start_pos,1,r0)<1)
      return(0);// нет данных
   //---
   int sh;
   if(shift>=0)
     {
      //--- фиксированный сдвиг
      if(shift<k)
         sh=shift;
      else
         return(-2);//--- неверно задан сдвиг   
     }
   else if(shift==-1)
     {
      //--- нужно рассчитать сдвиг (динамический, начало формирования бара)
      sh=int((TimeCurrent()-r0[0].time)/PeriodSeconds(base_period));
     }
   else if(shift==-2)
     {
      //--- нужно рассчитать сдвиг (динамический, завершение формирования бара)
      sh=1+int((TimeCurrent()-r0[0].time)/PeriodSeconds(base_period));
      if(sh>=k)
         sh = 0;
     }
   else
      return(-2);//неверно задан сдвиг       
   //--- время открытия бара базового периода, с которого начинается формирование бара текущего периода
   //--- относительно времени tO происходит синхронизация времен открытия баров
   datetime tO;
   //--- время закрытия формируемого бара, т.е. время открытия последнего бара базового периода в серии
   datetime tC;
   tO=r0[0].time+sh*PeriodSeconds(base_period);
   if(tO>TimeCurrent())
      tO-=PeriodSeconds();
   tC=tO+PeriodSeconds()-PeriodSeconds(base_period);
   if(tC>TimeCurrent())
      tC=TimeCurrent();
   int cnt=0;
   while(cnt<len)
     {
      ArrayFree(r0);
      int l=CopyRates(_Symbol,base_period,tC,k,r0);
      if(l<1)
         break;
      //--- время бара с индексом (l-1) не обязательно соответствует tC
      //--- если бара с временем tC не существует, это может быть ближайший бар
      //--- в любом случае, я присваиваю его время времени tC
      tC=r0[l-1].time;
      //--- теперь нужно проверить, что tO имеет корректное значение и исправить при необходимости.
      while(tO>tC)
         tO-=PeriodSeconds();
      //--- здесь времена tO и tC уже имеют актуальные значения для формируемого бара  
      int index=len-1-cnt;
      rates[index].close=0;
      rates[index].open=0;
      rates[index].high=0;
      rates[index].low=0;
      rates[index].time=tO;
      for(int i=0; i<l; i++)
         if(r0[i].time>=tO && r0[i].time<=tC)
           {
            if(rates[index].open==0)
              {
               rates[index].open= r0[i].open;
               rates[index].low = r0[i].low;
               rates[index].high= r0[i].high;
                 }else{
               if(rates[index].low > r0[i].low)
                  rates[index].low=r0[i].low;
               if(rates[index].high < r0[i].high)
                  rates[index].high=r0[i].high;
              }
            rates[index].close=r0[i].close;
           }
      //--- установка времени закрытия бара, следующего в цикле
      tC=tO-PeriodSeconds(base_period);
      //
      cnt++;
     }
   if(cnt<len)
     {
      //-- данных меньше, чем нужно, сдвигаем в начало буфера
      int d=len-cnt;
      for(int j=0; j<cnt; j++)
         rates[j]=rates[j+d];
      for(int j=cnt;j<len;j++)
        {
         //--- неиспользованные элементы массива заполняем нулями
         rates[j].close=0;
         rates[j].open=0;
         rates[j].high=0;
         rates[j].low=0;
         rates[j].time=0;
        }
     }
   shift = sh;  
   return(cnt);
  }

Сразу отмечу несколько важных моментов.

  • Функция не возвращает тиковые объемы. Все потому, что в режиме DSC функция никогда не вернет объем, равный единице, как это бывает при открытии бара. Это совершенно логично. Но если ваш советник использует тиковый объем, равный единице, как сигнал о формировании нового бара - то он его никогда не получит. Этот способ используется в советнике Moving Average из стандартных примеров. Вы можете дописать в функцию подсчет тиковых объемов, но он будет работать не совсем корректно. Чтобы не возникло путаницы, я вообще не считаю тиковые объемы.
  • Функция возвращает запрошенное количество баров, но это не значит, что промежуток времени между первым и последним баром будет соизмерим с соответствующим промежутком времени на исходном графике. На непрерывном участке исторических данных соответствие будет. Но если на заданном промежутке попадутся выходные, то на границе могут появиться "фантомные бары".

На рисунке ниже приведен пример "фантомного бара". Этот бар получился из первой минуты 27 октября, которая и попала в бар со временем открытия 23:01 26 октября. Нужно иметь в виду, что после таких баров график индикатора будет сдвинут влево по отношению к исходному графику. Бары со временем, соответствующим исходному времени (например, 21:00 -> 21:01), будут иметь другие индексы.

Фантомный бар

Рис. 4. Фантомный бар 2014.10.26 в 23:01



3. Реализация индикатора

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

Для начала нам понадобится функция GetRatesLC() из файла liquidchart.mqh. Мы будем вызывать ее из функции RefreshBuffers(), которая, в свою очередь, вызывается из OnCalculate. Она также вызывается из OnChartEvent, при условии, что изменился режим или сдвиг, и требуется пересчет буферов индикатора. Функция OnChartEvent будет обрабатывать нажатия на кнопки, и менять значения сдвига и режима.

Входные параметры индикатора:

input ENUM_TIMEFRAMES   BaseTF=PERIOD_M1;       // LC Base Period
input int               Depth=100;              // Depth, bars
input ENUM_LC_MODE      inp_LC_mode=LC_MODE_SS; // LC mode
input int               inp_LC_shift=0;         // LC shift

где Depth - количество баров результирующего графика, а ENUM_LC_MODE - тип, описывающий режимы построения индикатора:

enum ENUM_LC_MODE
  {//режим построения
   LC_MODE_SS=0,  // Static Shift
   LC_MODE_DSO=1, // Dynamic Shift, just Open
   LC_MODE_DSC=2  // Dynamic Shift, expected Close
  };
Параметры inp_LC_mode и inp_LC_shift дублируются переменными LC_mode и LC_shift соответственно. Это сделано для того, чтобы можно было менять их значения по нажатию на кнопки. Рисование и обработку нажатия кнопок мы не будем рассматривать, так как это не относится к теме данной статьи. Функцию RefreshBuffers() рассмотрим подробнее.
bool RefreshBuffers(int total,
                    double &buff1[],
                    double &buff2[],
                    double &buff3[],
                    double &buff4[],
                    double &col_buffer[])
  {
   MqlRates rates[];
   ArrayResize(rates,Depth);
//---
   int copied=0;
   int shift=0;
   if(LC_mode==LC_MODE_SS)
      shift = LC_shift; //статический сдвиг
   else if(LC_mode==LC_MODE_DSO)
      shift = -1;       //рассчитать сдвиг (начало формирования бара)
   else if(LC_mode==LC_MODE_DSC)
      shift = -2;       //рассчитать сдвиг (завершение формирования бара)
   else
      return(false);
//---
   copied=GetRatesLC(0,Depth,rates,BaseTF,shift);
//---
   if(copied<=0)
     {
      Print("Нет данных");
      return(false);
     }
   LC_shift = shift;
   refr_keys();
//--- инициализируем буферы пустыми значениями
   ArrayInitialize(buff1,0.0);
   ArrayInitialize(buff2,0.0);
   ArrayInitialize(buff3,0.0);
   ArrayInitialize(buff4,0.0);
//---
   int buffer_index=total-copied;
   for(int i=0;i<copied;i++)
     {
      buff1[buffer_index]=rates[i].open;
      buff2[buffer_index]=rates[i].high;
      buff3[buffer_index]=rates[i].low;
      buff4[buffer_index]=rates[i].close;
      //---
      if(rates[i].open<=rates[i].close)
         col_buffer[buffer_index]=1;//бычья или доджи
      else
         col_buffer[buffer_index]=0;//медвежья
      //
      buffer_index++;
     }
//
   return(true);
  }

Сначала необходимо передать функции GetRatesLC() нужное значение переменной shift, в зависимости от режима. В статическом режиме это будет копия параметра LC_shift, в режиме открытия или закрытия бара это будет -1 или -2 соответственно. После успешного выполнения, GetRatesLC() вернет в переменной shift текущее значение сдвига. Оно будет пересчитано или оставлено прежним. В любом случае, присваиваем его значение переменной LC_shift и вызовем перерисовку графических элементов функцией refr_keys().

После этого обновим значения OHLC и цвет баров в индикаторных буферах.

Полный код индикатора находится в файле liquid_chart.mq5. После запуска индикатор выглядит так:

Индикатор Liquid Chart, сдвиг 0

Рис. 5. Индикатор Liquid Chart

Немного об элементах управления.

  • Кнопка SS переключает индикатор в режим статического сдвига. В этом режиме активны кнопки со стрелками, которыми можно установить нужное значение сдвига.
  • Кнопка DSO переключает индикатор в режим динамического сдвига, начало формирования бара. В этом режиме сдвиг рассчитывается, и изменить его значение вручную нельзя.
  • Кнопка DSC переключает индикатор в режим динамического сдвига, завершение формирования бара. В этом режиме ручное изменение сдвига также недоступно.

В режиме SS при значении сдвига 0, индикатор в точности повторяет значения исходного графика. Попробуйте изменить сдвиг, и вы увидите, как график перестраивается. При значении 28 уже есть заметные отличия. Вместо слабо выраженных "рельс" появился вполне различимый "молот". Пришло время покупать?

Индикатор Liquid Chart, сдвиг 28

Рис. 6. Индикатор Liquid Chart, статический сдвиг 28

Переключите индикатор в режим DSO - и справа всегда будет только что сформировавшийся бар. А в режиме DSC - бар, которому до закрытия осталось не более одного базового периода.


4. Создание эксперта

Мы создадим двух экспертов. Первый будет торговать по скользящим средним, второй - по паттерну "пин бар".

За основу возьмем эксперт Moving Average из стандартного набора примеров (папка Experts\Examples\Moving Average). Таким образом, у нас будет возможность сравнить результаты оптимизации двух принципиально разных стратегий, чтобы понять, в каких именно случаях имеет значение применение статического или динамического сдвига.


4.1. Эксперт, торгующий по скользящим средним

Для начала определимся с входными параметрами. В оригинале их четыре:

input double MaximumRisk    = 0.1// Maximum Risk in percentage
input double DecreaseFactor = 3;    // Descrease factor
input int    MovingPeriod   = 12;   // Moving Average period
input int    MovingShift    = 6;    // Moving Average shift

Вследствие модернизации, добавятся еще три параметра:

input ENUM_TIMEFRAMES  BaseTF=PERIOD_M1;  // LC Base Period
input bool             LC_on = true;      // LC mode ON
input int              LC_shift = 0;      // LC shift

Параметр LC_on пригодится на тот случай, если нужно будет проверить корректность работы GetRatesLC(). Комбинация (LC_on == true && LC_shift == 0) должна давать тот же результат, что и (LC_on == false).

Для модернизации готового эксперта Moving Average с применением сдвига, нужно для начала прикрепить файл liquidchart.mqh и заменить функции CopyRates() функциями GetRatesLC() для тех случаев, когда включено использование сдвига (входной параметр LC_on равен true):

   int copied;
   if(LC_on==true)
     {
      int shift = LC_shift;
      copied=GetRatesLC(0,2,rt,BaseTF,shift);
     }
   else
      copied = CopyRates(_Symbol,_Period,0,2,rt);
   if(copied!=2)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }

Это нужно сделать в двух местах - в функциях CheckForOpen() и CheckForClose(). Также, мы вынуждены отказаться от использования хэндлов индикатора, и будем считать скользящие средние "вручную". Для этого добавлена функция CopyMABuffer():

int CopyMABuffer(int len,double &ma[])
  {
   if(len<=0)
      return(0);
   MqlRates rates[];
   int l=len-1+MovingPeriod;
   int copied;
   if(LC_on==true)
     {
      int shift = LC_shift;
      ArrayResize(rates,l);
      copied=GetRatesLC(MovingShift,l,rates,BaseTF,shift);
     }
   else
      copied=CopyRates(_Symbol,_Period,MovingShift,l,rates);
//      
   if(copied<l)
      return(0);
//
   for(int i=0;i<len;i++)
     {
      double sum=0;
      for(int j=0;j<MovingPeriod;j++)
        {
         if(LC_on==true)
            sum+=rates[j+i].close;
         else
            sum+=rates[copied-1-j-i].close;
        }
      ma[i]=sum/MovingPeriod;
     }
   return(len);
  }

Она возвращает в буфере ma[] запрошенное количество значений скользящей средней, или 0, если по каким-то причинам не удалось их получить.

Еще один важный момент - контроль открытия баров. В оригинальной версии советника Moving Average это реализовано, опираясь на значение тиковых объемов:

   if(rt[1].tick_volume>1)
      return;

В нашем случае тиковых объемов нет, поэтому, для контроля открытия баров напишем функцию newbar():

bool newbar(datetime t)
  {
   static datetime t_prev=0;
   if(t!=t_prev)
     {
      t_prev=t;
      return(true);
     }
   return(false);
  }

Принцип действия прост - сравнение времени открытия бара с его предыдущим значением. Заменим проверку тикового объема на вызов функции newbar() в двух местах - в функции CheckForOpen() и CheckForClose():

   if(newbar(rt[1].time)==false)
      return;

Полный код готового эксперта находится в файле moving_average_lc.mq5.


4.2. Эксперт, торгующий по паттерну "пин бар"

Пин бар, или бар Пиноккио - это паттерн из трех баров. Средний бар должен иметь длинную тень, так называемый "нос", который указывает на вероятный разворот движения цены. Крайние бары называют "глаза". Их экстремумы не должны выступать за тень среднего бара. Этот паттерн широко популярен среди трейдеров, торгующих по свечным моделям.

Наш пин бар должен удовлетворять следующим условиям (для разворота движения цены вниз):

  • Бар r[0] должен быть бычьим.
  • Бар r[2] должен быть медвежьим.
  • Большее из значений цены A и C не должно превышать B, где A и C - значения High баров r[0] и r[2] соответственно, а B - цена High бара r[1].
  • Тело среднего бара, то есть модуль разницы Open-Close (на рисунке - OC) бара r[1], не должно превышать количество пунктов, заданное внешним параметром.
  • Тень среднего бара, то есть разница цены High и большего из значений Open и Close бара r[1], не должна быть меньше количества пунктов, заданного внешним параметром.
  • Соотношение тени среднего бара к его телу должно быть не меньше значения, заданного внешним параметром.

Проверку паттерна будем производить в момент открытия бара r[3].

Пинбар

Рис. 7. Паттерн "Пин бар"

Код, определяющий наличие пин бара для разворота вниз, будет иметь следующий вид:

   if(r[0].open<r[0].close && r[2].open>r[2].close && r[1].high>MathMax(r[0].high,r[2].high))
     {
     //--- глаза верхнего пин бара
      double oc=MathAbs(r[1].open-r[1].close)/_Point;
      if(oc>inp_pb_max_OC)
         return(0);
      double shdw=(r[1].high-MathMax(r[1].open,r[1].close))/_Point;
      if(shdw<inp_pb_min_shdw)
         return(0);
      if(oc!=0)
        {
         if((shdw/oc)<inp_pb_min_ratio)
            return(0);
        }
      return(1);
     }

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

int IsPinbar(MqlRates &r[])
  {
   //--- в массиве r[] должно быть 4 значения
   if(ArraySize(r)<4)
      return(0);
   if(r[0].open<r[0].close && r[2].open>r[2].close && r[1].high>MathMax(r[0].high,r[2].high))
     {
      //--- глаза верхнего пин бара
      double oc=MathAbs(r[1].open-r[1].close)/_Point;
      if(oc>inp_pb_max_OC)
         return(0);
      double shdw=(r[1].high-MathMax(r[1].open,r[1].close))/_Point;
      if(shdw<inp_pb_min_shdw)
         return(0);
      if(oc!=0)
        {
         if((shdw/oc)<inp_pb_min_ratio)
            return(0);
        }
      return(1);
     }
   else if(r[0].open>r[0].close && r[2].open<r[2].close && r[1].low<MathMin(r[0].low,r[2].low))
     {
      //--- глаза нижнего пин бара
      double oc=MathAbs(r[1].open-r[1].close)/_Point;
      if(oc>inp_pb_max_OC)
         return(0);
      double shdw=(MathMin(r[1].open,r[1].close)-r[1].low)/_Point;
      if(shdw<inp_pb_min_shdw)
         return(0);
      if(oc!=0)
        {
         if((shdw/oc)<inp_pb_min_ratio)
            return(0);
        }
      return(-1);
     }
   return(0);
  }

Передаваемый массив исторических данных не должен иметь менее четырех элементов. В случае нахождения верхнего пин бара (то есть пин бара, предполагающего разворот вниз) функция вернет значение 1. В случае нахождения нижнего пин бара (предполагается разворот вверх) функция вернет значение -1. Если пин баров не обнаружено, функция вернет ноль. Функция также использует следующие входные параметры:

input uint   inp_pb_min_shdw     = 40;    // Pinbar min shadow, point
input uint   inp_pb_max_OC       = 20;    // Pinbar max OC, point
input double inp_pb_min_ratio    = 2.0;   // Pinbar shadow to OC min ratio

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

За основу для советника, торгующего по паттерну "пин бар", возьмем наш советник, торгующий по скользящим средним. Для начала, из него нужно удалить функцию CopyMABuffer(), а также ее вызов из функций CheckForOpen() и CheckForClose(). Количество запрашиваемых исторических данных увеличиваем с двух до четырех, а для проверки открытия нового бара будем использовать время бара r[3]:

   int copied;
   if(LC_on==true)
   {
      int shift = LC_shift;
      copied=GetRatesLC(0,4,rt,BaseTF,shift);
   }
   else
      copied = CopyRates(_Symbol,_Period,0,4,rt);
   if(copied!=4)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }
   if(newbar(rt[3].time)==false)
      return;

Проверка сигнала для открытия позиции будет иметь следующий вид:

   int pb=IsPinbar(rt);
   if(pb==1)       // верхний пин бар
      signal=ORDER_TYPE_SELL; // sell conditions
   else if(pb==-1) // нижний пин бар
      signal=ORDER_TYPE_BUY// buy conditions

Для закрытия позиции по встречному пин бару:

   if(type==(long)POSITION_TYPE_BUY && pb==1)
      signal=true;
   if(type==(long)POSITION_TYPE_SELL && pb==-1)
      signal=true;

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

В связи с этим, добавим уровни Take Profit и Stop Loss. Задавать их будем внешними параметрами inp_tp_pp и  inp_sl_pp соответственно:

   double sl=0,tp=0,p=0;
   double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
   if(signal==ORDER_TYPE_SELL)
   {
     p=bid;
     if(inp_sl_pp!=0)
       sl=NormalizeDouble(ask+inp_sl_pp*_Point,_Digits);
     if(inp_tp_pp!=0)
       tp=NormalizeDouble(ask-inp_sl_pp*_Point,_Digits);
   } else {
     p=ask;
     if(inp_sl_pp!=0)
       sl=NormalizeDouble(bid-inp_sl_pp*_Point,_Digits);
     if(inp_tp_pp!=0)
       tp=NormalizeDouble(bid+inp_sl_pp*_Point,_Digits);
   }
   CTrade trade;
   trade.PositionOpen(_Symbol,signal,TradeSizeOptimized(),p,sl,tp);

Если значение inp_tp_pp или inp_sl_pp равно нулю, то соответствующий уровень Take Profit или Stop Loss выставляться не будет.

Доработки выполнены, советник готов. Полный код содержится в файле pinbar_lc.mq5.


5. Оптимизация экспертов

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

Оптимизация будет проводиться по котировкам с сервера MetaQuotes-Demo на интервале за последние полгода. Участвовать в эксперименте будут пары EURUSD, GBPUSD и USDJPY. Начальный депозит 3000 USD, плечо 1:100. Режим тестирования - все тики. Режим оптимизации - быстрая (генетический алгоритм), Balance Max.


5.1. Обзор результатов оптимизации эксперта, торгующего по скользящим средним

Сравним результаты оптимизации эксперта при его работе в разных режимах: без смещения, со статическим смещением, и с динамическим (DSO и DSC).

Тестирование будем проводить на парах EURUSD, GBPUSD и USDJPY, на участке 2014.04.01 - 2014.10.25 (последние полгода). Период H1.

Входные параметры эксперта:

Параметр
Значение
 Maximum Risk in percentage
 0.1
 Decrease factor
 3.0
 Moving Average period
 12
 Moving Average shift
 6
 BaseTF
 1 Minute
 LC_on
 true
 LC_shift
 0

Табл. 3. Входные параметры эксперта Moving Average LC

5.1.1. Оптимизация эксперта в режиме с отключенным смещением

Оптимизируемые параметры:

Параметр
 Старт ШагСтоп
 Moving Average period
 12
 1
 90
 Moving Average shift
 6
 1
 30

Табл. 4. Оптимизируемые параметры эксперта Moving Average LC в режиме без смещения

График оптимизации эксперта в режиме с отключенным смещением, пара EURUSD:

Оптимизация в режиме без смещения, EURUSD

Рис. 8. Оптимизация эксперта Moving Average LC в режиме без смещения, пара EURUSD

Лучшие результаты:

 Результат
 ПрибыльПросадка %
Всего трейдов
MovingPeriod MovingShift
 3796,43 796,43 16,18 111 24 12
 3776,98 776,98 17,70 77 55
 22
 3767,45 767,45 16,10 74 59
 23
 3740,38 740,38 15,87 78 55
 17
 3641,16 641,16 15,97 105 12
 17

Табл. 5. Лучшие результаты оптимизации эксперта Moving Average LC на паре EURUSD в режиме без смещения

График оптимизации эксперта в режиме с отключенным смещением, пара GBPUSD:

Оптимизация в режиме без смещения, GBPUSD

Рис. 9. Оптимизация эксперта Moving Average LC в режиме без смещения, пара GBPUSD

Лучшие результаты:

 Результат ПрибыльПросадка %
 Всего трейдов
 MovingPeriodMovingShift
 4025,75 1025,75 8,08 80 18
 22
 3857,90 857,90 15,04 74 55
 13
 3851,40 851,40 18,16 80 13
 24
 3849,48 849,48 13,05 69 34
 29
 3804,70 804,70 16,57 137 25
 8

Табл. 6. Лучшие результаты оптимизации эксперта Moving Average LC на паре GBPUSD в режиме без смещения

График оптимизации эксперта в режиме с отключенным смещением, пара USDJPY:

Оптимизация в режиме без смещения, USDJPY

Рис. 10. Оптимизация эксперта Moving Average LC в режиме без смещения, пара USDJPY

Лучшие результаты:

Результат
Прибыль
Просадка %
Всего трейдов
 MovingPeriod MovingShift
5801,632801,6311,5448
65
23
5789,172789,1714,0350
44
27
5539,062539,0617,1446
67
27
5331,342331,3415,0561
70
9
5045,192045,1912,6148
83
15

Табл. 7. Лучшие результаты оптимизации эксперта Moving Average LC на паре USDJPY в режиме без смещения

5.1.2. Оптимизация эксперта в режиме со статическим смещением

Оптимизируемые параметры:

Параметр
 Старт ШагСтоп
 Moving Average period
 12
 1
 90
 Moving Average shift
 6
 1
 30
 LC_shift 1 1 59

Табл. 8. Оптимизируемые параметры эксперта Moving Average LC в режиме со статическим смещением

График оптимизации эксперта в режиме статического смещения, пара EURUSD:

Оптимизация в режиме статического смещения, EURUSD

Рис. 11. Оптимизация эксперта Moving Average LC в режиме статического смещения, пара EURUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
MovingPeriod
MovingShift
LC_shift
 4385,06
 1385,06
 12,87 100 32 11 8
 4149,63
 1149,63
 14,22 66 77 25 23
 3984,92
 984,92
 21,52 122 12 11 26
 3969,35
 969,35
 16,08 111 32 11 24
 3922,95
 922,95
 12,29 57 77 25 10

Табл. 9. Лучшие результаты оптимизации эксперта Moving Average LC на паре EURUSD в режиме статического смещения

График оптимизации эксперта в режиме статического смещения, пара GBPUSD:

Оптимизация в режиме статического смещения, GBPUSD

Рис. 12. Оптимизация эксперта Moving Average LC в режиме статического смещения, пара GBPUSD

Лучшие результаты:

 Результат ПрибыльПросадка %
Всего трейдов
 MovingPeriod MovingShiftLC_shift
 4571,07 1571,07 14,90 79 12
 25
 42
 4488,90 1488,90 15,46 73 12
 25
 47
 4320,31 1320,31 9,59 107 12
 16
 27
 4113,47 1113,47 10,96 75 12
 25
 15
 4069,21 1069,21 15,27 74 12
 25
 50

Табл. 10. Лучшие результаты оптимизации эксперта Moving Average LC на паре GBPUSD в режиме статического смещения

График оптимизации эксперта в режиме статического смещения, пара USDJPY:

Оптимизация в режиме статического смещения, USDJPY

Рис. 13. Оптимизация эксперта Moving Average LC в режиме статического смещения, пара USDJPY

Лучшие результаты:

Результат
Прибыль
Просадка %
Всего трейдов
MovingPeriod
 MovingShiftLC_shift
 6051,39 3051,39 15,94 53
 76
 12
 31
 5448,98 2448,98 10,71 54
 44
 30
 2
 5328,15 2328,15 11,90 50
 82
 13
 52
 5162,82 2162,82 10,46 71
 22
 26
 24
 5154,71 2154,71 14,34 54
 75
 14
 58

Табл. 11. Лучшие результаты оптимизации эксперта Moving Average LC на паре USDJPY в режиме статического смещения

5.1.3. Оптимизация эксперта в режиме с динамическим смещением

Оптимизируемые параметры:

Параметр
 Старт ШагСтоп
 Moving Average period
 12
 1
 90
 Moving Average shift
 6
 1
 30
 LC_shift -2 1 -1

Табл. 12. Оптимизируемые параметры эксперта Moving Average LC в режиме с динамическим смещением

График оптимизации эксперта в режиме динамического смещения, EURUSD:

Оптимизация в режиме динамического смещения, EURUSD

Рис. 14. Оптимизация эксперта Moving Average LC в режиме динамического смещения, пара EURUSD

Лучшие результаты:

Результат
Прибыль
Просадка %
Всего трейдов
MovingPeriod
MovingShift
LC_shift
 3392,64 392,64 27,95 594 15 13 -2
 3140,26 140,26 23,35 514 12 17 -2
 2847,12 -152,88 17,04 390 79 23 -1
 2847,12 -152,88 17,04 390 79 12 -1
 2826,25 -173,75 20,12 350 85 22 -1

Табл. 13. Лучшие результаты оптимизации эксперта Moving Average LC на паре EURUSD в режиме динамического смещения

График оптимизации эксперта в режиме динамического смещения, GBPUSD:

Оптимизация в режиме динамического смещения, GBPUSD

Рис. 15. Оптимизация эксперта Moving Average LC в режиме динамического смещения, пара GBPUSD

Лучшие результаты:

 РезультатПрибыль
 Просадка %
Всего трейдов
MovingPeriod
 MovingShiftLC_shift
 5377,58 2377,58 19,73 391 12
 26
 -2
 3865,50 865,50 18,18 380 23
 23
 -2
 3465,63 465,63 21,22 329 48
 21
 -2
 3428,99 428,99 24,55 574 51
 16
 -1
 3428,99 428,99 24,55 574 51
 15
 -1

Табл. 14. Лучшие результаты оптимизации эксперта Moving Average LC на паре GBPUSD в режиме динамического смещения

График оптимизации эксперта в режиме динамического смещения, USDJPY:

Оптимизация в режиме динамического смещения, USDJPY

Рис. 16. Оптимизация эксперта Moving Average LC в режиме динамического смещения, пара USDJPY

Лучшие результаты:

Результат
Прибыль
Просадка %
 Всего трейдов
MovingPeriod
MovingShift
 LC_shift
 6500,19 3500,19 17,45 244
 42
 28
 -2
 6374,18 3374,18 19,91 243
 54
 24
 -2
 6293,29 3293,29 19,30 235
 48
 27
 -2
 5427,69 2427,69 17,65 245
 90
 8
 -2
 5421,83 2421,83 16,30 301
 59
 12
 -2

Табл. 15. Лучшие результаты оптимизации эксперта Moving Average LC на паре USDJPY в режиме динамического смещения

5.2. Обзор результатов оптимизации эксперта, торгующего по патерну "пин бар"

Сравним результаты оптимизации эксперта при его работе в разных режимах: без смещения, со статическим смещением, и с динамическим (DSO и DSC). Тестирование будет проводиться на парах EURUSD, GBPUSD и USDJPY, на участке 2014.04.01 - 2014.10.25. Период H1.

Входные параметры эксперта:

 ПараметрЗначение
Maximum Risk in percentage
0.1
Descrease factor
3.0
Pinbar min shadow, points
40
Pinbar max OC, points
110
Pinbar shadow to OC min ratio
1.4
SL, points (0 for OFF)
150
TP, points (0 for OFF)
300
LC Base Period
1 Minute
LC mode ON
true
LC shift
0

Табл. 16. Входные параметры эксперта Pinbar LC

Оптимизировать будем параметры, характеризующие геометрию пин бара. Такие, как длина "носа", отношение длины "носа" к телу среднего бара и максимальный размер тела. Также, будем оптимизировать уровни Take Profit и Stop Loss.


5.2.1. Оптимизация эксперта в режиме с отключенным смещением

Оптимизируемые параметры:

 Параметр Старт Шаг Стоп
Pinbar min shadow, points
100
20
400
Pinbar max OC, points
20
20
100
Pinbar shadow to OC min ratio
1
0.2
3
SL, points (0 for OFF)
150
50
500
TP, points (0 for OFF)
150
50
500

Табл. 17. Оптимизируемые параметры эксперта Pinbar LC в режиме с отключенным смещением

График оптимизации эксперта в режиме с отключенным смещением, пара EURUSD:

Оптимизация без смещения, EURUSD

Рис. 17. Оптимизация эксперта Pinbar LC в режиме без смещения, пара EURUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP
 3504,59
 504,59
 9,82
 33
 100
 60
 1.8
 450
 500
 3428,89
 428,89
 8,72
 21
 120
 60
 2.8
 450
 350
 3392,37
 392,37
 9,94
 30
 100
 60
 2,6
 450
 250
 3388,54
 388,54
 9,93
 31
 100
 80
 2,2
 450
 300
 3311,84
 311,84
 6,84
 13
 140
 60
 2,2
 300
 450

Табл. 18. Лучшие результаты оптимизации эксперта Pinbar LC на паре EURUSD в режиме без смещения

График оптимизации эксперта в режиме с отключенным смещением, пара GBPUSD:

Оптимизация без смещения, GBPUSD

Рис. 18. Оптимизация эксперта Pinbar LC в режиме без смещения, пара GBPUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP
 3187,13
 187,13
 11,10
 13
 160
 60
 2,6
 500
 350
 3148,73
 148,73
 3,23
 4
 220
 40
 2,8
 400
 400
 3142,67
 142,67
 11,27
 17
 160
 100
 1,8
 500
 350
 3140,80
 140,80
 11,79
 13
 180
 100
 2
 500
 500
 3094,20
 94,20
 1,62
 1
 260
 60
 1,6
 500
 400

Табл. 19. Лучшие результаты оптимизации эксперта Pinbar LC на паре GBPUSD в режиме без смещения

График оптимизации эксперта в режиме с отключенным смещением, пара USDJPY:

Оптимизация без смещения, USDJPY

Рис. 19. Оптимизация эксперта Pinbar LC в режиме без смещения, пара USDJPY

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP
 3531,99
 531,99
 9,00
 6
 160
 60
 2.2
 450
 500
 3355,91
 355,91
 18,25
 16
 120
 60
 1,6
 450
 400
 3241,93
 241,93
 9,11
 4
 160
 40
 2,8
 450
 500
 3180,43
 180,43
 6,05
 33
 100
 80
 1,8
 150
 450
 3152,97
 152,97
 3,14
 6
 160
 80
 2,8
 150
 500

Табл. 20. Лучшие результаты оптимизации эксперта Pinbar LC на паре USDJPY в режиме без смещения

5.2.2. Оптимизация эксперта в режиме со статическим смещением

Оптимизируемые параметры:

 Параметр Старт Шаг Стоп
 Pinbar min shadow, points
 100
 20
 400
 Pinbar max OC, points
 20
 20
 100
 Pinbar shadow to OC min ratio
 1
 0.2
 3
 SL, points (0 for OFF)
 150
 50
 500
 TP, points (0 for OFF)
 150
 50
 500
 LC shift
 1 1 59

Табл. 21. Оптимизируемые параметры эксперта Pinbar LC в режиме со статическим смещением

График оптимизации эксперта в режиме статического смещения, пара EURUSD:

Оптимизация в режиме статического смещения, EURUSD

Рис. 20. Оптимизация эксперта Pinbar LC в режиме статического смещения, пара EURUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP LC shift
 4843,54
 1843,54
 10,14
 19
 120
 80
 1,6
 500
 500
 23
 4714,81
 1714,81
 10,99
 28
 100
 100
 1,6
 500
 500
 23
 4672,12
 1672,12
 10,16
 18 120
 80
 1,8
 500
 500
 23
 4610,13
 1610,13
 9,43
 19
 120
 80
 1,6
 450
 450
 23
 4562,21
 1562,21
 13,94
 27
 100
 100
 1,6
 500
 400
 25

Табл. 22. Лучшие результаты оптимизации эксперта Pinbar LC на паре EURUSD в режиме статического смещения

График оптимизации эксперта в режиме статического смещения, пара GBPUSD:

Оптимизация в режиме статического смещения, GBPUSD

Рис. 21. Оптимизация эксперта Pinbar LC в режиме статического смещения, пара GBPUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP LC shift
 4838,10
 1838,10
 5,60
 34
 100
 40
 2,4
 450
 500
 24
 4797,09
 1797,09
 5,43
 35
 100
 40
 2,6
 400
 500
 24
 4755,57
 1755,57
 7,36
 42
 100
 100
 2
 400
 500
 24
 4725,41
 1725,41
 8,35
 45
 100
 80
 1
 400
 500
 24
 4705,61
 1705,61
 8,32
 41
 100
 100
 2
 450
 500
 24

Табл. 23. Лучшие результаты оптимизации эксперта Pinbar LC на паре GBPUSD в режиме статического смещения

График оптимизации эксперта в режиме статического смещения, пара USDJPY:

Оптимизация в режиме статического смещения, USDJPY

Рис. 22. Оптимизация эксперта Pinbar LC в режиме статического смещения, пара USDJPY

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP LC shift
 4108,83
 1108,83
 6,45
 9
 140
 40
 1,4
 500
 450
 55
 3966,74
 966,74
 7,88
 12
 140
 60
 2,8
 450
 500
 45
 3955,32
 955,32
 9,91
 21
 120
 80
 2
 500
 500
 45
 3953,80
 953,80
 6,13
 10
 140
 60
 2,8
 450
 450
 47
 3944,33
 944,33
 6,42
 6
 160
 100
 2,6
 500
 400
 44

Табл. 24. Лучшие результаты оптимизации эксперта Pinbar LC на паре USDJPY в режиме статического смещения

5.2.3. Оптимизация эксперта в режиме с динамическим смещением

Оптимизируемые параметры:

 Параметр Старт Шаг Стоп
 Pinbar min shadow, points
 100
 20
 400
 Pinbar max OC, points
 20
 20
 100
 Pinbar shadow to OC min ratio
 1
 0.2
 3
 SL, points (0 for OFF)
 150
 50
 500
 TP, points (0 for OFF)
 150
 50
 500
 LC shift
 -2 1 -1

Табл. 25. Оптимизируемые параметры эксперта Pinbar LC в режиме с динамическим смещением

График оптимизации эксперта в режиме динамического смещения, пара EURUSD:

Оптимизация в режиме динамического смещения, EURUSD

Рис. 23. Оптимизация эксперта Pinbar LC в режиме динамического смещения, пара EURUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP LC shift
 4185,65
 1185,65
 13,22
 49
 200
 100
 1,8
 450
 500
 -2
 4011,80
 1011,80
 13,75
 49
 200
 100
 2
 400
 500
 -2
 3989,28
 989,28
 12,01
 76
 140
 20
 1,2
 350
 200
 -1
 3979,50
 979,50
 16,45
 157
 100
 20
 1
 450
 500
 -1
 3957,25
 957,25
 16,68
 162
 100
 20
 1
 400
 500
 -1

Табл. 26. Лучшие результаты оптимизации эксперта Pinbar LC на паре EURUSD в режиме динамического смещения

График оптимизации эксперта в режиме динамического смещения, пара GBPUSD:

Оптимизация в режиме динамического смещения, GBPUSD

Рис. 24. Оптимизация эксперта Pinbar LC в режиме динамического смещения, пара GBPUSD

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP LC shift
 4906,84
 1906,84
 10,10
 179
 120
 40
 1,8
 500
 500
 -2
 4316,46
 1316,46
 10,71
 151
 120
 20
 2,4
 450
 500
 -1
 4250,96
 1250,96
 12,40
 174
 120
 40
 1,8
 500
 500
 -1
 4040,82
 1040,82
 12,40
 194
 120
 60
 2
 500
 200
 -2
 4032,85
 1032,85
 11,70
 139
 140
 40
 2
 400
 200
 -1

Табл. 27. Лучшие результаты оптимизации эксперта Pinbar LC на паре GBPUSD в режиме динамического смещения

График оптимизации эксперта в режиме динамического смещения, пара USDJPY:

Оптимизация в режиме динамического смещения, USDJPY

Рис. 25. Оптимизация эксперта Pinbar LC в режиме динамического смещения, пара USDJPY

Лучшие результаты:

Результат
Прибыль
 Просадка %
 Всего трейдов
 Pinbar min shadow
 Pinbar max OC
 Pinbar shadow
to OC min ratio
 SL TP LC shift
 5472,67
 2472,67
 13,01
 138
 100
 20
 2,4
 500
 500
 -1
 4319,84
 1319,84
 15,87
 146
 100
 20
 2,2
 400
 500
 -1
 4259,54
 1259,54
 19,71
 137
 100
 20
 2,4
 500
 500
 -2
 4197,57
 1197,57
 15,98
 152
 100
 20
 1
 350
 500
 -1
 3908,19
 908,19
 16,79
 110
 120
 40
 3
 400
 400
 -1

Табл. 28. Лучшие результаты оптимизации эксперта Pinbar LC на паре USDJPY в режиме динамического смещения


6. Сравнение результатов оптимизации

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


6.1. Эксперт, торгующий по скользящим средним

Прибыль:

 Без смещения
 Статическое
смещение
Динамическое
смещение
 EURUSD
 796,43
 1385,06 (+74%)
 392,64 (-51%)
 GBPUSD
 1025,75
 1571,07 (+53%)
 2377,58 (+132%)
 USDJPY
 2801,63
 3051,39 (+9%)
 3500,19 (+25%)

Табл. 29. Сравнение максимальных значений прибыли из таблиц лучших результатов оптимизации эксперта Moving Average LC

Просадка:

 Без смещения
 Статическое
смещение
Динамическое
смещение
 EURUSD
 17,7
 21,52 (+22%)   
 27,95 (+58%)      
 GBPUSD
 18,16
 15,46 (-15%)
 24,55 (+35%)
 USDJPY
 17,14
 15,94 (-7%)
 19,91 (+16%)

Табл. 30. Сравнение максимальных значений просадки из таблиц лучших результатов оптимизации эксперта Moving Average LC

Всего трейдов:

 Без смещения
 Статическое
смещение
Динамическое
смещение
 EURUSD
 111
 122 (+10%)     
 594 (+435%)       
 GBPUSD
 137
 107 (-22%)
 574 (+319%)
 USDJPY
 61
 71 (+16%)
 301 (+393%)

Табл. 31. Сравнение максимальных значений количества трейдов из таблиц лучших результатов оптимизации эксперта Moving Average LC

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

Режим статического смещения для данного советника более благоприятный. Мы видим уменьшение просадки по парам GBPUSD и USDJPY, а также заметное увеличение прибыли для EURUSD и GBPUSD.


6.2. Эксперт, торгующий по патерну "пин бар"

Прибыль:

 Без смещения
 Статическое
смещение
Динамическое
смещение
 EURUSD
504,59
1843,54 (+265%)
1185,65 (+135%)
 GBPUSD
187,13
1838,10 (+882%)
1906,84 (+919%)
 USDJPY
531,99
1108,83 (+108%)2472,67 (+365%)

Табл. 32. Сравнение максимальных значений прибыли из таблиц лучших результатов оптимизации эксперта Pinbar LC

Просадка:

 Без смещения
 Статическое
смещение
Динамическое
смещение
 EURUSD
9,94
13,94 (+40%)
16,68 (+68%)
 GBPUSD
11,79
8,35 (-29%)
12,4 (+5%)
 USDJPY
18,25
9,91 (-46%)
19,71 (+8%)

Табл. 33. Сравнение максимальных значений просадки из таблиц лучших результатов оптимизации эксперта Pinbar LC

Всего трейдов:

 Без смещения
 Статическое
смещение
Динамическое
смещение
 EURUSD
33
28 (-15%)
162 (+391%)
 GBPUSD
17
45 (+165%)
194 (+1041%)
 USDJPY
33
21 (-36%)
152 (+361%)

Табл. 34. Сравнение максимальных значений количества трейдов из таблиц лучших результатов оптимизации эксперта Pinbar LC

Здесь также наблюдаем существенное увеличение количества трейдов в режиме динамического смещения. Но столь значительное увеличение просадки, как наблюдалось в подобном случае для эксперта Moving Average LC, здесь наблюдается только для пары EURUSD. Для остальных пар просадка увеличилась незначительно, на 5-8 процентов.

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


Заключение

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

Отсюда можно сделать следующие выводы:

  • Для экспертов, использующих индикаторные стратегии (например, торгующих по скользящим средним), больше подходит режим статического смещения. Он дает более точный вход в рынок, за счет чего достигается уменьшение просадки и увеличение прибыли.
  • Для экспертов, использующих торговлю по паттернам, больше подходит режим динамического сдвига. Он значительно повышает количество точек входа, однако, вместе с этим вырастает и просадка.
  • Режим динамического сдвига при объединении с хорошо организованным мани-менеджментом может дать очень неплохие результаты.
  • Режим статического сдвига, при всей его привлекательности для индикаторных стратегий, имеет один существенный недостаток: величина сдвига, дающего наилучший результат - это еще одна переменная в списке входных параметров, которую нужно угадать.

Прикрепленные файлы |
liquidchart.mqh (4.16 KB)
liquid_chart.mq5 (13.56 KB)
pinbar_lc.mq5 (9.28 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (33)
Stanislav Korotky
Stanislav Korotky | 5 авг 2015 в 10:35
Serhii Shevchuk:

Вот пример, где воскресный дневной бар состоит всего из одного часового. Никакой отсебятины, оригинальный график:

Теперь откроем часовой график и найдём тот самый бар, который сформировал воскресенье на дневном:

Но это похоже не тот случай - здесь воскресный бар есть в котировках самого брокера - и на дневке, и на H1, так что это не "фантом", созданный в индикаторе, а реальный бар.
Stanislav Korotky
Stanislav Korotky | 5 авг 2015 в 10:47
Serhii Shevchuk:

Добавляем сдвиг на 1 единицу базового периода. В данном случае, это 1 час. Теперь все бары результирующего графика будут перестроены. Сутки будут начинаться не в 00:00:00, а в 01:00:00. Таким образом, бар N откроется в 01:00:00 2015.08.03, бар N+1 в 01:00:00 2015.08.04, бар N+2 откроется в 01:00:00 2015.08.05, и так далее. Но у нас есть данные за время с 00:00:00 до 01:00:00. Мы их не можем выбросить, поэтому их них формируется бар за воскресенье. 

Всё логично: если, учитывая сдвиг, наш синтетический "день" теперь начинается в 01:00:00, то заканчиваться должен через 24 часа, то есть в 00:59:59 следующего календарного дня. Данные за воскресенье мы не может добавить в пятничный бар, поскольку, разрыв между временами открытия баров базового периода больше суток.

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

У себя я считал по описанному мной выше алгоритму (отсчет сдвига от начала одного бара текущего тф до следующего), то есть если продолжать этот же пример и нужен сдвиг в 1 час, то в бар пятницы попадет все от 1:00 пятницы до 1:00 понедельника. Обоснование простое - пятница и понедельник - соседние бары в текущем периоде, там нет никаких воскресений, и потому не может быть в индикаторе.

Serhii Shevchuk
Serhii Shevchuk | 5 авг 2015 в 11:00
Stanislav Korotky:
Но это похоже не тот случай - здесь воскресный бар есть в котировках самого брокера - и на дневке, и на H1, так что это не "фантом", созданный в индикаторе, а реальный бар.
А чем воскресный бар, созданный в индикаторе, хуже воскресного бара в котировках брокера? Если, сдвигая время открытия, получаем синтетику, то на неё распространяются те же правила. Если есть данные за час до начала понедельника, то из них формируется воскресенье, и никак иначе. То, что при этом полученный график уползает от соответствующих баров исходного графика - вполне нормально.
Serhii Shevchuk
Serhii Shevchuk | 5 авг 2015 в 11:02

Stanislav Korotky:

Обоснование простое - пятница и понедельник - соседние бары в текущем периоде, там нет никаких воскресений, и потому не может быть в индикаторе.

Здесь я категорически не согласен, но спорить нет желания.
Stanislav Korotky
Stanislav Korotky | 5 авг 2015 в 11:18
Serhii Shevchuk:
А чем воскресный бар, созданный в индикаторе, хуже воскресного бара в котировках брокера? Если, сдвигая время открытия, получаем синтетику, то на неё распространяются те же правила. Если есть данные за час до начала понедельника, то из них формируется воскресенье, и никак иначе. То, что при этом полученный график уползает от соответствующих баров исходного графика - вполне нормально.

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

А инидкатор имеет привязку к котировкам, должен быть синхронизирован с ними. Наличие фантомов привязку нарушает. Это как минимум неудобно.

Но пусть каждый сам для себя решает, что лучше.

Почему виртуальный хостинг в платформах MetaTrader 4 и MetaTrader 5 лучше обычных VPS Почему виртуальный хостинг в платформах MetaTrader 4 и MetaTrader 5 лучше обычных VPS

Сеть Virtual Hosting Cloud разработана специально для MetaTrader 4 и MetaTrader 5 и обладает всеми преимуществами родного решения. Арендуйте виртуальный сервер прямо сейчас и протестируйте его работу - мы даем 24 бесплатных часа!

Основы  программирования на MQL5 - Глобальные переменные терминала Основы программирования на MQL5 - Глобальные переменные терминала

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

Нейросети бесплатно и сердито - соединяем NeuroPro и MetaTrader 5 Нейросети бесплатно и сердито - соединяем NeuroPro и MetaTrader 5

Если специализированные нейросетевые программы для трейдинга вам кажутся дорогими и сложными (или наоборот - примитивными), то попробуйте NeuroPro - она на русском языке, бесплатна и содержит оптимальный набор возможностей для любителей. О том, как использовать ее с MetaTrader 5, вы узнаете из этой статьи.

Третье поколение нейросетей: "Глубокие нейросети" Третье поколение нейросетей: "Глубокие нейросети"

Статья посвящена новому и очень перспективному направлению в машинном обучении — так называемому "глубокому обучению" и конкретней "глубоким нейросетям". Сделан краткий обзор нейросетей 2 поколения, их архитектуры связей и основных видов, методов и правил обучения и их основных недостатков. Далее рассмотрена история появления и развития нейросетей 3 поколения, их основные виды, особенности и методы обучения. Проведены практические эксперименты по построению и обучению на реальных данных глубокой нейросети, инициируемой весами накапливающего автоэнкодера. Рассмотрены все этапы от выбора исходных данных до получения метрик. В последней части статьи приведена программная реализация глубокой нейросети в виде индикатора-эксперта на MQL4/R.