тел.: 8 800 200 86 47|+7 (812) 336 61 11Заказать звонок
Admiral Markets UK Admiral Markets UK Choose your country

Утренний флэт

Индикатор MorningFlat_OpenLevel

Советник MorningFlat_OpenLevel_Expert

Файлы стратегии для AutoGraf 4.0

Развернутые результаты тестирования эксперта

 

    В канун Нового Года, как и полагается, рабочее настроение улетучивается. Направление мыслей при этом тоже соответствующее. У кого-то они греются под жарким солнцем на берегу Индийского океана, у кого-то в заснеженных Альпах стремглав несутся к подножию Монблана. А у кого-то мысли более спокойные. Ведь все можно устроить все по старинке, в семейном кругу спокойно и непринужденно открыть бутылочку "Советского", наслаждаясь теплом и уютом родного дома.

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

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

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

    В итоге получаем три значения:

  • количество свечей, находящихся в верхней части канала (число на рис. 1, расположенное под бирюзовой линией);

  • количество свечей, находящихся в нижней части канала (число расположено под красной линией);

  • количество центральных свечей (указано под синей пунктирной линией).

Рис. 1. - Общий вид индикатора MorningFlat_OpenLevel и стратегия торговли на его основе.

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

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

    Начало и окончание утреннего флэта может быть изменено и указано с точностью до минут. Это делается при помощи установки нужных значений в параметрах индикатора MorningFlat_OpenLevel:

  • StartHour - час начала диапазона.

  • StartMinute - минуты начала диапазона. Свеча, соответствующая времени StartHour:StartMinute открывает канал.

  • EndHour - час окончания диапазона.

  • EndMinute - минуты окончания диапазона. Свеча, соответствующая времени EndHour:EndMinute является первой, которая не является частью канала утреннего флэта.

Параметр TargetLevel не относится к стратегии. Его индикатор унаследовал от старшего брата - индикатора MorningFlat_V3. Оставлен для удобства пользователей.

Вернемся непосредственно к стратегии и опишем ее сигнальную часть в функции GetSignal:

 
//+-------------------------------------------------------------------------------------+
//| Расчет границ канала и подсчет баров ниже и выше линии открытия                     |
//+-------------------------------------------------------------------------------------+
void GetSignal()
{
 Signal = 0;
// - 1 - ====================== Получение значений границ канала ========================
 // Бар, соответсвующий началу суток плюс смещение в часах и минутах
 int StartBar = iBarShift(Symbol(), 0, BeginDay+StartHour*3600+StartMinute*60);
 // Бар, соответствующий последнему бару "утреннего флэта"
 int FinishBar = iBarShift(Symbol(), 0, BeginDay+EndHour*3600+EndMinute*60)+1; 
        
 double LowV = Low[iLowest(Symbol(), 0, MODE_LOW, StartBar-FinishBar+1,         // Нижняя
                   FinishBar)];                                         // граница канала
 double HighV = High[iHighest(Symbol(), 0, MODE_HIGH, StartBar-FinishBar+1,
                     FinishBar)];                               // Верхняя граница канала
 double OpenL = Open[StartBar];                                // Цена открытия диапазона
 double CloseL = Close[FinishBar];                             // Цена закрытия диапазона
 OpenAfterFlat = Open[FinishBar-1];                               // Цена открытия сделки
 int AboveBars = 0;                               // Закрытие и открытие свечи выше линии
 int BelowBars = 0;                               // Закрытие и открытие свечи ниже линии
 int CenterBars = 0;              // Закрытие и открытие свечи по разные стороны от линии
 for (int j = StartBar; j >= FinishBar; j--)
   {
    if (Open[j] >= OpenL && Close[j] >= OpenL)   // Подсчет баров, закрывшихся выше линии
      AboveBars++;
     else
      if (Open[j] <= OpenL && Close[j] <= OpenL) // Подсчет баров, закрывшихся ниже линии
        BelowBars++;
       else
        CenterBars++;  
   }
// - 1 - == Окончание блока =============================================================

// - 2 - == Генерация сигнала ===========================================================
 if (CloseL < OpenL && BelowBars > AboveBars+CenterBars)  // Цена закрытия диапазона ниже
            //  цены открытия диапазона и количество баров ниже цены открытия больше, чем
                                                       // количество всех остальных баров
   Signal = 1;                                                            // Открытие BUY
 
 if (CloseL > OpenL && AboveBars > BelowBars+CenterBars)  // Цена закрытия диапазона выше
            //  цены открытия диапазона и количество баров выше цены открытия больше, чем
                                                       // количество всех остальных баров
   Signal = -1;                                                          // Открытие SELL
// - 2 - == Окончание блока =============================================================
 return(True);
}

    Первый блок подготавливает данные. Сначала находятся номера баров, которые соответствуют первому и последнему бару, входящих в канал (StartBar и FinishBar). Рассчитываются они путем поиска бара, соответствующего времени открытия дневного бара, к которому добавлено необходимое количество часов и минут. Зная номера начального и конечного баров, не составляет особого труда найти между ними максимальное (HighV) и минимальное (LowV) значение цены. Еще проще находятся цены открытия (OpenL) и закрытия (CloseL) диапазона. Здесь же определяется рекомендуемая цена открытия сделки, которая равна цене открытия свечи, следующей за окончанием формирования утреннего флэта.

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

      Второй блок, как обычно, анализирует полученные данные и присваивает флагу Signal нужное значение. Для сигнала BUY требуется, чтобы цена закрытия диапазона была ниже цены открытия (CloseL < OpenL), а количество свечей, принадлежащих нижней части канала, было больше половины всех свечей канала (BelowBars > AboveBars+CenterBars).  Для сигнала SELL необходимо, чтобы цена закрытия диапазона была выше цены открытия (CloseL > OpenL), а количество свечей, принадлежащих верхней части канала, было больше половины всех свечей, составляющих канал (AboveBars > BelowBars+CenterBars).

После формирования сигналов открытия и закрытия можно приступать к их непосредственному использованию в функции start:

 
//+-------------------------------------------------------------------------------------+
//| Функция START эксперта                                                              |
//+-------------------------------------------------------------------------------------+
int start()
  {
// - 1 -  == Разрешено ли советнику работать? ===========================================
   if (!Activate || FatalError)             // Отключается работа советника, если функция
    return(0);           //  init завершилась с ошибкой  или имела место фатальная ошибка
// - 1 -  == Окончание блока ============================================================
     
// - 2 - == Сбор информации об условиях торговли ========================================
   Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point);                 // текущий спрэд
   StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point);  // текущий уровень стопов
// - 2 -  == Окончание блока ============================================================

// - 3 - ==================== Проверка срабатывания сигнала за текущий день =============
   BeginDay = iTime(Symbol(), PERIOD_D1, 0);
   if (LastOpen > BeginDay)
     return(0);
    else
     if (!CheckOpen())
       return(0);
// - 3 -  == Окончание блока ============================================================

// - 4 - =============== Расчет сигнала при окончании флэта =============================
   if (LastChannel < BeginDay && (Hour() > EndHour || 
       (Hour() == EndHour && Minute() > EndMinute)))
     {  
      GetSignal();
      LastChannel = BeginDay;
     } 
// - 4 -  == Окончание блока ============================================================

// - 5 - == Открытие позиций ============================================================
   if (Signal == 1 &&                            // Открытие BUY, если сигнал для покупки
       Bid <= OpenAfterFlat)     //и текущая цена лучше, чем цена открытия самого первого
     {                                            // бара после окончания утреннего флэта
      RefreshRates();
      double SL = ND(IF(StopLoss == 0, 0, Ask - StopLoss*Tick));
      double TP = ND(IF(TakeProfit == 0, 0, Ask + TakeProfit*Tick));
      if (OpenOrderCorrect(OP_BUY, ND(Ask), SL, TP, True) != 0)       // открытие позиции
        return(0);    // если не удалось открыть, то попытка переносится на следующий тик
     }

   if (Signal == -1 &&                          // Открытие SELL, если сигнал для продажи
       Bid >= OpenAfterFlat)     //и текущая цена лучше, чем цена открытия самого первого
     {                                            // бара после окончания утреннего флэта
      RefreshRates();
      SL = ND(IF(StopLoss == 0, 0, Bid + StopLoss*Tick));
      TP = ND(IF(TakeProfit == 0, 0, Bid - TakeProfit*Tick));
      if (OpenOrderCorrect(OP_SELL, ND(Bid), SL, TP, True) != 0)      // открытие позиции
        return(0);    // если не удалось открыть, то попытка переносится на следующий тик
     }
// - 5 -  == Окончание блока ============================================================

   return(0);
  }

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

    В третьем блоке сперва формируется значение времени открытия текущего дневного бара BeginDay, которое впоследствии также используется в функции GetSignal при подсчете времени начала и окончания диапазона утреннего флэта. Затем сравнивается время открытия последней совершенной сделки и время начала дня. Если последняя сделка была совершена в течение текущего дня, то функция start завершается досрочно. Этим приемом ограничивается до одной количество сделок в день.

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

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

    В пятом блоке открываются сделки. Делается это в соответствии со значением флага Signal. Причем в обоих случаях присутствует дополнительное условие (Bid <= OpenAfterFlat или Bid >= OpenAfterFlat). Это условие введено для ситуаций, когда трейдер не успел включить компьютер до времени окончания формирования утреннего флэта. В результате вход в сделку может произойти по худшей цене, чем предполагается в стратегии. Дополнительное условие как раз отслеживает момент возврата цены к нужному значению, на котором и открывается сделка.

    Оставшаяся функция CheckOpen довольно компактная:

 
//+-------------------------------------------------------------------------------------+
//| Проверка существования позиции и закрытие ее, если наступил следующий день          |
//| Также проверяется время окончания утреннего флэта                                   |
//+-------------------------------------------------------------------------------------+
bool CheckOpen()
{
 if (OrderSelect(LastTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
   if (WaitForTradeContext())
     {
      if (OrderType() == OP_BUY)
        double Price = Bid;
       else
        Price = Ask;
      if (!OrderClose(OrderTicket(), OrderLots(), ND(Price), 3))
        return(False);   
     }
 if (Hour() > EndHour || (Hour() == EndHour && Minute() > EndMinute))    
   return(True);
  else
   return(False); 
}

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

    Если сделки уже нет, то проверяется окончание формирования утреннего флэта. Только при этом условии CheckOpen вернет True. Иначе результат будет False.

   К тестированию эксперта подойдем через оптимизацию входных параметров. Поэтому приведенные на рис. 2 - 5 графики изменения кривых баланса являются уже окончательными результатами подбора параметров. Исторический промежуток выбран для всех пар одинаковый 01.01.2008 - 26.12.2009, равно как и таймфрейм - М15. Отличие составляют лишь значения TakeProfit и StopLoss.

    Для валютной пары EURUSD параметр TakeProfit выбран равным 45 пунктам, а StopLoss равен 170 пунктам.

              Рис. 2. - График кривой баланса, получаемый при тестировании советника на валютной паре EURUSD.

    Чистая прибыль добралась до отметки 1433 доллара, а максимальная просадка до 1169 долларов, что дало фактор восстановления чуть больше единицы (1.23). Прибыль была достигнута за счет доминирования прибыльных сделок над убыточными (68% против 32%). Можно взять на заметку.

     Для валютной пары USDCHF наилучшими оказались значения TakeProfit = 15, StopLoss = 95.

               Рис. 3. - График кривой баланса, получаемый при тестировании советника на валютной паре USDCHF.

    Чистая прибыль не смогла остаться в положительной зоне и составила -30 долларов при максимальной просадке 696 долларов. Поэтому дальнейшее рассмотрение результатов не является интересным.

    Валютная пара GBPUSD остановила свой выбор на таких параметрах: TakeProfit = 265, StopLoss = 230. Результат не заставил себя ждать.

               Рис. 4. - График кривой баланса, получаемый при тестировании советника на валютной паре GBPUSD.

       Чистая прибыль достигла рекордных 7445 долларов при скромной для такого результата максимальной просадке 1164 доллара. Фактор восстановления смог достичь отметки 6.40. В данном случае о доминировании прибыльных сделок над убыточными речь не идет. Хотя небольшой перевес в сторону прибыльных сделок и наблюдается - 56% против 44%. Стабильный вид кривой баланса дает все основания для доверия такой стратегии на GBPUSD.

        И, наконец, для USDJPY параметры подобраны такие: TakeProfit = 20, StopLoss = 90.

                Рис. 5. - График кривой баланса, получаемый при тестировании советника на валютной паре USDJPY.

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

Доработка стратегии для использования в AutoGraf 4.0

    Для поклонников AutoGraf по традиции произведем некоторые изменения в эксперте, чтобы он смог работать под управлением AG. В советнике присутствует четыре очень важных параметра - время начала и окончания действия диапазона утреннего флэта. Они должны быть настраиваемыми. Поэтому необходимо вынести их во внешние переменные AutoGraf. В результате, параметру StartHour будет соответствовать параметр AT_1, параметру StartMinute - AT_2, EndHour - AT_3 и EndMinute - AT_4.

    Остальные настройки эксперта (Lots, TakeProfit, StopLoss) доступны в AutoGraf в режиме реального времени и могут быть изменены в любой момент. В итоге для запуска советника из-под AutoGraf 4.0 потребуется проделать следующие шаги:

  • Воспользоваться ссылкой Файлы стратегий для Autograf 4.0 и полученный архив распаковать в папку MT4\experts\libraries.

  •  Запустить AutoGraf и во входных параметрах AT_1 - AT_4 указать необходимые значения. Например, для параметров по умолчанию: AT_1 = 0, AT_2 = 0, AT_3 = 8, AT_4 = 0.

  •  Для получения похожих с тестами результатов работы выставить объем открываемой позиции (Lots) 0.1, настроить правильные значения SL и TP. Например, для пары GBPUSD установить SL = 230, а TP= 265.

  • Выбрать стратегию №3. Для этого передвинуть вверх значок So и среди названий стратегий найти S3

  • Запустить функцию автоматической торговли, передвинув значок AT в верхнее положение.

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

    В заключение поздравляю всех с наступающим Новым Годом. Пусть в Новом Году все ваши планы осуществятся самым наилучшим образом, а удача, здоровье и любовь станут спутницами! До новых встреч в Новом Году.

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

Игорь Герасько

Декабрь 2009

Специально для компании Admiral Markets

2.333335
 
 
X
Loading