Смотри, как бесплатно скачать роботов
Ищи нас в Twitter!
Ставь лайки и следи за новостями
Интересный скрипт?
Поставь на него ссылку - пусть другие тоже оценят
Понравился скрипт?
Оцени его работу в терминале MetaTrader 5
Советники

MACD Sample - эксперт для MetaTrader 5

Опубликовал:
MetaQuotes
Просмотров:
14574
Рейтинг:
(51)
Опубликован:
2014.03.04 16:03
Обновлен:
2016.11.22 07:33
Нужен робот или индикатор на основе этого кода? Закажите его на бирже фрилансеров Перейти на биржу

Советник MACD Sample входит в комплект стандартной поставки клиентского терминала MetaTrader 5 и представляет собой пример советника, торгующего при помощи индикатора MACD.

Файл советника MACD Sample.mq5 располагается в папке: "каталог_данных_терминала\MQL5\Experts\Examples\MACD\". Данный советник представляет собой пример использования объектно-ориентированного подхода к разработке советников.

Рассмотрим подробнее структуру этого советника и принцип его работы.


1. Свойства советника

1.1. Свойства советника

//+------------------------------------------------------------------+
//|                                                  MACD Sample.mq5 |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2009-2013, MetaQuotes Software Corp."
#property link        "https://www.mql5.com"
#property version     "5.20"
#property description "It is important to make sure that the expert works with a normal"
#property description "chart and the user did not make any mistakes setting input"
#property description "variables (Lots, TakeProfit, TrailingStop) in our case,"
#property description "we check TakeProfit on a chart of more than 2*trend_period bars"

Первые 5 строк содержат комментарий, следующие 7 строк задают свойства MQL5-программы (copyright, link, version, description) при помощи директивы препроцессора #property.

При запуске советника они отображаются во вкладке "Общие":

Советник MACD Sample

Рис. 1. Общие параметры советника MACD Sample

1.2. Включаемые файлы

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

  • Trade.mqh (CTrade - класс для совершения торговых операций);
  • SymbolInfo.mqh (CSymbolInfo - класс для работы со свойствами торгового инструмента);
  • PositionInfo.mqh (CPositionInfo - класс для работы со свойствами открытой позиции);
  • AccountInfo.mqh (CAccountInfo - класс для работы со свойствами торгового счета).
//--- включаемые файлы 
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>

Экземпляры соответствующих классов в дальнейшем используются как переменные-члены класса CExpert (раздел 3).

1.3. Входные параметры

После этого указываются тип, наименования, значения по умолчанию и комментарии, роль которых показана на рис. 2.

//--- входные параметры советника
input double InpLots          =0.1; // Lots
input int    InpTakeProfit    =50;  // Take Profit (in pips)
input int    InpTrailingStop  =30;  // Trailing Stop Level (in pips)
input int    InpMACDOpenLevel =3;   // MACD open level (in pips)
input int    InpMACDCloseLevel=2;   // MACD close level (in pips)
input int    InpMATrendPeriod =26;  // MA trend period

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

InpLots - торговый объем, параметры InpTakeProfit и InpTrailingStop определяют уровни Take Profit и Trailing Stop,

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

Рис. 2. Входные параметры советника MACD Sample

Рис. 2. Входные параметры советника MACD Sample


1.4. Глобальные переменные

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

int ExtTimeOut=10; // время (в секундах) между торговыми операциями

После объявления класса CSampleExpert в строке 76 объявляется другая глобальная переменная: ExtExpert - экземпляр класса CSampleExpert:

//--- глобальная переменная ExtExpert
CSampleExpert ExtExpert;

Объект ExtExpert (экземпляр класса CSampleExpert) содержит базовую логику торговой стратегии (раздел 3).


2. Функции обработки событий

Функции обработки событий

2.1. Функция инициализации OnInit()

Функция OnInit() вызывается один раз при первом запуске советника. В обработчике события OnInit() обычно производится подготовка советника к работе: проверка корректности входных параметров, инициализация индикаторов, переменных и т.д. В случае критических ошибок, при которых дальнейшая работа не имеет смысла, используется выход из функции с кодом возврата INIT_FAILED.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//--- инициализация и создание всех необходимых объектов
   if(!ExtExpert.Init())
      return(INIT_FAILED);
//--- успешная инициализация
   return(INIT_SUCCEEDED);
  }

В данном случае вызывается метод Init() объекта ExtExpert, который возвращает true или false в зависимости от успешности подготовки всех объектов, необходимых для работы (подробнее в разделе 3.4). В случае ошибки производится выход из функции OnInit() с кодом возврата INIT_FAILED - это правильный способ завершения работы советника/индикатора в случае неудачной инициализации.


2.2. Функция OnTick()

Функция OnTick() вызывается каждый раз при поступлении новой котировки по символу графика, на котором запущен советник.

//+------------------------------------------------------------------+
//| Expert new tick handling function                                |
//+------------------------------------------------------------------+
void OnTick(void)
  {
   static datetime limit_time=0; // хранит последнее время вызова + timeout
//--- не производить работу, если не прошло указанное время
   if(TimeCurrent()>=limit_time)
     {
      //--- проверка данных
      if(Bars(Symbol(),Period())>2*InpMATrendPeriod)
        {
         //--- после вызова метода Processing() увеличиваем значение limit_time на ExtTimeOut 
         if(ExtExpert.Processing())
            limit_time=TimeCurrent()+ExtTimeOut;
        }
     }
  }

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

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


2.3. Функция деинициализации OnDeInit()

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

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


3. Класс CSampleExpert

3.1. Класс CSampleExpert

//+------------------------------------------------------------------+
//| Класс советника MACD Sample                                      |
//+------------------------------------------------------------------+
class CSampleExpert
  {
protected: 
   //--- protected переменные-члены класса доступны только внутри методов класса 
   double            m_adjusted_point;             // множитель для 3/5-значных котировок
   CTrade            m_trade;                      // экземпляр класса CTrade
   CSymbolInfo       m_symbol;                     // экземпляр класса CSymbolInfo
   CPositionInfo     m_position;                   // экземпляр класса CPositionInfo
   CAccountInfo      m_account;                    // экземпляр класса CAccountInfo
   //--- хендлы индикаторов
   int               m_handle_macd;                // хендл индикатора MACD
   int               m_handle_ema;                 // хендл индикатора Moving Average
   //--- индикаторные буферы
   double            m_buff_MACD_main[];           // буфер главной линии индикатора MACD
   double            m_buff_MACD_signal[];         // буфер сигнальной линии индикатора MACD
   double            m_buff_EMA[];                 // буфер индикатора EMA
   //--- текущие значения индикаторов
   double            m_macd_current;
   double            m_macd_previous;
   double            m_signal_current;
   double            m_signal_previous;
   double            m_ema_current;
   double            m_ema_previous;
   //--- уровни (в стандартных пунктах)
   double            m_macd_open_level;
   double            m_macd_close_level;
   double            m_traling_stop;
   double            m_take_profit;

public: 
   //--- конструктор
                     CSampleExpert(void);
   //--- деструктор
                     ~CSampleExpert(void);
   //--- public-методы являются доступными извне, их можно вызывать вне класса 
   //--- метод инициализации
   bool              Init(void);
   //--- метод деинициализации
   void              Deinit(void);
   //--- метод обработки
   bool              Processing(void);
protected: 
   //--- protected-методы доступны только внутри методов класса 
   bool              InitCheckParameters(const int digits_adjust);
   bool              InitIndicators(void);
   bool              LongClosed(void);
   bool              ShortClosed(void);
   bool              LongModified(void);
   bool              ShortModified(void);
   bool              LongOpened(void);
   bool              ShortOpened(void);
  };

Класс советника содержит декларацию переменных (членов класса) и функций (методов класса).

Для удобства работы с переменными все переменные-члены класса содержат префикс "m_" (member), который указывает на то, что данная переменная является членом класса. Перед объявлением переменной или метода указывается ее тип (или возвращаемое значение для функций).

Видимость переменных и методов-членов класса задается при помощи модификаторов доступа. В классе CSampleExpert используется модификаторы protected и public. Все переменные и методы, объявленные в секции public, являются публичными и доступны извне. Класс CSampleExpert имеет 5 таких методов:

  1. CSampleExpert(void) - конструктор  (вызывается автоматически при создании экземпляра класса);
  2. ~CSampleExpert(void) - деструктор (вызывается автоматически при удалении экземпляра класса);
  3. bool Init(void) - метод инициализации, в котором производится подготовка все данных, необходимых для работы;
  4. void Deinit(void) - метод деинициализации;
  5. bool Processing(void) - метод обработки.

Переменные-члены класса CSampleExpert, объявленные с модификатором доступа protected, будут доступны только внутри методов класса CSampleExpert (и его потомков).

  1. double           m_adjusted_point - переменная-множитель для корректной работы с 3/5-значными котировками;
  2. CTrade          m_trade - экземпляр класса СTrade;
  3. CSymbolInfo  m_symbol - экземпляр класса CSymbolInfo;
  4. CPositionInfo  m_position - экземпляр класса СPositionInfo;
  5. CAccountInfo  m_account - экземпляр класса CAccountInfo;
  6. int                 m_handle_macd - переменная для хранения значения хендла индикатора MACD.
  7. int                 m_handle_ema - переменная для хранения значения хендла индикатора EMA;
  8. double           m_buff_MACD_main[] - динамический массив значений типа double, используется для запроса значений основной линии индикатора MACD;
  9. double           m_buff_MACD_signal[] - динамический массив значений типа double, используется для запроса значений сигнальной линии индикатора MACD;
  10. double           m_buff_EMA[] - динамический массив значений типа double, используется для запроса значений индикатора EMA;
  11. double           m_macd_current - используется для хранения текущего значения основной линии индикатора MACD;
  12. double           m_macd_previous - используется для хранения предыдущего значения основной линии индикатора MACD;
  13. double           m_signal_current - используется для хранения текущего значения сигнальной линии индикатора MACD;
  14. double           m_signal_previous - используется для хранения предыдущего значения сигнальной линии индикатора MACD;
  15. double           m_ema_current - используется для хранения текущего значения индикатора EMA;
  16. double           m_ema_previous используется для хранения предыдущего значения индикатора EMA;
  17. double           m_macd_open_level,
  18. double           m_macd_close_level,
  19. double           m_traling_stop,
  20. double           m_take_profit - используются для хранения значений ценовых уровней (заданных во входных параметрах) с учетом множителя m_adjusted_point.

Методы класса CSampleExpert, объявленные с модификатором доступа protected:

  1. bool  InitCheckParameters(const int digits_adjust) - проверка на корректность входных параметров и инициализация параметров работы эксперта;
  2. bool  InitIndicators(void) - инициализация (создание) индикаторов MACD и Moving Average;
  3. bool  LongClosed(void) - возвращает true (и закрывает открытую длинную позицию) при выполнении условий закрытия длинной позиции;
  4. bool  ShortClosed(void) - возвращает true (и закрывает открытую короткую позицию) при выполнении условий закрытия короткой позиции;
  5. bool  LongModified(void) - возвращает true (и модифицирует цену Stop Loss) при выполнении условий изменения уровня Stop Loss открытой длинной позиции;
  6. bool  ShortModified(void) - возвращает true (и модифицирует цену Stop Loss) при выполнении условий изменения уровня Stop Loss открытой короткой позиции;
  7. bool  LongOpened(void) - возвращает true (и открывает длинную позицию) при выполнении условий открытия длинной позиции;
  8. bool  ShortOpened(void) - возвращает true (и открывает короткую позицию) при выполнении условий открытия короткой позиции.


3.2. Конструктор класса CSampleExpert

//+------------------------------------------------------------------+
//| Конструктор класса CSampleExpert                                 |
//+------------------------------------------------------------------+
CSampleExpert::CSampleExpert(void) : m_adjusted_point(0),
                                     m_handle_macd(INVALID_HANDLE),
                                     m_handle_ema(INVALID_HANDLE),
                                     m_macd_current(0),
                                     m_macd_previous(0),
                                     m_signal_current(0),
                                     m_signal_previous(0),
                                     m_ema_current(0),
                                     m_ema_previous(0),
                                     m_macd_open_level(0),
                                     m_macd_close_level(0),
                                     m_traling_stop(0),
                                     m_take_profit(0)
  {
   ArraySetAsSeries(m_buff_MACD_main,true);
   ArraySetAsSeries(m_buff_MACD_signal,true);
   ArraySetAsSeries(m_buff_EMA,true);
  }

Конструктор класса вызывается автоматически при создании объекта-экземпляра класса. При его вызове устанавливаются значения по умолчанию (в скобках) для переменных-членов класса и задается направление индексации как в таймсериях для массивов m_buff_MACD_main[], m_buff_MACD_signal[], m_buff_EMA[].


3.3. Деструктор класса CSampleExpert

//+------------------------------------------------------------------+
//| Деструктор класса CSampleExpert                                  |
//+------------------------------------------------------------------+
CSampleExpert::~CSampleExpert(void)
  {
  }

Деструктор класса CSampleExpert кода не содержит.


3.4. Метод Init класса CSampleExpert

//+------------------------------------------------------------------+
//| Инициализация и проверка корректности входных параметров         |
//+------------------------------------------------------------------+
bool CSampleExpert::Init(void)
  {
//--- установка общих свойств
   m_symbol.Name(Symbol());              // инструмент
   m_trade.SetExpertMagicNumber(12345);  // magic
//--- учет 3/5-значных котировок
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;
//--- установка значений уровней с учетом множителя m_adjusted_point
   m_macd_open_level =InpMACDOpenLevel*m_adjusted_point;
   m_macd_close_level=InpMACDCloseLevel*m_adjusted_point;
   m_traling_stop    =InpTrailingStop*m_adjusted_point;
   m_take_profit     =InpTakeProfit*m_adjusted_point;
//--- установка проскальзывания в 3 пункта
   m_trade.SetDeviationInPoints(3*digits_adjust);
//---
   if(!InitCheckParameters(digits_adjust))
      return(false);
   if(!InitIndicators())
      return(false);
//--- успешное завершение
   return(true);
  }

В методе Init() производится инициализация переменных членов-класса и проверка корректности входных параметров.

Вызовом метода Name() объекта m_symbol (экземпляр класса CSymbolInfo) устанавливается наименование инструмента, на котором запущен советник, затем вызывается метод SetExpertMagicNumber(), устанавливающий значение идентификатора эксперта (magic) для объекта m_trade (будет использоваться при проведении торговых операций). После этого при помощи метода Digits() запрашивается количество знаков после запятой у символа, и при необходимости производится корректировка значений уровней.

Далее вызывается метод SetDeviationInPoints() объекта m_trade, в котором устанавливается величина допустимого проскальзывания при проведении торговых операций.


3.5. Метод InitCheckParameters класса CSampleExpert

//+------------------------------------------------------------------+
//| Checking for input parameters                                    |
//+------------------------------------------------------------------+
bool CSampleExpert::InitCheckParameters(const int digits_adjust)
  {
//--- проверка корректности уровня Take Profit
   if(InpTakeProfit*digits_adjust<m_symbol.StopsLevel())
     {
      printf("Take Profit must be greater than %d",m_symbol.StopsLevel());
      return(false);
     }
//--- проверка корректности уровня Trailing Stop
   if(InpTrailingStop*digits_adjust<m_symbol.StopsLevel())
     {
      printf("Trailing Stop must be greater than %d",m_symbol.StopsLevel());
      return(false);
     }
//--- проверка корректности торгового объема
   if(InpLots<m_symbol.LotsMin() || InpLots>m_symbol.LotsMax())
     {
      printf("Lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
      return(false);
     }
   if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10)
     {
      printf("Lots amount is not corresponding with lot step %f",m_symbol.LotsStep());
      return(false);
     }
//--- выводим предупреждение если Take Profit<=Trailing Stop
   if(InpTakeProfit<=InpTrailingStop)
      printf("Warning: Trailing Stop must be less than Take Profit");
//--- успешное завершение
   return(true);
  }

В методе InitCheckParameters() производится проверка на корректность входных параметров советника. Если какой-либо параметр имеет недопустимое значение, то выводится соответствующее сообщение, а функция возвращает false.


3.6. Метод InitIndicators() класса CSampleExpert

//+------------------------------------------------------------------+
//| Метод инициализации индикаторов                                  |
//+------------------------------------------------------------------+
bool CSampleExpert::InitIndicators(void)
  {
//--- создание индикатора MACD
   if(m_handle_macd==INVALID_HANDLE)
      if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE)
        {
         printf("Error creating MACD indicator");
         return(false);
        }
//--- создание индикатора EMA
   if(m_handle_ema==INVALID_HANDLE)
      if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE)
        {
         printf("Error creating EMA indicator");
         return(false);
        }
//--- успешное завершение
   return(true);
  }

В методе InitIndicators() производится проверка начальных значений переменных m_handle_macd и m_handle_ema (они должны быть равны INVALID_HANDLE, т.к. инициализированы в конструкторе) и создание технических индикаторов MACD и Moving Average (при помощи функций iMACD и iMA). При успешном завершении функция возвращает true, а хендлы индикаторов сохраняются в членах класса m_handle_macd и m_handle_ema.

Хендлы созданных индикаторов затем будут использованы для проверки количества рассчитанных данных (BarsCalculated) и получения численных значений (CopyBuffer) данных индикаторов в методе Processing().


3.7. Метод LongClosed() класса CSampleExpert

//+------------------------------------------------------------------+
//| Проверка условий закрытия длинной позиции                        |
//+------------------------------------------------------------------+
bool CSampleExpert::LongClosed(void)
  {
   bool res=false;
//--- нужно ли закрывать позицию?
   if(m_macd_current>0)
      if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous)
         if(m_macd_current>m_macd_close_level)
           {
            //--- закрытие позиции
            if(m_trade.PositionClose(Symbol()))
               printf("Long position by %s to be closed",Symbol());
            else
               printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment());
            res=true;
           }
//--- возвращаем результат
   return(res);
  }

Метод LongClosed() возвращает true (и закрывает открытую длинную позицию) при выполнении условий закрытия длинной позиции:

  1. m_macd_current>0 - текущее значение главной линии индикатора MACD положительное (MACD-гистограмма выше нулевой линии);
  2. m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - основная линия индикатора MACD пересекла сигнальную сверху вниз.
  3. m_macd_current>m_macd_close_level - текущее значение главной линии индикатора MACD больше m_macd_close_level.


3.8. Метод ShortClosed() класса CSampleExpert

//+------------------------------------------------------------------+
//| Проверка условий закрытия короткой позиции                       |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortClosed(void)
  {
   bool res=false;
//--- нужно ли закрывать позицию?
   if(m_macd_current<0)
      if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous)
         if(MathAbs(m_macd_current)>m_macd_close_level)
           {
            //--- закрытие позиции
            if(m_trade.PositionClose(Symbol()))
               printf("Short position by %s to be closed",Symbol());
            else
               printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment());
            res=true;
           }
//--- возвращаем результат
   return(res);
  }

Метод ShortClosed() возвращает true (и закрывает открытую короткую позицию) при выполнении условий закрытия короткой позиции:

  1. m_macd_current<0 - текущее значение главной линии индикатора MACD отрицательное (MACD-гистограмма ниже нулевой линии).
  2. m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - основная линия индикатора MACD пересекла сигнальную снизу вверх.
  3. MathAbs(m_macd_current)>m_macd_close_level - текущее значение главной линии индикатора MACD по модулю больше m_macd_close_level.


3.9. Метод LongModified() класса CSampleExpert

//+------------------------------------------------------------------+
//| Проверка условий модификации длинной позиции                     |
//+------------------------------------------------------------------+
bool CSampleExpert::LongModified(void)
  {
   bool res=false;
//--- проверка необходимости Trailing Stop 
   if(InpTrailingStop>0)
     {
      if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop)
        {
         double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits());
         double tp=m_position.TakeProfit();
         if(m_position.StopLoss()<sl || m_position.StopLoss()==0.0)
           {
            //--- модификация параметров Stop Loss и Take Profit позиции
            if(m_trade.PositionModify(Symbol(),sl,tp))
               printf("Long position by %s to be modified",Symbol());
            else
              {
               printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment());
               printf("Modify parameters : SL=%f,TP=%f",sl,tp);
              }
            res=true;
           }
        }
     }
//--- возвращаем результат
   return(res);
  }

Метод LongModified() возвращает true (и изменяет значение параметра Stop Loss позиции) при выполнении условий модификации длинной позиции. Если значение входного параметра InpTrailingStop>0, то производится проверка факта прохождения цены InpTrailingStop пунктов от цены открытия в направлении позиции. Далее производится расчет нового значения уровня Stop Loss и модификация параметра Stop Loss открытой позиции.


3.10. Метод ShortModified класса CSampleExpert

//+------------------------------------------------------------------+
//| Проверка условий модификации короткой позиции                    |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortModified(void)
  {
   bool   res=false;
//--- проверка необходимости trailing stop
   if(InpTrailingStop>0)
     {
      if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop))
        {
         double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits());
         double tp=m_position.TakeProfit();
         if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0)
           {
            //--- модификация параметров Stop Loss и Take Profit позиции
            if(m_trade.PositionModify(Symbol(),sl,tp))
               printf("Short position by %s to be modified",Symbol());
            else
              {
               printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment());
               printf("Modify parameters : SL=%f,TP=%f",sl,tp);
              }
            res=true;
           }
        }
     }
//--- возвращаем результат
   return(res);
  }

Метод ShotModified() возвращает true (и изменяет значение параметра Stop Loss позиции) при выполнении условий модификации короткой позиции. Если значение входного параметра InpTrailingStop>0, то производится проверка факта прохождения цены InpTrailingStop пунктов от цены открытия в направлении позиции. Далее производится расчет нового значения уровня Stop Loss и модификация параметра Stop Loss открытой позиции.


3.11. Метод LongOpened() класса CSampleExpert

//+------------------------------------------------------------------+
//| Check for long position opening                                  |
//+------------------------------------------------------------------+
bool CSampleExpert::LongOpened(void)
  {
   bool res=false;
//--- проверка условий открытия длинной позиции
   if(m_macd_current<0)
      if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous)
         if(MathAbs(m_macd_current)>(m_macd_open_level) && m_ema_current>m_ema_previous)
           {
            double price=m_symbol.Ask();
            double tp   =m_symbol.Bid()+m_take_profit;
            //--- проверка наличия свободных средств
            if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0)
               printf("We have no money. Free Margin = %f",m_account.FreeMargin());
            else
              {
               //--- открытие длинной позиции
               if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp))
                  printf("Position by %s to be opened",Symbol());
               else
                 {
                  printf("Error opening BUY position by %s : '%s'",Symbol(),m_trade.ResultComment());
                  printf("Open parameters : price=%f,TP=%f",price,tp);
                 }
              }
            res=true;
           }
//--- возвращаем результат
   return(res);
  }

Метод LongOpened() возвращает true (и открывает длинную позицию) в случае выполнения условий для открытия позиции на покупку:

  1. m_macd_current<0 - текущее значение главной линии индикатора MACD отрицательное (MACD-гистограмма ниже нулевой линии);
  2. m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - основная линия индикатора MACD пересекла сигнальную снизу вверх;
  3. MathAbs(m_macd_current)>m_macd_open_level - текущее значение главной линии индикатора MACD по модулю больше m_macd_open_level;
  4. m_ema_current>m_ema_previous - ema возрастает.

При выполнении всех условий производится проверка наличия достаточного количества свободных средств (используется метод FreeMarginCheck() класса CAccountInfo Стандартной библиотеки) и открытие длинной позиции при помощи метода PositionOpen() класса CTrade.


3.12. Метод ShortOpened класса CSampleExpert

//+------------------------------------------------------------------+
//| Check for short position opening                                 |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortOpened(void)
  {
   bool res=false;
//--- проверка условий открытия короткой позиции
   if(m_macd_current>0)
      if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous)
         if(m_macd_current>(m_macd_open_level) && m_ema_current<m_ema_previous)
           {
            double price=m_symbol.Bid();
            double tp   =m_symbol.Ask()-m_take_profit;
            //--- проверка наличия свободных средств
            if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_SELL,InpLots,price)<0.0)
               printf("We have no money. Free Margin = %f",m_account.FreeMargin());
            else
              {
               //--- открытие короткой позиции
               if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,InpLots,price,0.0,tp))
                  printf("Position by %s to be opened",Symbol());
               else
                 {
                  printf("Error opening SELL position by %s : '%s'",Symbol(),m_trade.ResultComment());
                  printf("Open parameters : price=%f,TP=%f",price,tp);
                 }
              }
            res=true;
           }
//--- возвращаем результат
   return(res);
  }

Метод ShortOpened() возвращает true (и открывает короткую позицию) в случае выполнения условий для открытия позиции на продажу:

  1. m_macd_current>0 - текущее значение главной линии индикатора MACD положительное (MACD-гистограмма выше нулевой линии);
  2. m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - основная линия индикатора MACD пересекла сигнальную сверху вниз;
  3. m_macd_current>m_macd_open_level - текущее значение главной линии индикатора MACD больше m_macd_open_level;
  4. m_ema_current<m_ema_previous - ema убывает.

При выполнении всех условий производится проверка наличия достаточного количества свободных средств (используется метод FreeMarginCheck() класса CAccountInfo Стандартной библиотеки) и открытие короткой позиции при помощи метода PositionOpen() класса CTrade.


3.13 Метод Processing() класса CSampleExpert

//+------------------------------------------------------------------+
//| main function returns true if any position processed             |
//+------------------------------------------------------------------+
bool CSampleExpert::Processing(void)
  {
//--- обновление котировок
   if(!m_symbol.RefreshRates())
      return(false);
//--- обновление значений индикаторов
   if(BarsCalculated(m_handle_macd)<2 || BarsCalculated(m_handle_ema)<2)
      return(false);
   if(CopyBuffer(m_handle_macd,0,0,2,m_buff_MACD_main)  !=2 ||
      CopyBuffer(m_handle_macd,1,0,2,m_buff_MACD_signal)!=2 ||
      CopyBuffer(m_handle_ema,0,0,2,m_buff_EMA)         !=2)
      return(false);
//--- для упрощения работы с индикаторами и ускорения доступа
//--- текущие значения индикаторов сохраняются во внутренних переменных (членах класса)
   m_macd_current   =m_buff_MACD_main[0];
   m_macd_previous  =m_buff_MACD_main[1];
   m_signal_current =m_buff_MACD_signal[0];
   m_signal_previous=m_buff_MACD_signal[1];
   m_ema_current    =m_buff_EMA[0];
   m_ema_previous   =m_buff_EMA[1];
//--- важно правильно зайти в рынок, но более важным является правильный выход
//--- сначала проверим существование открытой позиции
   if(m_position.Select(Symbol()))
     {
      if(m_position.PositionType()==POSITION_TYPE_BUY)
        {
         //--- если нужно, пытаемся закрыть или модифицировать длинную позицию
         if(LongClosed())
            return(true);
         if(LongModified())
            return(true);
        }
      else
        {
         //--- если нужно, пытаемся закрыть или модифицировать короткую позицию
         if(ShortClosed())
            return(true);
         if(ShortModified())
            return(true);
        }
     }
//--- открытых позиций нет
   else
     {
      //--- проверяем условия и при необходимости открываем длинную позицию
      if(LongOpened())
         return(true);
      //--- проверяем условия и при необходимости открываем короткую позицию
      if(ShortOpened())
         return(true);
     }
//--- выходим без обработки позиции
    return(false);
  }

Метод Processing() класса CSampleExpert является главным методом советника. Вызов метода Processing() осуществляется в обработчике события OnTick(), при этом осуществляется контроль интервала времени (не менее ExtTimeOut секунд) между последовательными вызовами данного метода (раздел 2.2).

Вызовом метода RefreshRates() класса CSymbolInfo производится обновление котировок. При помощи функции BarsCalculated() запрашивается количество баров, для которых вычислены индикаторы MACD и Moving Average (раздел 3.6.), если баров менее 2, то производится выход из функции с возвращаемым значением false.

Далее вызовом функции CopyBuffer производится запрос двух последних значений технических индикаторов (основной и сигнальной линии MACD и значений Moving Average), при этом если количество скопированных данных менее двух, то производится выход из функции. После этого значения индикаторов из массивов m_buff_MACD_main[], m_buff_MACD_signal[] и m_buff_EMA[] копируются в переменные m_macd_current, m_macd_previous, m_signal_current, m_signal_previous, m_ema_current и m_ema_previous.

Следующий шаг - работа с позицией, она осуществляется при помощи класса CPositionInfo Стандартной библиотеки. Если вызов метода Select() вернул true, это означает, что в настоящее время присутствует открытая позиция, ее тип определяется при помощи метода PositionType(). Далее производится работа в соответствии с типом открытой позиции.


4. Тестирование на исторических данных

Наилучшие значения параметров можно найти при помощи тестера стратегий терминала MetaTrader 5.

На рис.3 приведены результаты тестирования советника за 2013 год с параметрами по умолчанию.

Рис. 3. Результаты тестирования на исторических данных советника MACD Sample

Рис. 3. Результаты тестирования на исторических данных советника MACD Sample

Выводы

Советник MACD Sample, входящий в поставку клиентского терминала MetaTrader 5, представляет собой пример применения объектно-ориентировнного подхода к разработке советников.


DynamicRS_C_HTF DynamicRS_C_HTF

Индикатор DynamicRS_C с возможностью изменения таймфрейма индикатора во входных параметрах.

CronexRSI CronexRSI

Индикатор MACD, в котором ценовой ряд заменён на ряд значений из технического индикатора iRSI, выполненный в виде цветного облака.

CronexDeMarker CronexDeMarker

Индикатор MACD, в котором ценовой ряд заменён на ряд значений технического индикатора DeMarker, выполненный в виде цветного облака.

Exp_ColorZerolagStochs Exp_ColorZerolagStochs

Эксперт Exp_ColorZerolagStochs построен на основе сигналов осциллятора ColorZerolagStochs.