English 中文 Español Deutsch 日本語 Português
Ночная торговля в азиатскую сессию: как оставаться в прибыли

Ночная торговля в азиатскую сессию: как оставаться в прибыли

MetaTrader 5Трейдинг | 14 ноября 2017, 12:31
11 288 13
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Введение

Многие не раз сталкивались с понятием ночной торговли. Первое, что приходит на ум при знакомстве с этим понятием — то, что торговля осуществляется ночью. Но всё проще: из-за разницы в часовых поясах ночь в разных уголках мира наступает в разное время. Американская и европейская торговые сессии проходят в часовых поясах -4 и +1 к Всемирному координированному времени UTC, соответственно.

Позднее к мировым торгам подключаются азиатские и тихоокеанские биржи, чей часовой пояс противоположен американским и европейским коллегам. Здесь торговля начинается, когда американские трейдеры идут домой, а европейские уже ложатся спать. Это и есть ночная торговля в нашем понимании. Периоды торговых сессий условно можно изобразить на карте мира рисунок 1 (время идёт справа налево):


Рис.1. Торговые сессии на Мировой карте

Рис.1. Торговые сессии на мировой карте


Из вышесказанного следует, что ночная торговля в основном идёт во флэте на таких парах как: EUR/USD, GBP/USD, USD/CHF, USD/CAD, EUR/GBP, но проявляет немалую активность на парах: USD/JPY, GBP/JPY, AUD/JPY. Естественно, нет никакой гарантии, что так будет изо дня в день. С учетом вышесказанного, на разных валютных парах может быть разная стратегия в ночное время.

Стратегии ночной торговли

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

Возьмем популярную пару EUR/USD. Чаще всего во время азиатской сессии она начинает сбавлять волатильность и двигаться во флэте. Коррекция на этом этапе может быть настолько незначительна, что ее можно посчитать за горизонтальное движение.


Рис.2. Флэтовое движение, в Азиатскую сессию, на паре EUR/USD

Рис.2. Флэтовое движение в азиатскую сессию, на паре EUR/USD

На рис. 2 жёлтыми прямоугольниками обозначено движение пары EUR/USD на таймфрейме H1 во время азиатской сессии. На первом прямоугольнике (слева) просматривается небольшое внутриканальное колебание. В начале сессии происходит движение по ранее созданному тренду, затем — небольшая корректировка (в середине сессии) и в завершении — резкое возвращение обратно. На втором прямоугольнике наблюдается медленное движение вверх, в данном случае повторяющее движение конца дня. На третьем прямоугольнике ситуация немного изменилась. В отличие от предыдущих сессий, начальное движение в ночное время корректирует дневной тренд.

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

На жёлтых прямоугольниках видны верхние и нижние границы. Они ограничивают канал, в котором колеблется цена. На уже сформированном графике обрисовать канал не составит труда, но в реальном времени неизвестно, как будет двигаться цена и большие вопросы вызывает волатильность. Что же делать?

Предлагаю решить этот вопрос при помощи трендового индикатора Bollinger Bands, который дает неплохие сигналы на флэте.

Рис.3. Использование индикатора Bollinger Bands, на паре EUR/USD M30

Рис.3. Использование индикатора Bollinger Bands, на паре EUR/USD M30

На рис. 3 представлен график валютной пары EUR/USD на таймфрейме М30. На него наложен индикатор Bollinger Bands, период выбран максимально низкий (10), остальные настройки — по умолчанию. Здесь видно, как цена попадает в так называемый "динамический канал", создаваемый индикатором. Но этот канал дает не совсем точные сигналы. Например, в первом прямоугольнике цена двигается вниз, и канал повторяет за ней движение. При этом цена не отскакивает от нижней границы канала, но к концу азиатской сессии всё меняется. Рынок начинает отскакивать от создаваемых ограничителей каналов. На втором прямоугольнике действие индикатора наблюдается лишь в конце. На третьем прямоугольнике ситуация схожа с первым.

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

Теперь обратимся к другой стратегии, основанной на резкой волатильности. Для азиатской сессии это будут пары, в которых есть японская иена. Рассматриваемая стратегия широко описана в Сети. Смысл её заключается в том, чтобы войти в рынок в наиболее волатильный момент, когда возможно резкое движение в каком-либо направлении. Два отложенных ордера выставляются одновременно в противоположных направлениях, на равном расстоянии, с равными параметрами, сверху от текущей цены — на покупку, и снизу — на продажу. Время выставления этих ордеров находится, как правило, во второй половине азиатской сессии (возможны исключения).

Итак, на рис. 4 представлен график пары USD/JPY на таймфрейме H1:


Рис.4. Азиатская сессия на паре USD/JPY H1

Рис.4. Азиатская сессия на паре USD/JPY H1

Рассмотрим участки азиатской сессии более подробно:


Рис.5. Участки Азиатской сессии, пара USD/JPY H1

Рис.5. Участки азиатской сессии, пара USD/JPY H1


На рис. 5 красными ценовыми метками отмечены возможности входа в рынок. Все они выставлены на цену открытия свечи. Это моменты, когда описываемая стратегия предлагает выставлять отложенные ордера.

Теперь разберём каждый участок по отдельности. На всех четырёх участках время открытия стоит на 8.00 МСК (5.00 UTC).

  1. На верхнем левом участке открытие свечи начинается на отметке 113.521. Минимум цены 113.341, максимум 113.553. Итого получаем 32 пункта от цены открытия вверх и 180 пунктов вниз.
  2. На верхнем правом участке открытие свечи начинается на отметке 114.152. Минимум цены 114.109, максимум (уже на следующем часе) 114.308. Итого получаем 156 пунктов от цены открытия вверх и 43 вниз. 
  3. Нижний левый участок открывается на 113.601. Минимум цены 113.587, максимум (через три часа) 113.747. Итого 146 пунктов от цены открытия вверх и 14 вниз.
  4. Последний, нижний правый участок: открытие 113.192, минимум 112.957, максимум 113.193. Итого вверх 1 пункт, вниз 235.

Объединим всё в таблицу для наглядности:

Таблица 1

№ участкаЦена открытияМаксимальная ценаМинимальная ценаМаксимальные пунктыМинимальные пункты
1113.521113.553113.34118032
2114.152114.308114.10915643
3113.601113.747113.58714614
4113.192113.193112.9572351
Итог---------минимум 146максимум 43

Как видно из таблицы 1, за четыре сессии минимум из максимальных движений в одну сторону составил 146 пунктов, а максимум из минимальных — 43 пункта. Округлим максимальное до отметки 140 пунктов (в меньшую сторону) и минимальное до 45 пунктов (в большую сторону), соответственно. 

Для всех четырех ситуациях выставим по два противоположных отложенных ордера на 50 пунктов. Стоп-лосс поставим на 100-110 пунктов, тейк-профит на 50-80 пунктов. Профит составит 200-320 пунктов соответственно. То есть во всех четырёх случаях получаем срабатывание тейк-профита.

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

Кодируем стратегии

Стратегия на основе индикатора Bollinger Bands 

Вначале подключаем класс CTrade, для удобства управления сделками. Далее займемся входящими переменными.

  • Переменная div_work отвечает за резкие скачки цен: она ограничивает предельный диапазон, в котором может находиться сигнал.
  • Переменная div_signal отвечает за искажение сигнала. Сигналом считается не сама точка контакта с верхней или нижней границей индикатора, ей дается некоторый запас. Иными словами, сигнал срабатывает, когда цена выходит за пределы границы на расстояние этой переменной. Это отфильтровывает ряд ложных сигналов.
  • Переменная work_alt — флаг, разрешающий закрывать текущую позицию и открывать новую при появлении противоположного сигнала.
//+------------------------------------------------------------------+
//|                                        BollingerBandsForFlat.mq5 |
//|                                                          Aktiniy |
//|                                                             BBFF |
//+------------------------------------------------------------------+
#property copyright "Aktiniy"
#property link      "BBFF"
#property version   "1.01"
#include<Trade\Trade.mqh>
//--- input parameters
input char     time_h_start=22;       // Время начала торговли
input char     time_h_stop=3;         // Время окончания торговли
input int      bands_period=12;       // Период Bollinger Bands
input int      bands_shift=0;         // Сдвиг Bollinger Bands
input double   bands_diviation=2;     // Отклонения Bollinger Bands
input double   div_work=3;            // Отклонение от сигнала
input double   div_signal=5;          // Занижение основного сигнала
input bool     work_alt=true;         // Работа с позицией в случае наличия противоположного сигнала
input int      take_profit=50;        // Take Profit
input int      stop_loss=100;         // Stop Loss
//---
input bool     mon=true;              // Работа в Понедельник
input bool     tue=false;             // Работа во Вторник
input bool     wen=true;              // Работа в Среду
input bool     thu=true;              // Работа в Четверг
input bool     fri=true;              // Работа в Пятницу
//---
input long magic_number=65758473787389; // Магический номер
input double order_volume=0.01;         // Размер Лота
input int order_deviation=100;          // Отклонение по открытию позиции
//--- Variable
MqlDateTime time_now_str;
datetime time_now_var;
CTrade trade;
int bb_handle;
double bb_base_line[3];
double bb_upper_line[3];
double bb_lower_line[3];
bool work_day=true;

Остальные входящие переменные достаточно подробно прокомментированы в коде.

Что же касается глобальных переменных, то здесь есть:

  • две равнозначные переменные времени (time_now_str, time_now_var) для удобства работы,
  • следом объект класса для работы с ордерами,
  • хэндл индикатора,
  • три небольших массива для данных об индикаторе на текущий момент (bb_base_line[], bb_upper_line[], bb_lower_line[]).
  • Переменная work_day отвечает за разрешение на выставление ордеров по дням недели.

Далее идет небольшой код для инициализации некоторых параметров работы с классом:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   trade.SetExpertMagicNumber(magic_number);
   trade.SetDeviationInPoints(order_deviation);
   trade.SetTypeFilling(ORDER_FILLING_FOK);
   trade.SetAsyncMode(false);
//---
   return(INIT_SUCCEEDED);
  }

Теперь рассмотрим основной код взаимодействия и получения сигналов.

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

Предполагалось, что советник будет работать не только в азиатскую сессию (будет универсальным). Кроме того, возможно, что время терминала на разных серверах будет отличаться. Поэтому надо проверить время работы. Здесь есть два варианта: либо работа в течение периода, либо с переходом через разделитель суточного периода. Заносим информацию в флаг work.

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   time_now_var=TimeCurrent(time_now_str);// текущее время
   bool work=false;
   
      switch(time_now_str.day_of_week)
     {
      case 1: if(mon==false){work_day=false;}
      else {work_day=true;}
      break;
      case 2: if(tue==false){work_day=false;}
      else {work_day=true;}
      break;
      case 3: if(wen==false){work_day=false;}
      else {work_day=true;}
      break;
      case 4: if(thu==false){work_day=false;}
      else {work_day=true;}
      break;
      case 5: if(fri==false){work_day=false;}
      else {work_day=true;}
      break;
     }

//--- проверяем время работы     
   if(time_h_start>time_h_stop)             // работа с переходом на следующий день
     {
      if(time_now_str.hour>=time_h_start || time_now_str.hour<=time_h_stop)
        {
         work=true;
        }                                   // передача флага разрешения на работу
     }
   else                                     // работа в течении дня
     {
      if(time_now_str.hour>=time_h_start && time_now_str.hour<=time_h_stop)
        {
         work=true;
        }
     }                                     // передача флага разрешения на работу

   int pos=PositionsTotal();

   if(work==true && work_day==true)        // разрешение на работу получено
     {
      bb_handle=iBands(_Symbol,_Period,bands_period,bands_shift,bands_diviation,PRICE_CLOSE);         // узнаём хэндл индикатора Bollinger Bands
      int i_bl=CopyBuffer(bb_handle,0,0,3,bb_base_line);
      int i_ul=CopyBuffer(bb_handle,1,0,3,bb_upper_line);
      int i_ll=CopyBuffer(bb_handle,2,0,3,bb_lower_line);
      if(i_bl==-1 || i_ul==-1 || i_ll==-1)
        {Alert("Error of copy iBands: base line=",i_bl,", upper band=",i_ul,", lower band=",i_ll);}   // проверяем скопированные данные

      double price_ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      double price_bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);

      if(pos<1)
        {
         if((price_ask-(div_signal*_Point))>=bb_upper_line[2]-(div_work*_Point) && (price_ask-(div_signal*_Point))<=bb_upper_line[2]+(div_work*_Point))// сигнал к продаже
           {
            trade.Sell(order_volume,_Symbol,price_bid,(price_bid+(stop_loss*_Point)),(price_bid-(take_profit*_Point)),"pos<1_sell");
           }
         if((price_bid+(div_signal*_Point))<=bb_lower_line[2]+(div_work*_Point) && (price_bid+(div_signal*_Point))>=bb_lower_line[2]-(div_work*_Point))// сигнал к покупки
           {
            trade.Buy(order_volume,_Symbol,price_ask,(price_ask-(stop_loss*_Point)),(price_ask+(take_profit*_Point)),"pos<1_buy");
           }
        }
      if(pos>0 && work_alt==true)
        {
         if(trade.RequestType()==ORDER_TYPE_BUY)                     // если до этого стоял ордер на покупку
            if((price_ask-(div_signal*_Point))>=bb_upper_line[2]-(div_work*_Point) && (price_ask-(div_signal*_Point))<=bb_upper_line[2]+(div_work*_Point))// сигнал к продаже
              {
               trade.PositionClose(_Symbol,order_deviation);
               trade.Sell(order_volume,_Symbol,price_bid,(price_bid+(stop_loss*_Point)),(price_bid-(take_profit*_Point)),"pos>0_sell");
              }
         if(trade.RequestType()==ORDER_TYPE_SELL)                   // если до этого стоял ордер на продажу
            if((price_bid+(div_signal*_Point))<=bb_lower_line[2]+(div_work*_Point) && (price_bid+(div_signal*_Point))>=bb_lower_line[2]-(div_work*_Point))// сигнал к покупки
              {
               trade.PositionClose(_Symbol,order_deviation);
               trade.Buy(order_volume,_Symbol,price_ask,(price_ask-(stop_loss*_Point)),(price_ask+(take_profit*_Point)),"pos>0_buy");
              }
        }
     }
   else
     {
      if(pos>0)
        {
         trade.PositionClose(_Symbol,order_deviation);
        }
     }
  }
//+------------------------------------------------------------------+ 

И последний элемент кода: в случае закрытия ночной сессии закрываются все ордера. На этом код советника кончается.

Стратегия на основе резкого изменения волатильности

Здесь всё предельно просто: ордера выставляются только в определённое время order_time. Ордера выставляются на расстоянии order_div от текущей цены, с соответствующими стоп-лоссом (order_sl) и тейк-профитом (order_tp). Если ни один из отложенных ордеров не сработал, это говорит о флэтовом движении на рынке, и ордера удаляются по истечении времени time_to_del (указывается в секундах).

Остальные входные данные — такие же, как в предыдущем эксперте.

Из глобальных переменных тут добавляются:

  • work — флаг для разрешения только на одноразовое выставление ордеров,
  • work_del — флаг для разрешения на удаление противоположного ордера в случае срабатывания одного из ордеров,
  • work_day — флаг разрешения на работу в текущий день.

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

//+------------------------------------------------------------------+
//|                                                TimeBuyOrSell.mq5 |
//|                                                          Aktiniy |
//|                                                             TBOS |
//+------------------------------------------------------------------+
#property copyright "Aktiniy"
#property link      "TBOS"
#property version   "1.01"
#include<Trade\Trade.mqh>
//--- input parameters
input int      order_time=0;                        // Время открытия ордера
input int      order_sl=200;                        // Stop Loss
input int      order_tp=180;                        // Take Profit
input int      order_div=120;                       // Отклонения по выставлению ордеров от текущей цены
input int      time_to_del=10800;                   // Время удаления ордеров
//---
input bool     mon=true;                            // Работа в Понедельник
input bool     tue=false;                           // Работа во Вторник
input bool     wen=true;                            // Работа в Среду
input bool     thu=true;                            // Работа в Четверг
input bool     fri=true;                            // Работа в Пятницу
//---
input long magic_number=65758473787389;             // Магический номер
input double order_volume=0.01;                     // Размер Лота
input int order_deviation=100;                      // Отклонение по открытию позиции
//--- Variable
CTrade trade;
MqlDateTime time_now_str;
datetime time_now_var;
bool work=true;
bool work_del=true;
bool work_day=true;
//---
MqlTradeResult result_buy={0};
MqlTradeResult result_sell={0};

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

Начало функции OnTick сходно с предыдущим описанным экспертом. После получения флага на работу в этот день идёт проверка соответствия текущего часа на работу. Если всё успешно, рассчитываем параметры открытия ордеров (Take Profit, Stop Loss, цену открытия и время удаления в случае несрабатывания). Отправляем соответствующие торговые запросы на сервер.

После выставления отложенных ордеров эксперт следит за срабатыванием одного из них и удаляет лишний по тикету из структуры результата (result_buy, result_sell).

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   time_now_var=TimeCurrent(time_now_str);// текущее время

   switch(time_now_str.day_of_week)
     {
      case 1: if(mon==false){work_day=false;}
      else {work_day=true;}
      break;
      case 2: if(tue==false){work_day=false;}
      else {work_day=true;}
      break;
      case 3: if(wen==false){work_day=false;}
      else {work_day=true;}
      break;
      case 4: if(thu==false){work_day=false;}
      else {work_day=true;}
      break;
      case 5: if(fri==false){work_day=false;}
      else {work_day=true;}
      break;
     }

   if(time_now_str.hour==order_time && work==true && work_day==true)
     {
      double price_ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      double price_bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);

      double div=order_div*_Point;
      double sl=order_sl*_Point;
      double tp=order_tp*_Point;

      double price_buy=price_ask+div;
      double price_sell=price_bid-div;

      double buy_sl=price_buy-sl;
      double buy_tp=price_buy+tp;
      double sell_sl=price_sell+sl;
      double sell_tp=price_sell-tp;

      datetime time_end=time_now_var+time_to_del;     //3600 секунд, один час

      trade.BuyStop(order_volume,price_buy,_Symbol,buy_sl,buy_tp,ORDER_TIME_SPECIFIED,time_end,"BuyLimit");
      trade.Result(result_buy);

      trade.SellStop(order_volume,price_sell,_Symbol,sell_sl,sell_tp,ORDER_TIME_SPECIFIED,time_end,"SellLimit");
      trade.Result(result_sell);

      work=false;
     }

   if(PositionsTotal()>0 && work_del==true)
     {
      PositionSelect(_Symbol);
      long position_type=PositionGetInteger(POSITION_TYPE);
      if(position_type==POSITION_TYPE_SELL)
         trade.OrderDelete(result_buy.order);
      if(position_type==POSITION_TYPE_BUY)
         trade.OrderDelete(result_sell.order);

      work_del=false;
     }
   if(PositionsTotal()==0)
      work_del=true;

   if(time_now_str.hour!=order_time)
     {
      work=true;
     }

  }
//+------------------------------------------------------------------+

В конце кода выставляется флаг разрешения на выставление ордеров ввиду выхода из времени открытия.

Тестирование и прибыльность

Стратегия на основе индикатора Bollinger Bands 

  • Символ: EURUSD
  • Период: М30 (2017.01.01 - 2017.11.03)
  • Брокер: Halifax Investment Services Pty Ltd
  • Валюта: AUD
  • Начальный депозит: 100.00
  • Плечо: 1:100

В ходе оптимизации были выявлены параметры:


Приведу краткую расшифровку: работа идет в ночное время с часу ночи до 11 (МСК), период индикатора 11, отклонение от сигнала 12, занижение основного сигнала 13, Stop Loss=140 и Take Profit=120, работа во все дни недели, кроме вторника.

Для начала посмотрим на результаты при тестировании по "OHLC на M1", рис. 6 и 7:


Рис.6. Результаты тестирование стратегии на основе Bollinger Bands по OHLC на M1

Рис.6. Результаты тестирования стратегии на основе Bollinger Bands по OHLC на M1

Рис.7. Результат тестирования на графике (Bollinger Bands по OHLC на M1)

Рис.7. Результат тестирования на графике (Bollinger Bands по OHLC на M1)

Результаты тестирования на тех же параметрах, но в режиме "Каждый тик на основе реальных тиков", рис. 8 и 9:

Рис.8. Результаты тестирование стратегии на основе Bollinger Bands по Каждый тик на основе реальных тиков

Рис.8. Результаты тестирования стратегии на основе Bollinger Bands по Каждый тик на основе реальных тиков

Рис.9. Результат тестирования на графике (Bollinger Bands по Каждый тик на основе реальных тиков)

Рис.9. Результат тестирования на графике (Bollinger Bands по Каждый тик на основе реальных тиков)

Как видно из результатов, прибыль получается в обоих случаях: в первом — 152%, во втором — 48%, (сказывается качество истории). В обоих тестированиях просадка составила менее 25%. Мне кажется, это достаточно интересный результат, заслуживающий внимания.

Ранее на рис. 3 мы рассмотрели три периода сессии и описали стратегию. Теперь рассмотрим, как же советник справился с торговлей на первых двух участках (рис. 10 и 11):

Рис.10. Результат работы, советника на ранее рассматриваемом первом периоде

Рис.10. Результат работы советника на ранее рассмотренном первом периоде

На рисунке 10 (это первый период из рис. 3) видно, как советник реализует три входа. Первый получается неудачным и заканчивается стоп-лоссом, зато два следующих — в конце азиатской сессии и начале европейской — закрываются по тейк-профиту.

Рис.11. Результат работы, советника на ранее рассматриваемом втором периоде

Рис.11. Результат работы, советника на ранее рассматриваемом втором периоде

На рис. 11 (это второй период из рис. 3) советник совершает два входа — в конце азиатской сессии и начале европейской. Один из них оказался прибыльным, второй — убыточным. На третьем периоде из рис. 3 советник не входил в рынок. Это был вторник, и согласно настройкам, в этот день эксперт не торгует.

Теперь посмотрим, как стратегия проявит себя на других мажорных парах:

Символ: AUDUSD

Период: M30 (2017.01.01 - 2017.11.07)

Параметры:


Рис.13. Результаты тестирования AUDUSD M30 (BollingerBands)

Рис.13. Результаты тестирования AUDUSD M30 (BollingerBands)

Рис.13. Результаты тестирования AUDUSD M30 (BollingerBands)

Символ: GBPUSD

Период: M30 (2017.01.01 - 2017.11.06)

Параметры:


Рис.14. Результаты тестирования GBPUSD M30 (BollingerBands)

Рис.14. Результаты тестирования GBPUSD M30 (BollingerBands)

Рис.14. Результаты тестирования GBPUSD M30 (BollingerBands)

Символ: NZDUSD

Период: M30 (2017.01.01 - 2017.11.07)

Параметры:


Рис.15. Результаты тестирования NZDUSD M30 (BollingerBands)

Рис.15. Результаты тестирования NZDUSD M30 (BollingerBands)

Рис.15. Результаты тестирования NZDUSD M30 (BollingerBands)

Символ: USDCAD

Период: M30 (2017.01.01 - 2017.11.07)

Параметры:


Рис.16. Результаты тестирования USDCAD M30 (BollingerBands)

Рис.16. Результаты тестирования USDCAD M30 (BollingerBands)

Рис.16. Результаты тестирования USDCAD M30 (BollingerBands)

Символ: USDCHF

Период: M30 (2017.01.01 - 2017.11.07)

Параметры:


Рис.17. Результаты тестирования USDCHF M30 (BollingerBands)

Рис.17. Результаты тестирования USDCHF M30 (BollingerBands)

Рис.17. Результаты тестирования USDCHF M30 (BollingerBands)

Аккумулируя все данные по тестированию, можно прийти к следующим выводам.

  • Наиболее благоприятные пары для работы с этим советником — EURUSD, NZDUSD, AUDUSD. По параметрам понятно, что сигналы больше отрабатываются на ранее названных парах, где Take Profit и Stop Loss отличаются не более, чем в три раза. Естественно, и прибыль здесь более прогрессивна.
  • День недели однозначно влияет на профит. Поведение валютных пар разное в разные дни недели, но однозначных зависимостей вывести не удалось: всё зависит как от конкретной выбранной пары, так и от выбранных настроек.

Стратегия на основе резкого изменения волатильности

Меняются такие параметры тестирования:

  • Символ: USDJPY
  • Период: H1 (2017.01.01 - 2017.11.03)

Для начала проверим оговоренную выше стратегию, вот ее параметры: 

  • order_time=8;
  • order_sl=140;
  •  order_tp=70;
  • order_div=50;
  • time_to_del=18000.

Здесь мы подняли стоп-лосс с 110 до 140, это немного повысило прибыльность стратегии. Результаты тестирования представлены на рис. 18 и 19, соответственно:

Рис.12. Результат тестирования стратегии резкого изменения волатильности USDJPY H1

Рис.18. Результат тестирования стратегии резкого изменения волатильности USDJPY H1

Рис.13. Результат тестирования на графике

Рис.19. Результат тестирования на графике USDJPY H1

По графику видно, что стратегия начинает работать приблизительно с середины тестирования. Но на более длинном периоде тестирования (примерно с 2015 года) стратегия не приносит прибыли в общем. Также по данным параметрам вход осуществляется в 8.00 МСК, а значит, опять же затрагивает европейскую сессию. Такую торговлю уже можно назвать утренней.

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

Меняются такие параметры тестирования:

  • Символ: USDJPY
  • Период: H1 (2015.01.01 - 2017.11.03)

Параметры тестирования:


То есть советник работает только во вторник, выставляет позиции в 4 часа по МСК (азиатская сессия),  стоп-лосс и тейк-профит почти равны и составляют 270 и 220 пунктов соответственно, ордера выставляются на расстоянии 130 от цены входа. Результаты тестирования представлены на рис. 20 и 21:

Рис.14. Результат тестирования стратегии резкого изменения волатильности USDJPY H1 (2015-2017)

Рис.20. Результат тестирования стратегии резкого изменения волатильности USDJPY H1 (2015-2017)

Рис.15. Результат тестирования на графике USDJPY H1 (2015-2017)

Рис.21. Результат тестирования на графике USDJPY H1 (2015-2017)

В последнем тестировании в режимах "Каждый тик на основе реальных тиков" или "OHLC на M1", результат не особо изменяется, поэтому представлен первый вариант (рис. 20 и 21)

Заключение

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

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


Файлы:

#ИмяТипОписание
1BollingerBandsForFlat_v1.01.mq5СоветникСоветник, ориентированный на торговлю в азиатскую сессию во флэте, на основе сигналов от индикатора Bollinger Bands
2TimeBuyOrSell_v1.01.mq5СоветникСоветник, ориентированный на торговлю в наиболее волатильное время


Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (13)
Dmitriy Zabudskiy
Dmitriy Zabudskiy | 15 нояб. 2017 в 11:53
Eugene Myzrov:

Может быть вместо

использовать более простое

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

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

Ваш пример:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   time_now_var=TimeCurrent(time_now_str);// текущее время

   switch(time_now_str.day_of_week)
     {
      case 1: work_day=mon; break;
      case 2: work_day=tue; break;
      case 3: work_day=wen; break;
      case 4: work_day=thu; break;
      case 5: work_day=fri; break;
     }
...

Честно говоря не понял, его нужно дополнить... Так как во входящих переменных в советник, дни недели, в которые нужно работать, отмечены как "true", а если в этот день не надо работать то "false". 

И переменная "work_day", передаёт ответ в виде "true" или "false". В вашем примере, переменная становится уже типа "string", дальше опять нужно будет делать сравнение.

А так, я за оптимизацию кода, хотя в этом советнике, это не стояло приоритетом.

Конкретно этот код можно оптимизировать:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   time_now_var=TimeCurrent(time_now_str);// текущее время

   work_day=true;

   switch(time_now_str.day_of_week)
     {
      case 1: if(mon==false){work_day=false;}
      break;
      case 2: if(tue==false){work_day=false;}
      break;
      case 3: if(wen==false){work_day=false;}
      break;
      case 4: if(thu==false){work_day=false;}
      break;
      case 5: if(fri==false){work_day=false;}
      break;
     }

Размер кода уменьшится, но вот скорость работы нет...

Возможно можно через цикл в функции реализовать, тогда размер может меньше, удастся сделать, но скорость обработки будет дольше.

Можно ещё поработать и как то изменить входящие параметры, тогда и код можно как то изменить, возможно упростить. 

Eugene Myzrov
Eugene Myzrov | 15 нояб. 2017 в 12:40
Dmitriy Zabudskiy: Спасибо, за комментарий. Привычка хорошая, сам так тоже бывает делаю... Ваш пример:Честно говоря не понял, его нужно дополнить... Так как во входящих переменных в советник, дни недели, в которые нужно работать, отмечены как "true", а если в этот день не надо работать то "false". И переменная "work_day", передаёт ответ в виде "true" или "false". В вашем примере, переменная становится уже типа "string", дальше опять нужно будет делать сравнение. А так, я за оптимизацию кода, хотя в этом советнике, это не стояло приоритетом. Конкретно этот код можно оптимизировать. Размер кода уменьшится, но вот скорость работы нет... Возможно можно через цикл в функции реализовать, тогда размер может меньше, удастся сделать, но скорость обработки будет дольше. Можно ещё поработать и как то изменить входящие параметры, тогда и код можно как то изменить, возможно упростить. 
   work_day=false;
   switch(time_now_str.day_of_week)
     {
      case 1: if (mon) work_day=true; break;
      case 2: if (tue) work_day=true; break;
      case 3: if (wen) work_day=true; break;
      case 4: if (thu) work_day=true; break;
      case 5: if (fri) work_day=true; break;
     }


Вы могли бы предложить еще и такой код. Но убрав операторы "else", Вы упростили исходный код только наполовину. Оптимальный вариант получится, если уберете еще и операторы "if", оставив только 5 операторов присваивания. Это и будет оптимальным вариантом, который был предложен.

switch(time_now_str.day_of_week)
     {
      case 1: work_day=mon; break;
      case 2: work_day=tue; break;
      case 3: work_day=wen; break;
      case 4: work_day=thu; break;
      case 5: work_day=fri; break;
     default: work_day=false; // в субботу и воскресенье не торгуем...
     }

А вот про переменную, которая становится типа "string", я совсем не понял.

Dmitriy Zabudskiy
Dmitriy Zabudskiy | 15 нояб. 2017 в 17:59
Eugene Myzrov:


Вы могли бы предложить еще и такой код. Но убрав операторы "else", Вы упростили исходный код только наполовину. Оптимальный вариант получится, если уберете еще и операторы "if", оставив только 5 операторов присваивания. Это и будет оптимальным вариантом, который был предложен.

А вот про переменную, которая становится типа "string", я совсем не понял.


Да, Вы правы, я что то по началу не учёл название переменных (не подумал про " " в синтаксисе, от этого и про string сказал). Так действительно короче получится.

Спасибо за подсказку, учтём на будущее)

kofesutra
kofesutra | 29 нояб. 2017 в 14:50

Здравствуйте, Дмитрий!

Скажите, почему при принятии решения о продаже в советнике используется цена Ask, а при покупке Bid?

Dmitriy Zabudskiy
Dmitriy Zabudskiy | 29 нояб. 2017 в 20:00
kofesutra:

Здравствуйте, Дмитрий!

Скажите, почему при принятии решения о продаже в советнике используется цена Ask, а при покупке Bid?


Здравствуйте!

В начале разработки не планировалось вводить дивергенцию (div_signal и div_work), хотелось ограничится (спредом), как более ранним входом в рынок, что бы не пропускать сигналы.

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

Торговая стратегия 'Momentum Pinball' Торговая стратегия 'Momentum Pinball'
В этой статье продолжается тема написания кода к торговым системам, описанным в книге Линды Рашке и Лоуренса Коннорса "Биржевые секреты. Высокоэффективные стратегии краткосрочной торговли". На этот раз исследуется система 'Momentum Pinball': описано создание двух индикаторов, торгового робота и сигнального блока по ней.
Раскладываем входы по индикаторам Раскладываем входы по индикаторам
В жизни трейдера бывают разные ситуации. Часто по истории успешных сделок мы пытаемся восстановить стратегию, а глядя на историю убытков — доработать и улучшить ее. И в том, и в другом случае мы сопоставляем сделки с известными индикаторами. В этой статье предлагается методика пакетного сопоставления сделок с рядом индикаторов.
Автоматический подбор перспективных сигналов Автоматический подбор перспективных сигналов
Статья посвящена изучению торговых сигналов для MetaTrader 5 с автоматическим исполнением на счетах подписчиков. Также рассматривается разработка инструментов для поиска перспективных торговых сигналов прямо в терминале.
Кроссплатформенный торговый советник: Классы CExpertAdvisor и CExpertAdvisors Кроссплатформенный торговый советник: Классы CExpertAdvisor и CExpertAdvisors
В заключительной статье серии о кроссплатформенном торговом советнике речь пойдет о классах CExpertAdvisor и CExpertAdvisors, которые служат контейнерами для всех ранее описанных компонентов эксперта. Также рассмотрена реализация отслеживания новых баров и сохранения данных.