Методы измерения скорости движения цены

4 июня 2019, 14:42
Alexander Fedosov
5
1 485

Содержание

Введение

Существует множество различных подходов к исследованию и анализу рынков. Но основных обычно два: технический и фундаментальный. В первом случае происходит сбор, обработка и изучение каких-либо числовых данных и характеристик, связанных с рынком: цены, объемы и так далее. Во втором анализ событий, новостей, которые, в свою очередь, влияют прямо или косвенно на рынки. Если в случае с фундаментальным анализом встает вопрос интерпретации какого-либо события относительно его влияния на рынок — и оно может носить отпечаток, влияние или желание самого интерпретатора, то в случае с техническим анализом дело чаще всего обстоит с данными, не имеющими различных интерпретаций. Хотя и здесь есть доля человеческого фактора в оценке результатов технического анализа.


Проблема восприятия

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

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

Методы измерения скорости движения цены

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

Определение скорости в Википедии:

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

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

Рис.1 Отображение цены в виде японской свечи на часовом таймфрейме.

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

Средняя скорость = (Цена закрытия — Цена открытия) / Час

Какие наблюдения и выводы относительно движения цены во времени мы можем сделать:

  • Мы определили среднее количество пунктов, которое цена проходит за час. Однако измерение проходит в рамках лишь одной свечи и общую картину тренда на данном таймфрейме мы не получим.
  • Тем не менее, если мы переведем скорость из количество пунктов в час в количество пунктов в минуту, 5 минут и так далее, мы получим получим более ценную информацию о движении цены внутри этой часовой свечи.
  • Поэтому очевидны два следующих момента: определение  скорости на младших таймфреймах удобней делать на старших. Если же замерять среднюю скорость на текущем таймфрейме, измеряя движение цены, то делать это за несколько свечей.
Ну и главный момент при измерении скорости таким простым способом состоит в том, что для свечей вглубь истории она не дает никакой информации о динамике внутри самой свечи, а показывает лишь итоговый усредненный результат. Глядя на среднюю скорость часовой свечи, мы, к примеру, никогда не узнаем по значению средней скорости, что в начале она была большой, но под конец часа упала до низких значений.

Для наглядности приведу пример, которой отлично характеризует тезисы, сказанные чуть выше. На рис.2 представлена часовая свеча и внизу с помощью индикатора Average Speed посчитана ее средняя скорость в минуту. В данном случае она равна 2,53 пункта в минуту.

Рис. 2 Пример расчета средней скорости на валютной паре EURUSD часового таймфрейма

А теперь рассмотрим эту свечу развернуто на 15-минутном таймфрейме.


Рис. 3 Пример расчета средней скорости на валютной паре EURUSD 15-минутного таймфрейма

Как видно из рис.3 в первую 15-минутку выбранного нами часового промежутка было очень сильное движение(Average speed показывал 6,93), но вскоре оно существенно замедлилось. Само собой если сложить все 4 значения средней скорость, то получим те же 2,53 пукнта в минуту с часового таймфрейма. Но ведь разложив одну свечу на её составляющие, сколько нового о самой динамике движения мы узнали.

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

Рис. 4 Пример расчета средней скорости на валютной паре EURUSD минутного таймфрейма

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

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

Рис.5 Пример работы индикатора мгновенной скорости движения цены

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

Как известно, подавляющая часть индикаторов — это те или иные производные цены или ее анализаторы. Вот пример некоторых хорошо известных, которые работают со скоростью движения цены:

  • Индикатор Momentum, который измеряет величину изменения цены финансового инструмента за определенный период. Крайне высокие или низкие значения индикатора Momentum предполагают продолжение текущей тенденции.  Что говорит о том, что большие отклонения данного индикатора — это текущая большая скорость цены в заданном направлении.
  • Трендовый индикатор ADX. Индекс Среднего Направления Движения (Average Directional Movement Index) показывает силу текущего тренда. По сути — текущую среднюю скорость.

Создание торговых стратегий на основе методов измерения

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

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

Торговая стратегия №1

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

В качестве такого фильтра было решено взять индикатор Coordinated ADX and MACD (CAM). И торговая стратегия будет выглядеть следующем образом:

Параметр Описание
Используемый индикатор Average Speed
Используемый индикатор Coordinated ADX and MACD (CAM) 
Таймфрейм Любой 
Условия на покупку Цвет свечи окрашен в зеленый цвет, а значение Average Speed выше порогового (изначально заданного в настройках)
Условия на продажу Цвет свечи окрашен в красный цвет, а значение Average Speed выше порогового (изначально заданного в настройках)
Условия выхода   Тейк-профит/Стоп-лосс

На рис.6 ниже представлена визуальная ситуация при открытии позиций на покупку и продажу:

Рис.6 Условия входа по торговой стратегии.

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

//+------------------------------------------------------------------+
//| Входные параметры эксперта                                       |
//+------------------------------------------------------------------+
input string               InpEaComment         =  "Strategy #1"; // EA Comment
input int                  InpMagicNum          =  1111;          // Magic number
input double               InpLot               =  0.1;           // Lots
input uint                 InpStopLoss          =  400;           // StopLoss in points
input uint                 InpTakeProfit        =  500;           // TakeProfit in points
input uint                 InpSlippage          =  0;             // Slippage in points
input ENUM_TIMEFRAMES      InpInd_Timeframe     =  PERIOD_H1;     // Timeframe for the calculation
//--- Параметры индикатора Average Speed
input int                  InpBars              =  1;             // Days
input ENUM_APPLIED_PRICE   InpPrice             =  PRICE_CLOSE;   // Applied price
input double               InpTrendLev          =  2;             // Trend Level
//--- Параметры индикатора CAM
input uint                 InpPeriodADX         =  10;            // ADX period
input uint                 InpPeriodFast        =  12;            // MACD Fast EMA period
input uint                 InpPeriodSlow        =  26;            // MACD Slow EMA period
//---
CEngine        engine;
CTrade         trade;
//--- Объявление переменных и хендлов индикаторов
double         lot;
ulong          magic_number;
uint           stoploss;
uint           takeprofit;
uint           slippage;
int            InpInd_Handle1,InpInd_Handle2;
double         avr_speed[],cam_up[],cam_dn[];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Первичные проверки
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      Print(InpEaComment,": Trade is not allowed!");
      return(INIT_FAILED);
     }
   if(!TerminalInfoInteger(TERMINAL_CONNECTED))
     {
      Print(InpEaComment,": No Connection!");
      return(INIT_FAILED);
     }
//--- Получение хэндла индикатора Average Speed
   InpInd_Handle1=iCustom(Symbol(),InpInd_Timeframe,"Speed Price\\average_speed",
                          InpBars,
                          InpPrice
                          );
   if(InpInd_Handle1==INVALID_HANDLE)
     {
      Print(InpEaComment,": Failed to get average_speed handle");
      Print("Handle = ",InpInd_Handle1,"  error = ",GetLastError());
      return(INIT_FAILED);
     }
//--- Получение хэндла индикатора CAM
   InpInd_Handle2=iCustom(Symbol(),InpInd_Timeframe,"Speed Price\\CAM",
                          InpPeriodADX,
                          InpPeriodFast,
                          InpPeriodSlow
                          );
   if(InpInd_Handle2==INVALID_HANDLE)
     {
      Print(InpEaComment,": Failed to get average_speed handle");
      Print("Handle = ",InpInd_Handle2,"  error = ",GetLastError());
      return(INIT_FAILED);
     }
//---
   ArrayInitialize(avr_speed,0.0);
   ArrayInitialize(cam_up,0.0);
   ArrayInitialize(cam_dn,0.0);
   ArraySetAsSeries(avr_speed,true);
   ArraySetAsSeries(cam_up,true);
   ArraySetAsSeries(cam_dn,true);
//--- setting trade parameters
   lot=NormalizeLot(Symbol(),fmax(InpLot,MinimumLots(Symbol())));
   magic_number=InpMagicNum;
   stoploss=InpStopLoss;
   takeprofit=InpTakeProfit;
   slippage=InpSlippage;
//--- 
   trade.SetDeviationInPoints(slippage);
   trade.SetExpertMagicNumber(magic_number);
   trade.SetTypeFillingBySymbol(Symbol());
   trade.SetMarginMode();
   trade.LogLevel(LOG_LEVEL_NO);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(!MQLInfoInteger(MQL_TESTER))
      engine.OnTimer();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Если работа в тестере
   if(MQLInfoInteger(MQL_TESTER))
      engine.OnTimer();

   if(!IsOpenedByMagic(InpMagicNum))
     {
      //--- Получение данных для расчета
      if(!GetIndValue())
         return;
      //---
      if(BuySignal())
        {
         //--- Получаем корректные цены StopLoss и TakeProfit относительно уровня StopLevel
         double sl=CorrectStopLoss(Symbol(),ORDER_TYPE_BUY,0,stoploss);
         double tp=CorrectTakeProfit(Symbol(),ORDER_TYPE_BUY,0,takeprofit);
         //--- Открываем позицию Buy
         trade.Buy(lot,Symbol(),0,sl,tp);
        }
      else if(SellSignal())
        {
         //--- Получаем корректные цены StopLoss и TakeProfit относительно уровня StopLevel
         double sl=CorrectStopLoss(Symbol(),ORDER_TYPE_SELL,0,stoploss);
         double tp=CorrectTakeProfit(Symbol(),ORDER_TYPE_SELL,0,takeprofit);
         //--- Открываем позицию Sell
         trade.Sell(lot,Symbol(),0,sl,tp);
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(avr_speed[0]>=InpTrendLev && cam_up[0]!=EMPTY_VALUE)?true:false;
  }
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(avr_speed[0]>=InpTrendLev && cam_dn[0]!=EMPTY_VALUE)?true:false;
  }
//+------------------------------------------------------------------+
//| Получение текущих значений индикаторов                           |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle2,0,0,1,cam_up)<1 ||
          CopyBuffer(InpInd_Handle2,1,0,1,cam_dn)<1 || 
          CopyBuffer(InpInd_Handle1,0,0,1,avr_speed)<1
          )?false:true;
  }
//+------------------------------------------------------------------+
//| Проверка на открытые позиций с магиком                           |
//+------------------------------------------------------------------+
bool IsOpenedByMagic(int MagicNumber)
  {
   int pos=0;
   uint total=PositionsTotal();
//---
   for(uint i=0; i<total; i++)
     {
      if(SelectByIndex(i))
         if(PositionGetInteger(POSITION_MAGIC)==MagicNumber)
            pos++;
     }
   return((pos>0)?true:false);
  }
//+------------------------------------------------------------------+
//| Select a position on the index                                   |
//+------------------------------------------------------------------+
bool SelectByIndex(const int index)
  {
   ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
//---
   if(margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      ulong ticket=PositionGetTicket(index);
      if(ticket==0)
         return(false);
     }
   else
     {
      string name=PositionGetSymbol(index);
      if(name=="")
         return(false);
     }
//---
   return(true);
  }
//+------------------------------------------------------------------+

Торговая стратегия №2

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

Параметр Описание
Таймфрейм Любой 
Условия на покупку Количество пунктов цены, пройденных за определенное количество тиков.
Условия на продажу Количество пунктов цены, пройденных за определенное количество тиков.
Условия выхода   Тейк-профит/Стоп-лосс

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

//+------------------------------------------------------------------+
//| Входные параметры эксперта                                       |
//+------------------------------------------------------------------+
input string               InpEaComment         =  "Strategy #2"; // EA Comment
input int                  InpMagicNum          =  1111;          // Magic number
input double               InpLots              =  0.1;           // Lots
input uint                 InpStopLoss          =  400;           // StopLoss in points
input uint                 InpTakeProfit        =  500;           // TakeProfit in points
input ENUM_COPY_TICKS      tick_flags           =  TICKS_INFO;    // Тики, вызванные изменениями Bid и/или Ask
input int                  InpPoints            =  15;            // Цена должна пройти NNN пунктов
input uchar                InpTicks             =  15;            // За XXX тиков

//--- массивы для приема тиков
MqlTick        tick_array_curr[];            // массив тиков полученный на текущем тике
MqlTick        tick_array_prev[];            // массив тиков полученный на предыдущем тике
ulong          tick_from=0;                  // если параметр tick_from=0, то отдаются последние tick_count тиков
uint           tick_count=15;                // количество тиков, которые необходимо получить 
//---
double         ExtStopLoss=0.0;
double         ExtTakeProfit=0.0;
double         ExtPoints=0.0;
bool           first_start=false;
long           last_trade_time=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(!m_symbol.Name(Symbol()))              // sets symbol name
      return(INIT_FAILED);

   tick_count+=InpTicks;                     // будем запрашивать "tick_count" + "за XXX тиков"
   ExtStopLoss=InpStopLoss*Point();
   ExtTakeProfit=InpTakeProfit*Point();
   ExtPoints=InpPoints*Point();
   first_start=false;
//--- запросим тики (первое заполнение)
   int copied=CopyTicks(Symbol(),tick_array_curr,tick_flags,tick_from,tick_count);
   if(copied!=tick_count)
      first_start=false;
   else
     {
      first_start=true;
      ArrayCopy(tick_array_prev,tick_array_curr);
     }
   m_trade.SetExpertMagicNumber(InpMagicNum);
   m_trade.SetTypeFillingBySymbol(Symbol());
   m_trade.SetMarginMode();
   m_trade.LogLevel(LOG_LEVEL_NO);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- проверка на первый старт
   int copied=-1;
   if(!first_start)
     {
      copied=CopyTicks(Symbol(),tick_array_curr,tick_flags,tick_from,tick_count);
      if(copied!=tick_count)
         first_start=false;
      else
        {
         first_start=true;
         ArrayCopy(tick_array_prev,tick_array_curr);
        }
     }
//--- запросим тики
   copied=CopyTicks(Symbol(),tick_array_curr,tick_flags,tick_from,tick_count);
   if(copied!=tick_count)
      return;
   int index_new=-1;
   long last_time_msc=tick_array_prev[tick_count-1].time_msc;
   for(int i=(int)tick_count-1;i>=0;i--)
     {
      if(last_time_msc==tick_array_curr[i].time_msc)
        {
         index_new=i;
         break;
        }
     }
//---
   if(index_new!=-1 && !IsOpenedByMagic(InpMagicNum))
     {
      int shift=(int)tick_count-1-index_new-InpTicks;   // смещение в текущем массиве тиков
      shift=(shift<0)?0:shift;
      if(tick_array_curr[tick_count-1].ask-tick_array_curr[shift].ask>ExtPoints)
        {
         //--- открываем BUY
         double sl=(InpStopLoss==0)?0.0:tick_array_curr[tick_count-1].ask-ExtStopLoss;
         double tp=(InpTakeProfit==0)?0.0:tick_array_curr[tick_count-1].ask+ExtTakeProfit;
         m_trade.Buy(InpLots,m_symbol.Name(),tick_array_curr[tick_count-1].ask,
                     m_symbol.NormalizePrice(sl),
                     m_symbol.NormalizePrice(tp));
         last_trade_time=tick_array_curr[tick_count-1].time_msc;
        }
      else if(tick_array_curr[shift].bid-tick_array_curr[tick_count-1].bid>ExtPoints)
        {
         //--- открываем SELL
         double sl=(InpStopLoss==0)?0.0:tick_array_curr[tick_count-1].bid-ExtStopLoss;
         double tp=(InpTakeProfit==0)?0.0:tick_array_curr[tick_count-1].bid+ExtTakeProfit;
         m_trade.Sell(InpLots,m_symbol.Name(),tick_array_curr[tick_count-1].bid,
                      m_symbol.NormalizePrice(sl),
                      m_symbol.NormalizePrice(tp));
         last_trade_time=tick_array_curr[tick_count-1].time_msc;
        }
     }
   ArrayCopy(tick_array_prev,tick_array_curr);
//---
  }
//+------------------------------------------------------------------+
//| Проверка на открытые позиций с магиком                           |
//+------------------------------------------------------------------+
bool IsOpenedByMagic(int MagicNumber)
  {
   int pos=0;
   uint total=PositionsTotal();
//---
   for(uint i=0; i<total; i++)
     {
      if(SelectByIndex(i))
         if(PositionGetInteger(POSITION_MAGIC)==MagicNumber)
            pos++;
     }
   return((pos>0)?true:false);
  }
//+------------------------------------------------------------------+
//| Select a position on the index                                   |
//+------------------------------------------------------------------+
bool SelectByIndex(const int index)
  {
   ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
//---
   if(margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      ulong ticket=PositionGetTicket(index);
      if(ticket==0)
         return(false);
     }
   else
     {
      string name=PositionGetSymbol(index);
      if(name=="")
         return(false);
     }
//---
   return(true);
  }
//+------------------------------------------------------------------+

Торговая стратегия №3

Для создания торговой стратегии, которая бы косвенно измеряла скорость движения цены, необходимо выбрать трендовый индикатор, а также фильтр, который бы подтверждал его возможные сигналы. Для этих целей было решено выбрать трендовый индикатор Trend direction and force, а в качестве фильтра взять скользящую среднюю Халла HMA Color. На рис.7 ниже показаны сигналы входа на продажу и покупку.

Рис.7 Условия входа по торговой стратегии

Параметр Описание
Используемый индикатор Trend direction and force
Используемый индикатор HMA Color
Таймфрейм M30 и выше
Условия на покупку Значение Trend direction and fast выше порогового(линия окрашивается в синий цвет), а скользящая средняя Халла растет и окрашивается в синий цвет.
Условия на продажу Значение Trend direction and fast ниже порогового(линия окрашивается в красный цвет), а скользящая средняя Халла падает и окрашивается в красный цвет.
Условия выхода   Тейк-профит/Стоп-лосс


Тестирование методов измерения скорости движения цен

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

  • Интервал: Последний год.( На момент написания статьи это 01.01.2019 — 26.05.2019)
  • Валютная пара: EURUSD.
  • Режим торговли: Без задержки (Представленные стратегии не относятся к высокочастотным, поэтому влияние задержек было бы очень мало). 
  • Тестирование: OHLC на М1 (Предварительное тестирование на реальных тиках оказалось почти неотличимо от этого режима). 
  • Начальный депозит: 1000 USD.
  • Плечо: 1:500.
  • Сервер: MetaQuotes-Demo.
  • Котировки: 5-значные.

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

Торговая стратегия №1.

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

Рис.8 Двадцать лучших результатов оптимизации торговой стратегии №1

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


Рис.9 Результат тестирования лучшего результата оптимизации торговой стратегии №1

При тестировании неизменным лотом в 0.1 видно, что прирост почти в 100%, однако коэффициент Шарпа всего 0.33 и значение Z-Score равное -0.16, а это означает, что стройности в торговле нет, и она в текущем тесте была больше случайна, чем подвержена системному подходу. 

Торговая стратегия №2.

Для тестирования следующей стратегии, в силу ее особенностей, необходимо изменить одно условие тестирования:

  • Тестирование: заменить OHLC на М1 (Предварительное тестирование на реальных тиках оказалось почти неотличимо от этого режима) на "Every ticks based on real ticks".

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

Рис.10 Двадцать лучших результатов оптимизации торговой стратегии №2

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


Рис.11 Результат тестирования лучшего результата оптимизации торговой стратегии №2

Да, здесь неплохой коэффициент Шарпа, потому как прибыль в более чем 30% достигнута лишь за 10 сделок. 

Торговая стратегия №3. 

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

Также посмотрим лучшие варианты оптимизации текущей стратегии:

Рис.12 Двадцать лучших результатов оптимизации торговой стратегии №3

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


Рис.13 Результат тестирования лучшего результата оптимизации торговой стратегии №3

Несмотря на почти 100%-й прирост депозита и выделяющийся коэффициент Шарпа (это еще заметно по тому, что на достижение текущего уровня прибыли потребовалось 52 сделки, а ближайшие результаты почти в два раза меньше).А Z-Score показывает отрицательную зависимость между сделками. Отрицательная зависимость, в свою очередь, означает, что после профитной сделки с большой вероятностью последует проигрыш, а после проигрыша последует выигрыш. 

Выводы

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

Заключение

В конце статьи приложен архив со всеми перечисленными файлами, отсортированными по папкам. Поэтому для корректной работы достаточно положить папку MQL5 в корень терминала. Для того чтобы найти корень терминала, в котором находится папка MQL5, нужно в MetaTarder 5 нажать комбинацию клавиш Ctrl+Shift+D или воспользоваться контекстным меню, как показано на рис.14 ниже.


Рис.14 Поиск папки MQL5 в корне терминала MetaTrader 5

Программы, используемые в статье:

#
 Имя
Тип
Описание
1
Strategy_1.mq5 Эксперт  Эксперт по торговой стратегии №1
2 Strategy_2.mq5 Эксперт  Эксперт по торговой стратегии №2
3Strategy_3.mq5Эксперт  Эксперт по торговой стратегии №3
4 Engine.mqh Библиотека  Библиотека торговых функций.
 5Average Speed Индикатор  Используется в торговой стратегии №1
 6CAM Индикатор   Используется в торговой стратегии №1
 7Trend direction and force Индикатор   Используется в торговой стратегии №3
 8HMA_color Индикатор  Используется в торговой стратегии №3


Прикрепленные файлы |
MQL5.zip (743.69 KB)
Aleksandr Masterskikh
Aleksandr Masterskikh | 4 июн 2019 в 19:31

Очень хорошая статья, это то,что действительно нужно участникам финансовых рынков.

Фактор скорости (вместе с контролем уровней) - важнейший параметр для анализа рыночной динамики.

Спасибо автору!

Alexander_K
Alexander_K | 4 июн 2019 в 21:22
Для мгновенных скоростей необходимо рассматривать их распределение вероятностей. Оттуда находишь среднюю скорость, среднеквадратическую и т.д. Составляешь таблицы применимости к рынку. Но, это - большой труд, просто так за день статью не налабаешь.
Stanislav Korotky
Stanislav Korotky | 4 июн 2019 в 23:03
Не хватает сравнения форвардов (и желательно в более наглядном виде, чем таблицы).
Реter Konow
Реter Konow | 5 июн 2019 в 08:14
Стройное изложение сути. Однако замечу, что "скорость" движения цены образуется  из двух компонент: разница активности покупателей и продавцов (кто совершает больше маркетных сделок) и разницы объемов маркетных и лимитных заявок. Чем активнее одна из сторон покупает или продает по маркетной цене и чем меньше объем лимитных заявок противоположной стороны, тем большее количество пунктов цена будет проходить за единицу времени.

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

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


Реter Konow
Реter Konow | 5 июн 2019 в 08:54
Реter Konow:
...
То есть, нам остаётся неизвестна точная причина скорости цены, которую мы измеряем, а причина эта, на мой взгляд, не менее (даже более) важна показателя скорости.
Все таки, проблема решается. Если сделать индикатор объемов лимитных и маркетных заявок, который бы записывал в файл их текущее соотношение (данные можно брать из стакана цен), а потом перед тестированием загружать его данные в советника (только период тестирования должен быть тот же, что и период записанных данных) и анализируя изменения соотношения маркетных и противоположных лимитных заявок, и количество пройденных пунктов за единицу времени, можно сделать наблюдение за изменением активности сторон. Таким образом, получить полное представление о динамики главных факторов обуславливающих скорость движения цены и о роли каждого в каждый конкретный момент. Задача сложная, но выполнимая.
Библиотека для простого и быстрого создания программ для MetaTrader (Часть XI). Совместимость с MQL4 - События закрытия позиций Библиотека для простого и быстрого создания программ для MetaTrader (Часть XI). Совместимость с MQL4 - События закрытия позиций

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

Оценка индекса фрактальности, показателя Херста и возможность предсказания финансовых временных рядов Оценка индекса фрактальности, показателя Херста и возможность предсказания финансовых временных рядов

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

Библиотека для простого и быстрого создания программ для MetaTrader (Часть XII): Класс объекта "аккаунт", коллекция объектов-аккаунтов Библиотека для простого и быстрого создания программ для MetaTrader (Часть XII): Класс объекта "аккаунт", коллекция объектов-аккаунтов

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

Создаем кроссплатформенный советник-сеточник (Часть II): Сетка в рейндже в направлении тренда Создаем кроссплатформенный советник-сеточник (Часть II): Сетка в рейндже в направлении тренда

Сегодня мы попробуем разработать сеточный советник для работы в диапазоне в направлении тренда. То есть для инструментов Forex или рынков сырья. Как показали тесты, наш сеточник работал в прибыль с 2018 года. Но вот беда, с 2014 по 2018 год это был стабильный слив депозита