English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
preview
Разработка торговой системы на основе индикатора OBV

Разработка торговой системы на основе индикатора OBV

MetaTrader 5Трейдинг | 25 июля 2022, 08:32
945 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Введение

В этой статье мы изучим новый технический индикатор, который работает с объемами и позволяет взглянуть на происходящее на рынке с другого ракурса — мы поговорим об индикаторе On-Balance Volume (OBV), о его преимуществах, и попытаемся научиться использовать его с выгодой для торговли. В этой статье будут затронуты следующие темы:

  1. Определение индикатора OBV
  2. Стратегия по индикатору OBV
  3. Схема стратегии по индикатору OBV
  4. Торговая система по OBV
  5. Заключение

В части "Определение индикатора OBV" мы подробно познакомимся с индикатором, узнаем, что он из себя представляет, что он измеряет, и как он рассчитывается, а также рассмотрим пример его расчета. Это позволит научиться понимать индикатор и правильно его использовать. Затем узнаем, как использовать индикатор OBV, с помощью простых стратегий, основанных на концепции этого индикатора — в разделе "Стратегия по индикатору OBV". После того, как мы научимся его использовать на основе простых стратегий, мы разработаем схему, которая поможет нам написать MQL5-код этих стратегий. Такая схема/план поможет упорядочить и организовать шаги для создания советника. После разработки плана мы сможем перейти к написанию кода на MQL5 и получим советника, который можно будет использовать в MetaTrader 5 для автоматического и точного исполнения торговых стратегий.

Для создания советника в этой статье, как и в предыдущих, будем использовать язык MQL5 (MetaQuotes Language). Получившуюся программу будем запускать в торговой платформе MetaTrader 5. Если вы хотите узнать больше о платформе и редакторе, рекомендую почитать раздел "Как написать MQL5-код в редакторе MetaEditor" одной из моих прошлых статей. Там в деталях описывается, как установить терминал и где найти редактор кода. Также я рекомендую читателям самостоятельно проработать каждый представленный в статье фрагмент кода, ведь практика — важная часть обучения.

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

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


Определение индикатора OBV

В этой части мы более подробно узнаем об индикаторе балансового объема OBV. Но сначала давайте немного поговорим об объеме, ведь OBV — один из индикаторов объема. Итак, объем — это количество акций или контрактов, которые торгуются в течение определенного периода времени. Если объем большой, это означает, что по инструменту ведется активная торговля, и наоборот, если мы видим низкий объем, это означает, что инструмент активно не торгуется.

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

Объем также может служить подтверждением пробоев — реальные они или нет: если пробой совершается с большим объемом, это может служить сигналом того, что пробой продолжится. 

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

Индикатор балансового объема OBV (On-balance volume) был разработан Джозефом Грэнвиллом. Он измеряет положительный и отрицательный поток объемов. Давайте посмотрим, как же он рассчитывается. Итак, шаги расчета индикатора такие:

  1. Проверяем цену закрытия - выше или ниже предыдущего закрытия.
  2. Если цена закрытия превысила предыдущую, прибавляем объем к предыдущему значению OBV.
  3. Если оказалась ниже, вычитаем объем из предыдущего значения OBV.
  4. Если сегодняшнее закрытие равно вчерашнему, то сегодняшнее значение OBV будет равно вчерашнему значению OBV.

Давайте посмотрим на пример и рассчитаем индикатор OBV по шагам. Предположим, у нас есть следующие данные по инструменту:

День Закрытие Объем
1 54
2 55 10000
3 60 15000
4 65 20000
5 60 10000
6 55 5000
7 60 7000
8 50 7500
9 48.75 8000
10 49 5000
11 48 6000
12 47.75 7500
13 48 9000
14 47.50 10000
15 48 7000
16 47 7500
17 46 6000
18 44 5000
19 45 15000

Для расчета индикатора OBV по предыдущим данным:

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

Расчет OBV 1

Затем прибавим объем положительных дней к предыдущему значению OBV и вычтем объем отрицательных дней из предыдущего значения OBV.

Расчет OBV 2

Итак, мы рассчитали значения OBV, и они отображаются на графике в вид кривой, измеряя положительные и отрицательные объемы. К счастью, нам фактически не нужно рассчитывать OBV вручную, ведь есть готовый индикатор, который идет в стандартной поставке платформы MetaTrader 5. На рисунке ниже показано, как запустить этот индикатор на графике:

Запуск OBV на графике

После выбора индикатора будет открыто окно его настроек:

Запуск OBV на графике 1

1 — тип объемов

2  — цвет кривой объемов OBV

3 — стиль линии кривой OBV

4 — толщина линии кривой OBV

Настраиваем нужные параметры, нажимаем Ok, и индикатор запускается на графике:

OBV на графике


Стратегия по индикатору OBV

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

  • Стратегия первая: простое движение OBV

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

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

Текущий OBV > предыдущий OBV --> OBV растет

Текущий OBV < предыдущий OBV --> OBV снижается

  • Стратегия вторая: простая сила OBV

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

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

Текущий OBV > Среднее предыдущих четырех значений OBV --> OBV сильный

Текущий OBV < Среднее предыдущих четырех значений OBV --> OBV слабый

  • Стратегия третья: простая стратегия по OBV — восходящий тренд

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

Текущий OBV > предыдущий OBV и текущий максимум > предыдущий максимум --> Сильное движение во время восходящего тренда

  • Стратегия четыре: простая стратегия по OBV — нисходящий тренд

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

Текущий OBV < предыдущий OBV и текущий минимум < предыдущий минимум --> Сильное движение во время нисходящего тренда


Схема стратегии по индикатору OBV

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

Схема простого OBV

  • Стратегия первая: простое движение OBV

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

Ниже показана пошаговая схема, которая поможет разработать торговую систему по этой стратегии:

Схема OBV - Простое движение

  • Стратегия вторая: простая сила OBV

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

Вот такая пошаговая схема поможет разработать торговую систему по этой стратегии:

Схема OBV - Простая сила

  • Стратегия третья: простая стратегия по OBV — восходящий тренд

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

Вот такая пошаговая схема поможет разработать торговую систему по этой стратегии:

Схема стратегии OBV - Uptrend

  • Стратегия четыре: простая стратегия по OBV — нисходящий тренд

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

Вот такая пошаговая схема поможет разработать торговую систему по этой стратегии:

Схема стратегии OBV - Downtrend


Торговая система по OBV

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

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

  • Для этого создадим массив для значений OBV с помощью функции "double". Double — это один вещественный тип, число с плавающей запятой, то есть значение с дробной частью. Вообще, существует два типа чисел с плавающей запятой: double и float. Имя "double" означает, что точность этих чисел вдвое превышает точность типа float:
double OBVArray[];
  • Сортируем массив в обратном порядке, начиная с текущих данных, с помощью функции ArraySetAsSeries, она возвращает true или false:
ArraySetAsSeries(OBVArray,true);

  • Также определяем OBV с помощью функции iOBV, для этого создаем переменную integer OBVDef. Функция iOBV возвращает хэндл индикатора On Balance Volume и его параметры (символ, период, цена расчета):
int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);
  • Заполняем массив OBVArray значениями OBVDef, используя функцию CopyBuffer, которая возвращает количество скопированных данных. Параметры функции: хэндл индикатора, номер буфера, время начала, время окончания, буфер:
CopyBuffer(OBVDef,0,0,3,OBVArray);
  • Рассчитываем текущее значение OBV. Для этого предварительно создаем double-переменную OBVValue:
double OBVValue=OBVArray[0];
  • Создаем комментария с помощью функции comment, которая выведет на график сообщение с текущим значением OBV:
Comment("OBV Value is: ",OBVValue);

Вот так выглядит целиком код торговой системы, которая отображает на графике комментарий с текущим значением индикатора OBV:

//+------------------------------------------------------------------+
//|                                                   Simple OBV.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   //создание массива для OBV
   double OBVArray[];
   
   //сортировка массива по текущим данным
   ArraySetAsSeries(OBVArray,true);
   
   //определение OBV
   int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);
   
   //определение советника, буфера, сортировка в массиве
   CopyBuffer(OBVDef,0,0,3,OBVArray);
   
   //расчет текущего значения OBV
   double OBVValue=OBVArray[0];
   
   //вывод комментария со значением OBV
   Comment("OBV Value is: ",OBVValue);  
  }
//+------------------------------------------------------------------+

После этого компилируем код советника, и он появляется в окне Навигатора в терминале MetaTrader 5:

OBV в Навигаторе 1

Запускаем двойным кликом на файле или перетаскиваем на график, после чего появится следующее окно:

Окно простого OBV

Нажимаем OK, и программа (советник) запустится на графике, как показано на рисунке ниже:

Простой OBV на графике

Понять, что программа работает, можно будет по выведенным на график комментариям, как на примере ниже:

Тестовый сигнал простого OBV

Также можем проверить, что это то же самое значение, которое показывает индикатор On Balance Volume, встроенный в MetaTrader 5. Для этого запустим на графике нашего созданного советника и стандартный индикатор On Balance Volume. При этом обе программы будут показывать одинаковые значения, например, как показано на скриншоте ниже:

Одинаковый сигнал от простого OBV и индикатора

 Далее напишем торговые системы по каждой рассмотренной стратегии.

  • Стратегия первая: простое движение OBV

Как мы уже говорили, в соответствии с этой стратегией программа должна определять направление кривой OBV, сравнивая текущее значение OBV с предыдущим значением — если текущее значение больше предыдущего, это означает, что OBV растет, и на графике должен появиться комментарий "OBV is rising" (OBV растет), а также два значения OBV — текущее и предыдущее. Ниже приведен полный код для создания такой стратегии:

//+------------------------------------------------------------------+
//|                                          Simple OBV movement.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
//создание двух массивов для OBV
   double OBVArray1[];
   double OBVArray2[];

//сортировка массива по текущим данным
   ArraySetAsSeries(OBVArray1,true);
   ArraySetAsSeries(OBVArray2,true);

//определение OBV
   int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);

//определение советника, буфера, сортировка в массиве
   CopyBuffer(OBVDef,0,0,3,OBVArray1);
   CopyBuffer(OBVDef,0,0,3,OBVArray2);

//получение значения текущего и предыдущего OBV
   double OBVCurrentValue=NormalizeDouble(OBVArray1[0],5);
   double OBVPrevValue=NormalizeDouble(OBVArray2[1],5);

//задание условий роста и снижения OBV на основе его значений   
   if(OBVCurrentValue>OBVPrevValue)
     {
      Comment("OBV is rising","\n","OBV current is ",OBVCurrentValue,"\n","OBV previous is ",OBVPrevValue);
     }

   if(OBVCurrentValue<OBVPrevValue)
     {
      Comment("OBV is declining","\n","OBV current is ",OBVCurrentValue,"\n","OBV previous is ",OBVPrevValue);
     }

  }
//+------------------------------------------------------------------+
  • Отличия в этом коде:
 Создание двух массивов для OBV:
double OBVArray1[];
double OBVArray2[];

Сортировка этих двух массивов от текущих данных:

ArraySetAsSeries(OBVArray1,true);
ArraySetAsSeries(OBVArray2,true);

Заполняем массивы:

CopyBuffer(OBVDef,0,0,3,OBVArray1);
CopyBuffer(OBVDef,0,0,3,OBVArray2);

Получаем значения текущего и предыдущего OBV с помощью функции NormalizeDouble, которая возвращает значение типа double с заданной точностью. Также для этого мы создали double-переменные OBVCurrentValue и OBVPrevValue. Параметры функции NormalizeDouble — значение и точность, значение будет OBVArray, а цифр будет 5, то есть количество цифр после запятой:

double OBVCurrentValue=NormalizeDouble(OBVArray1[0],5);
double OBVPrevValue=NormalizeDouble(OBVArray2[1],5);

Установка условий роста и снижения OBV с помощью функции if:

if(OBVCurrentValue>OBVPrevValue)
   {
    Comment("OBV is rising","\n","OBV current is ",OBVCurrentValue,"\n","OBV previous is ",OBVPrevValue);
   }

if(OBVCurrentValue<OBVPrevValue)
   {
    Comment("OBV is declining","\n","OBV current is ",OBVCurrentValue,"\n","OBV previous is ",OBVPrevValue);
   }

После компиляции программа советника появится в окне Навигатора в MetaTrader 5, в подпапке "Expert Advisors", как показано на скриншоте ниже:

OBV в Навигаторе 2

Запускаем двойным кликом на файле или перетаскиваем на график, после чего появится следующее окно:

Окно программы OBV - Простое движение

Нажимаем OK, и программа (советник) запустится на графике, как показано на рисунке ниже:

OBV - Простое движение - на графике

Ниже приведены примеры тестовых сигналов, сгенерированных этой стратегией.

OBV растет:

OBV - Простое движение - сигнал роста

Снижение OBV:

OBV - Простое движение - сигнал снижения

  • Стратегия вторая: простая сила OBV

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

//+------------------------------------------------------------------+
//|                                          Simple OBV Strength.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   //создание шести массивов для OBV
   double OBVArray0[];
   double OBVArray1[];
   double OBVArray2[];
   double OBVArray3[];
   double OBVArray4[];
   
   //сортировка массивов по текущим данным
   ArraySetAsSeries(OBVArray0,true);   
   ArraySetAsSeries(OBVArray1,true);
   ArraySetAsSeries(OBVArray2,true);
   ArraySetAsSeries(OBVArray3,true);
   ArraySetAsSeries(OBVArray4,true);
   
   //определение OBV
   int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);
   
   //определение советника, буфера, сортировка в массивах
   CopyBuffer(OBVDef,0,0,5,OBVArray0);
   CopyBuffer(OBVDef,0,0,5,OBVArray1);
   CopyBuffer(OBVDef,0,0,5,OBVArray2);
   CopyBuffer(OBVDef,0,0,5,OBVArray3);
   CopyBuffer(OBVDef,0,0,5,OBVArray4);
   
   //получение значения текущего и пяти предыдущих OBV
   double OBVCurrentValue=NormalizeDouble(OBVArray0[0],5);         
   double OBVPrevValue1=NormalizeDouble(OBVArray1[1],5);
   double OBVPrevValue2=NormalizeDouble(OBVArray2[2],5);
   double OBVPrevValue3=NormalizeDouble(OBVArray3[3],5);
   double OBVPrevValue4=NormalizeDouble(OBVArray4[4],5);
   
   //вычисление среднего значения предыдущих OBV
   double OBVAVG=((OBVPrevValue1+OBVPrevValue2+OBVPrevValue3+OBVPrevValue4)/4);
   
   if(OBVCurrentValue>OBVAVG)
   {
      Comment("OBV is strong","\n","OBV current is ",OBVCurrentValue,"\n","OBV Average is ",OBVAVG,"\n","Previous four OBV Values: ", 
      "\n", "1= ",OBVPrevValue1,"\n", "2= ",OBVPrevValue2,"\n", "3= ",OBVPrevValue3,"\n", "4= ",OBVPrevValue4);
   }
   
   if(OBVCurrentValue<OBVAVG)
   {
      Comment("OBV is weak","\n","OBV current is ",OBVCurrentValue,"\n","OBV Average is ",OBVAVG,"\n","Previous four OBV Values: ",
      "\n", "1= ",OBVPrevValue1,"\n", "2= ",OBVPrevValue2,"\n", "3= ",OBVPrevValue3,"\n", "4= ",OBVPrevValue4);
   }
   
  }
//+------------------------------------------------------------------+
  • Отличия в этом коде:

Создание пяти массивов значений OBV:

double OBVArray0[];
double OBVArray1[];
double OBVArray2[];
double OBVArray3[];
double OBVArray4[];

Сортировка созданных массивов от текущих данных:

ArraySetAsSeries(OBVArray0,true);   
ArraySetAsSeries(OBVArray1,true);
ArraySetAsSeries(OBVArray2,true);
ArraySetAsSeries(OBVArray3,true);
ArraySetAsSeries(OBVArray4,true);

Заполнение их определенным OBVDef:

CopyBuffer(OBVDef,0,0,5,OBVArray0);
CopyBuffer(OBVDef,0,0,5,OBVArray1);
CopyBuffer(OBVDef,0,0,5,OBVArray2);
CopyBuffer(OBVDef,0,0,5,OBVArray3);
CopyBuffer(OBVDef,0,0,5,OBVArray4);

Получение значений текущего и четырех предыдущих OBV:

double OBVCurrentValue=NormalizeDouble(OBVArray0[0],5);         
double OBVPrevValue1=NormalizeDouble(OBVArray1[1],5);
double OBVPrevValue2=NormalizeDouble(OBVArray2[2],5);
double OBVPrevValue3=NormalizeDouble(OBVArray3[3],5);
double OBVPrevValue4=NormalizeDouble(OBVArray4[4],5);

Расчет среднего значения предыдущих четырех значений OBV после создания переменной double OBVAVG:

double OBVAVG=((OBVPrevValue1+OBVPrevValue2+OBVPrevValue3+OBVPrevValue4)/4);

Установка условий сильного и слабого OBV с выводом комментария:

if(OBVCurrentValue>OBVAVG)
{
 Comment("OBV is strong","\n","OBV current is ",OBVCurrentValue,"\n","OBV Average is ",OBVAVG,"\n","Previous four OBV Values: ", 
  "\n", "1= ",OBVPrevValue1,"\n", "2= ",OBVPrevValue2,"\n", "3= ",OBVPrevValue3,"\n", "4= ",OBVPrevValue4);
}
   
if(OBVCurrentValue<OBVAVG)
{
 Comment("OBV is weak","\n","OBV current is ",OBVCurrentValue,"\n","OBV Average is ",OBVAVG,"\n","Previous four OBV Values: ",
  "\n", "1= ",OBVPrevValue1,"\n", "2= ",OBVPrevValue2,"\n", "3= ",OBVPrevValue3,"\n", "4= ",OBVPrevValue4);
}

После компиляции программа советника появится в окне Навигатора в MetaTrader 5:

OBV в Навигаторе 3

После выбора файла для исполнения в MetaTrader 5 откроется окно советника, показанное ниже:

Окно стратегии OBV - Простая сила

Нажимаем OK, и программа (советник) запустится на графике, как показано на рисунке ниже:

OBV - Простая сила - на графике

Ниже приведены примеры сигналов от этой программы:

Сильный OBV:

OBV - Сила - сигнал сильного OBV

Слабый OBV:

OBV - Сила - сигнал слабого OBV

  • Стратегия третья: простая стратегия по OBV — восходящий тренд

Согласно условиям этой стратегии необходимо определять, превысил ли текущий максимум предыдущий и превысило ли текущее значение OBV предыдущее. Поэтому, будем сравнивать два значения OBV (текущее и предыдущее) и два максимума (текущий и предыдущий) — если условия подтвердятся, получим сигнал о наличии сильного движения во время восходящего тренда "Strong move during uptrend". Ниже приведен полный код для создания такой стратегии:

//+------------------------------------------------------------------+
//|                                         Simple OBV - Uptrend.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   //создаем строковую переменную для сигнала
   string signal="";
   
   //создаем два массива для OBV
   double OBVArray0[];
   double OBVArray1[];
   
   //создаем два массива цен
   MqlRates PriceArray0[];
   MqlRates PriceArray1[];
   
   //сортировка массивов OBV от текущих данных
   ArraySetAsSeries(OBVArray0,true);   
   ArraySetAsSeries(OBVArray1,true);   
   
   //сортировка ценовых массивов от текущих данных
   ArraySetAsSeries(PriceArray0,true);
   ArraySetAsSeries(PriceArray1,true);     
      
   //заполняем массивы ценовыми данными
   int Data0=CopyRates(_Symbol,_Period,0,3,PriceArray0);
   int Data1=CopyRates(_Symbol,_Period,0,3,PriceArray1);
   
   //определение OBV
   int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);

   //определение советника, буфера, сортировка в массивах
   CopyBuffer(OBVDef,0,0,3,OBVArray0);
   CopyBuffer(OBVDef,0,0,3,OBVArray1);
            
   //получаем значения текущего и предыдущего OBV
   double OBVCurrentValue=NormalizeDouble(OBVArray0[0],5);         
   double OBVPrevValue=NormalizeDouble(OBVArray1[1],5);
    
   //получаем значения текущего и предыдущего максимума
   double CurrentHighValue=NormalizeDouble(PriceArray0[0].high,5);         
   double PrevHighValue=NormalizeDouble(PriceArray1[1].high,5); 
      
   //сигнал сильного движения
   //если OBVCurrentValue>OBVPrevValue && текущий макс > предыдущий макс
   if(OBVCurrentValue > OBVPrevValue && PriceArray0[0].high>PriceArray0[1].high)
   {
      signal="Strong move during uptrend";
   }

   //комментарий с сигналом
   Comment("The signal is ",signal,"\n","OBVCurrentValue is :",OBVCurrentValue,
   "\n","OBVPrevValue is :", OBVPrevValue,"\n","Current high is :",CurrentHighValue,"\n","Previous high is :",PrevHighValue);            
  }
//+------------------------------------------------------------------+

Отличия в этом коде:

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

string signal="";

Создаем два массива для значений OBV с помощью функции double и двух массивов цен с помощью функции MqlRates, хранящей информацию о ценах, объеме и спреде:

//создаем два массива для OBV
double OBVArray0[];
double OBVArray1[];
   
//создаем два массива цен
MqlRates PriceArray0[];
MqlRates PriceArray1[];1[];

Сортируем эти массивы как временной ряд — начиная с текущих данных:

//сортировка массивов OBV от текущих данных
ArraySetAsSeries(OBVArray0,true);   
ArraySetAsSeries(OBVArray1,true);   
   
//сортировка ценовых массивов от текущих данных
ArraySetAsSeries(PriceArray0,true);
ArraySetAsSeries(PriceArray1,true);

Заполняем ценовые массивы ценами с помощью функции CopyRates, которая получает исторические данные структуры MqlRates — для этого мы создаем целочисленные переменные Data0 и Data1 для каждого массива:

int Data0=CopyRates(_Symbol,_Period,0,3,PriceArray0);
int Data1=CopyRates(_Symbol,_Period,0,3,PriceArray1);

Определяем OBV и заполняем им два массива OBVArray:

int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);

CopyBuffer(OBVDef,0,0,3,OBVArray0);
CopyBuffer(OBVDef,0,0,3,OBVArray1);

Получаем значения OBV и максимумов:

//получаем значения текущего и предыдущего OBV
double OBVCurrentValue=NormalizeDouble(OBVArray0[0],5);         
double OBVPrevValue=NormalizeDouble(OBVArray1[1],5);
    
//получаем значения текущего и предыдущего максимума
double CurrentHighValue=NormalizeDouble(PriceArray0[0].high,5);         
double PrevHighValue=NormalizeDouble(PriceArray1[1].high,5); 

Определяем условия сильного движения во время восходящего тренда и вывод комментария "Strong move during uptrend":

Comment("The signal is ",signal,"\n","OBVCurrentValue is :",OBVCurrentValue,
"\n","OBVPrevValue is :", OBVPrevValue,"\n","Current high is :",CurrentHighValue,"\n","Previous high is :",PrevHighValue); 

Если скомпилировать код, то советник появится в окне Навигатора:

OBV в Навигаторе 4

После выбора файла для исполнения в MetaTrader 5 откроется окно советника, показанное ниже:

Окно стратегии OBV - Uptrend

Нажимаем OK, и программа (советник) запустится на графике, как показано на рисунке ниже:

Советник по стратегии OBV - Uptrend на графике

Ниже показаны примеры сигналов, сгенерированных во время тестирования.

Сигнал с окном данных и текущим значением:

Сигнал советника по стратегии OBV Uptrend с текущим окном данных

Сигнал с окном данных и предыдущим значением:

Сигнал советника по стратегии OBV Uptrend с предыдущим окном данных

  • Стратегия четыре: простая стратегия по OBV — нисходящий тренд

Эта стратегия противоположна предыдущей — согласно условиям этой стратегии необходимо определять, совпало ли условие: текущий минимум ниже предыдущего и текущее значение OBV ниже предыдущего. Поэтому, будем сравнивать два значения OBV (текущее и предыдущее) и два минимума (текущий и предыдущий) — если условия подтвердятся, получим сигнал о наличии сильного движения во время нисходящего тренда "Strong move during downtrend". Ниже приведен полный код для создания такой стратегии:


//+------------------------------------------------------------------+
//|                                       Simple OBV - Downtrend.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   //создаем строковую переменную для сигнала
   string signal="";
   
   //создаем два массива для OBV
   double OBVArray0[];
   double OBVArray1[];
   
   //создаем два массива цен
   MqlRates PriceArray0[];
   MqlRates PriceArray1[];
   
   //сортировка массивов OBV от текущих данных
   ArraySetAsSeries(OBVArray0,true);   
   ArraySetAsSeries(OBVArray1,true);   
   
   //сортировка ценовых массивов от текущих данных
   ArraySetAsSeries(PriceArray0,true);
   ArraySetAsSeries(PriceArray1,true);     
      
   //заполняем массив ценовыми данными
   int Data0=CopyRates(_Symbol,_Period,0,3,PriceArray0);
   int Data1=CopyRates(_Symbol,_Period,0,3,PriceArray1);
   
   //определение OBV
   int OBVDef =iOBV(_Symbol, _Period,VOLUME_TICK);

   //определение советника, буфера, сортировка в массивах
   CopyBuffer(OBVDef,0,0,3,OBVArray0);
   CopyBuffer(OBVDef,0,0,3,OBVArray1);
            
   //получение значения текущего и предыдущего OBV
   double OBVCurrentValue=NormalizeDouble(OBVArray0[0],5);         
   double OBVPrevValue=NormalizeDouble(OBVArray1[1],5);
    
   //получение значения текущего и предыдущего OBV
   double CurrentLowValue=NormalizeDouble(PriceArray0[0].low,5);         
   double PrevLowValue=NormalizeDouble(PriceArray1[1].low,5); 
       
   //сигнал сильного движения
   //если OBVCurrentValue<OBVPrevValue && текущий минимум < предыдущий минимум
   if(OBVCurrentValue < OBVPrevValue && PriceArray0[0].low<PriceArray0[1].low)
   {
      signal="Strong move during downtrend";
   }

   //комментарий с сигналом
   Comment("The signal is ",signal,"\n","OBVCurrentValue is :",OBVCurrentValue,
   "\n","OBVPrevValue is :", OBVPrevValue,"\n","Current low is :",CurrentLowValue,"\n","Previous low is :",PrevLowValue);            
  }
//+------------------------------------------------------------------+

  • Отличия в этом коде:

Определяем условия сильного движения во время нисходящего тренда и вывод комментария "Strong move during downtrend":

Comment("The signal is ",signal,"\n","OBVCurrentValue is :",OBVCurrentValue,
"\n","OBVPrevValue is :", OBVPrevValue,"\n","Current low is :",CurrentLowValue,"\n","Previous low is :",PrevLowValue); 

Компилируем код и находим советник в окне Навигатора в MetaTrader 5:

OBV в Навигаторе 5

Перетаскиваем нашу программу из Навигатора на график. При этом откроется вот такое окно:

Советник по стратегии OBV - Downtrend

Нажимаем OK, и программа (советник) запустится на графике, как показано на рисунке ниже:

Советник по стратегии OBV - Downtrend на графике

Примеры сигналов, сгенерированных на основе этой стратегии.

Сигнал советника с окном данных и текущими данными:

Сигнал советника по стратегии OBV Downtrend с текущим окном данных

Сигнал советника с окном данных и предыдущими данными:

Сигнал советника по стратегии OBV Downtrend с предыдущим окном данных


Заключение

Итак, в этой статье мы познакомились с еще одним техническим индикатором, использующим в расчетах объемы. Такие данные позволяют увидеть иную перспективу на графике, которая поможет сделать торговые решения лучше. Это индикатор Балансового объема - On Balance Volume (OBV). Мы узнали, что он означает, что измеряет и как его рассчитать вручную (исключительно для того, чтобы понять его суть, хотя фактически мы сами его не рассчитываем). Мы также узнали, как можно использовать этот индикатор, познакомились с несколькими простыми стратегиями на его основе, которые могут быть полезны в торговле или могут помочь реализовать новые идеи — ведь это основная цель этой и других статей этой серии. Мы разработали план для каждой рассмотренной стратегии, который помогает написать код торговой системы на основе каждой из стратегий. И затем для каждой стратегии мы создали советник на языке MQL5, который можно запускать в торговой платформе MetaTrader 5 для автоматической и точной генерации сигналов в соответствии с заданными условиями и правилами каждой стратегии.

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

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

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

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/10961

Прикрепленные файлы |
Simple_OBV.mq5 (1.1 KB)
Разработка торговой системы на основе индикатора Накопления/Распределения - Accumulation/Distribution Разработка торговой системы на основе индикатора Накопления/Распределения - Accumulation/Distribution
Представляю вашему вниманию новую статью из серии, в которой мы учимся создавать торговые системы на основе популярных технических индикаторов. В этой статье мы будем изучать индикатор Накопления/Распределения (Accumulation/Distribution, A/D). Также мы разработаем торговую систему на языке MQL5 для работы в платформе MetaTrader 5, используя несколько простых стратегий.
DoEasy. Элементы управления (Часть 12): Базовый объект-список, WinForms-объекты ListBox и ButtonListBox DoEasy. Элементы управления (Часть 12): Базовый объект-список, WinForms-объекты ListBox и ButtonListBox
В статье создадим базовый объект списков WinForms-объектов и два новых объекта: ListBox и ButtonListBox.
Разработка торгового советника с нуля (Часть 21): Новая система ордеров (IV) Разработка торгового советника с нуля (Часть 21): Новая система ордеров (IV)
Наконец-то визуальная система заработает... хотя пока не до конца. Здесь мы закончим вносить основные изменения, которых будет не мало, но они все необходимы, и вся работа будет достаточно интересной.
Разработка торгового советника с нуля (Часть 20): Новая система ордеров (III) Разработка торгового советника с нуля (Часть 20): Новая система ордеров (III)
Продолжим внедрение новой системы ордеров. Создание такой системы требует хорошего владения MQL5, а также понимания того, как на самом деле работает платформа MetaTrader 5 и какие ресурсы она нам предоставляет.