Расширение стандартной библиотеки MQL5 и повторное использование кода
laplacianlab | 23 сентября, 2013
Введение
Стандартная библиотека MQL5 – это объектно-ориентированный фреймворк, состоящий из набора готовых к использованию классов, облегчающих труд разработчика. Однако она не может удовлетворить все требования абсолютно всех разработчиков в мире, поэтому если вы хотите иметь в своем распоряжении больше пользовательских элементов, вам необходимо расширить ее. В статье описывается интеграция обычного индикатора ZigZag в стандартную библиотеку. В ходе работы мы будем опираться на принципы разработки, применяемые в компании MetaQuotes.
Говоря кратко, MQL5 API предлагает вам надежность, гибкость, простоту обслуживания, а также возможность повторного использования кода. Если вы собираетесь совершенствовать ваши навыки в языке MQL5 и разрабатывать сложные приложения, например, мультивалютные советники, вам прежде всего необходимо освоить стандартную библиотеку, чтобы обеспечить своим программам успешную жизнь.
По мере усложнения ваших торговых советников и индикаторов необходимость в усвоении понятий, связанных с разработкой фреймворков, будет только возрастать. В качестве конкретного примера могу назвать собственную потребность в сложном мультивалютном советнике, которая заставляет тщательно продумывать основы проекта при его разработке с нуля.
Рис. 1. Правильные многогранники – совершенные объекты. Они хорошо демонстрируют идею разработки приложений по четкому плану
1. Загрузка индикатора ZigZag
Начнем с загрузки стандартного инидкатора ZigZag, доступного в Code Base, прямо в терминале MetaTrader 5. При этом будут созданы файлы Indicators\zigzag.mq5 и Indicators\zigzag.ex5.
Рис. 2. Загрузка стандартного индикатора ZigZag в терминале MetaTrader 5
Ниже приведены строки коды из Indicators\zigzag.mq5, содержащие входные параметры индикатора, глобальные переменные и обработчик OnInit(). Я привожу эту часть только потому, что весь файл состоит из 298 строк кода. Это сделано исключительно ради удобства и понимания более глобальной картины, о которой мы поговорим ниже.
//+------------------------------------------------------------------+ //| ZigZag.mq5 | //| Copyright 2009, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2009, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 3 #property indicator_plots 1 //---- plot Zigzag #property indicator_label1 "Zigzag" #property indicator_type1 DRAW_SECTION #property indicator_color1 Red #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters input int ExtDepth=12; input int ExtDeviation=5; input int ExtBackstep=3; //--- indicator buffers double ZigzagBuffer[]; // main buffer double HighMapBuffer[]; // highs double LowMapBuffer[]; // lows int level=3; // recounting depth double deviation; // deviation in points //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS); //--- set short name and digits PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")"); IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- set empty value PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); //--- to use in cycle deviation=ExtDeviation*_Point; //--- return(INIT_SUCCEEDED); }
2. Краткий обзор: от общего к частному
Мы попробуем применить нисходящий анализ при рассмотрении нашего нового объектно-ориентированного индикатора ZigZag, который мы хотим интегрировать в стандартную библиотеку MQL5. Это означает, что сначала мы должны рассмотреть всю систему, а затем проанализировать ее составные части. Так почему бы нам не написать пару тестовых советников, чтобы увидеть глобальную картину? Итак, давайте напишем процедурного советника и его объектно-ориентированную версию.
2.1. Стандартный индикатор ZigZag
Среднестатистический MQL5-разработчик скорее всего включит индикатор ZigZag в свой советник следующим образом:
//+----------------------------------------------------------------------+ //| ExpertOriginalZigZag.mq5 | //| Copyright © 2013, Laplacianlab - Jordi Bassagañas | //+----------------------------------------------------------------------+ //--- свойства торгового советника #property copyright "Copyright © 2013, Laplacianlab - Jordi Bassagañas" #property link "https://www.mql5.com/ru/articles" #property version "1.00" #property description "Этот тестовый торговый советник создан исключительно для демонстрации использования стандартного индикатора ZigZag." //--- входные данные торгового советника input ENUM_TIMEFRAMES EAPeriod=PERIOD_H1; input string CurrencyPair="EURUSD"; //--- глобальные переменные int zigZagHandle; double zigZagBuffer[]; double zigZagHigh[]; double zigZagLow[]; //+------------------------------------------------------------------+ //| Функция инициализации советника | //+------------------------------------------------------------------+ int OnInit() { zigZagHandle=iCustom(CurrencyPair,EAPeriod,"zigzag",12,5,3); ArraySetAsSeries(zigZagBuffer,true); ArraySetAsSeries(zigZagHigh,true); ArraySetAsSeries(zigZagLow,true); return(0); } //+------------------------------------------------------------------+ //| Функция деинициализации советника | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(zigZagHandle); ArrayFree(zigZagBuffer); ArrayFree(zigZagHigh); ArrayFree(zigZagLow); } //+------------------------------------------------------------------+ //| Тиковая функция советника | //+------------------------------------------------------------------+ void OnTick() { //--- обновляем данные if(CopyBuffer(zigZagHandle,0,0,2,zigZagBuffer)<0) { Print("Невозможно скопировать буфер 0 индикатора ZigZag!"); return; } if(CopyBuffer(zigZagHandle,1,0,2,zigZagHigh)<0) { Print("Невозможно скопировать буфер 1 индикатора ZigZag!"); return; } if(CopyBuffer(zigZagHandle,2,0,2,zigZagLow)<0) { Print("Невозможно скопировать буфер 2 индикатора ZigZag!"); return; } //--- вывод значений if(zigZagBuffer[0]!=0) Print("zigZagBuffer[0]: ", zigZagBuffer[0]); if(zigZagHigh[0]!=0) Print("zigZagHigh[0]: ", zigZagHigh[0]); if(zigZagLow[0]!=0) Print("zigZagLow[0]: ", zigZagLow[0]); } //+------------------------------------------------------------------+
2.2. Индикатор ZigZag в составе стандартной библиотеки
В то же время, опытный MQL5-разработчик наверняка решит работать с индикатором ZigZag так же, как он работает с индикаторами в составе стандартной библиотеки, а именно:
//+----------------------------------------------------------------------+ //| ExpertOOZigZag.mq5 | //| Copyright © 2013, Laplacianlab - Jordi Bassagañas | //+----------------------------------------------------------------------+ #include <..\Include\Indicators\Custom\Trend.mqh> //--- свойства торгового советника #property copyright "Copyright © 2013, Laplacianlab - Jordi Bassagañas" #property link "https://www.mql5.com/ru/articles" #property version "1.00" #property description "Этот тестовый торговый советник создан исключительно для демонстрации " #property description "использования объектно-ориентированной версии стандартного индикатора ZigZag." //--- входные данные торгового советника input ENUM_TIMEFRAMES EAPeriod=PERIOD_H1; input string CurrencyPair="EURUSD"; //--- глобальные переменные CiZigZag *ciZigZag; //+------------------------------------------------------------------+ //| Функция инициализации советника | //+------------------------------------------------------------------+ int OnInit() { ciZigZag=new CiZigZag; ciZigZag.Create(CurrencyPair,EAPeriod,12,5,3); return(0); } //+------------------------------------------------------------------+ //| Функция деинициализации советника | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { delete(ciZigZag); } //+------------------------------------------------------------------+ //| Тиковая функция советника | //+------------------------------------------------------------------+ void OnTick() { //--- обновляем данные ciZigZag.Refresh(); //--- вывод значений if(ciZigZag.ZigZag(0)!=0) Print("OO ZigZag buffer: ", ciZigZag.ZigZag(0)); if(ciZigZag.High(0)!=0) Print("OO ZigZag high: ", ciZigZag.High(0)); if(ciZigZag.Low(0)!=0) Print("OO ZigZag low: ",ciZigZag.Low(0)); } //+------------------------------------------------------------------+
2.3. Вывод
Второе решение лучше, потому что является объектно-ориентированным. После разработки классов, взаимодействие с соответствующим функционалом индикатора ZigZag значительно упрощается по сравнению с его процедурным аналогом. Тем не менее, позвольте кратко перечислить преимущества при работе с объектно-ориентированной библиотекой:
- ООП позволяет легко моделировать задачи.
- ООП упрощает повторное использование кода, что в свою очередь благотворно влияет на цену, надежность, гибкость и удобство технического обслуживания.
-
Данная парадигма позволяет создавать абстрактные типы данных (АТД, Abstract Data Types). АТД – это абстрактная модель типов данных, присутствующих во всех языках программирования.
Рис 3. Правильный двадцатигранник (икосаэдр). Создание приложений по четкому плану – это та гарантия качества, которая обеспечит долгую жизнь нашим разработкам
3. Интеграция нового объектно-ориентированного индикатора ZigZag в стандартную библиотеку MQL5
Как уже было сказано во Введении, в ходе работы мы будем опираться на объектно-ориентированный стиль компании MetaQuotes для создания набора классов, назначение которых – обладающих той же функциональностью, что и скачанный ранее индикатор
ZigZag. Это довольно легко. Нам лишь необходимо взглянуть на файлы в папке Include\Indicators, а также изучить и понять некоторые идеи, лежащие в основе стандартной библиотеки MQL5. Если вы взглянете на содержимое файла Trend.mqh, вы увидите, что в нем много классов технических индикаторов: ADX, Bollinger Bands, SAR, скользящие средние и т.д. Все эти классы наследуются от CIndicator. Мы можем придерживаться указанной структуры. Другой способ решения задачи – расширение нового объектно-ориентированного индикатора с помощью класса CiCustom.
Начнем с создания новой папки Include\Indicators\Custom и нового файла Include\Indicators\Custom\Trend.mqh для создания наших собственных индикаторов, так же как это делает MetaQuotes в Include\Indicators\Trend.mqh. Итак, у нас уже есть расширенный файл Include\Indicators\Custom\Trend.mqh. Ниже рассматриваются некоторые технические аспекты его разработки.
//+------------------------------------------------------------------+ //| Include\Indicators\Custom\Trend.mqh | //| Copyright 2013, Laplacianlab - Jordi Bassagañas | //| https://www.mql5.com/ru/users/laplacianlab | //+------------------------------------------------------------------+ #include <..\Include\Indicators\Indicator.mqh> //+------------------------------------------------------------------+ //| Класс CiZigZag. | //| Назначение: класс индикатора "ZigZag". | //| Выводится из класса CIndicator. | //+------------------------------------------------------------------+ class CiZigZag : public CIndicator { protected: int m_depth; int m_deviation; int m_backstep; public: CiZigZag(void); ~CiZigZag(void); //--- методы доступа к защищенным данным int Depth(void) const { return(m_depth); } int Deviation(void) const { return(m_deviation); } int Backstep(void) const { return(m_backstep); } //--- метод создания bool Create(const string symbol,const ENUM_TIMEFRAMES period, const int depth,const int deviation_create,const int backstep); //--- методы доступа к данным индикатора double ZigZag(const int index) const; double High(const int index) const; double Low(const int index) const; //--- метод идентификации virtual int Type(void) const { return(IND_CUSTOM); } protected: //--- методы настройки virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]); bool Initialize(const string symbol,const ENUM_TIMEFRAMES period, const int depth,const int deviation_init,const int backstep); }; //+------------------------------------------------------------------+ //| Конструктор | //+------------------------------------------------------------------+ CiZigZag::CiZigZag(void) : m_depth(-1), m_deviation(-1), m_backstep(-1) { } //+------------------------------------------------------------------+ //| Деструктор | //+------------------------------------------------------------------+ CiZigZag::~CiZigZag(void) { } //+------------------------------------------------------------------+ //| Создаем индикатор "Zig Zag" | //+------------------------------------------------------------------+ bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period, const int depth,const int deviation_create,const int backstep) { //--- проверяем историю if(!SetSymbolPeriod(symbol,period)) return(false); //--- создаем m_handle=iCustom(symbol,period,"zigzag",depth,deviation_create,backstep); //--- проверяем результат if(m_handle==INVALID_HANDLE) return(false); //--- индикатор успешно создан if(!Initialize(symbol,period,depth,deviation_create,backstep)) { //--- ошибка инициализации IndicatorRelease(m_handle); m_handle=INVALID_HANDLE; return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Инициализируем индикатор с универсальными параметрами | //+------------------------------------------------------------------+ bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]) { return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value)); } //+------------------------------------------------------------------+ //| Инициализируем индикатор со специальными параметрами | //+------------------------------------------------------------------+ bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period, const int depth,const int deviation_init,const int backstep) { if(CreateBuffers(symbol,period,3)) { //--- строка состояния отрисовки m_name ="ZigZag"; m_status="("+symbol+","+PeriodDescription()+","+ IntegerToString(depth)+","+IntegerToString(deviation_init)+","+ IntegerToString(backstep)+") H="+IntegerToString(m_handle); //--- сохраняем настройки m_depth=depth; m_deviation=deviation_init; m_backstep=backstep; //--- создаем буферы ((CIndicatorBuffer*)At(0)).Name("ZIGZAG"); ((CIndicatorBuffer*)At(1)).Name("HIGH"); ((CIndicatorBuffer*)At(2)).Name("LOW"); //--- ok return(true); } //--- ошибка return(false); } //+------------------------------------------------------------------+ //| Доступ к буферу ZigZag индикатора "Zig Zag" | //+------------------------------------------------------------------+ double CiZigZag::ZigZag(const int index) const { CIndicatorBuffer *buffer=At(0); //--- проверяем if(buffer==NULL) return(EMPTY_VALUE); //--- return(buffer.At(index)); } //+------------------------------------------------------------------+ //| Доступ к буферу High индикатора "Zig Zag" | //+------------------------------------------------------------------+ double CiZigZag::High(const int index) const { CIndicatorBuffer *buffer=At(1); //--- проверяем if(buffer==NULL) return(EMPTY_VALUE); //--- return(buffer.At(index)); } //+------------------------------------------------------------------+ //| Доступ к буферу Low индикатора "Zig Zag" | //+------------------------------------------------------------------+ double CiZigZag::Low(const int index) const { CIndicatorBuffer *buffer=At(2); //--- проверяем if(buffer==NULL) return(EMPTY_VALUE); //--- return(buffer.At(index)); } //+------------------------------------------------------------------+
3.1. Инкапсуляция
Инкапсуляция является хорошей практикой программирования, ограничивающей доступ к составляющим объект компонентам и делающей их доступными только внутри объекта. Все классы, определенные в Trend.mqh, реализуют данную идею, и мы делаем то же самое.
У CiZigZag имеются собственные защищенные свойства:
protected: int m_depth; int m_deviation; int m_backstep;
Соответственно, CiZigZag обладает открытым интерфейсом для доступа к указанным свойствам за пределами объекта типа CiZigZag:
public: //--- методы доступа к защищенным данным int Depth(void) const { return(m_depth); } int Deviation(void) const { return(m_deviation); } int Backstep(void) const { return(m_backstep); }
Это мера безопасности для изоляции объектов. Инкапсуляция защищает от произвольных изменений, вносимых кем-то или чем-то, не имеющим права доступа к данным объектов.
3.2. Доступ к данным ZigZag
Как видно из первой части этой статьи, файл с исходным кодом zigzag.mq5 создает три буфера:
//--- отображение индикаторных буферов SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);
С помощью инкапсуляции методы CiZigZag – ZigZag(const int index), High(const int index) и Low(const int index) – возвращают индикаторные буферы, созданные ранее в методе инициализации. Необходимо отметить, что основой этих трех методов является класс CIndicatorBuffer определена в файле MQL5 Include\Indicators\Indicator.mqh. Таким образом, мы уже с головой ушли в MQL5 API!
В качестве примера ниже приведен код для доступа к буферу High типа CiZigZag:
//+------------------------------------------------------------------+ //| Доступ к буферу High индикатора "Zig Zag" | //+------------------------------------------------------------------+ double CiZigZag::High(const int index) const { CIndicatorBuffer *buffer=At(1); //--- проверяем if(buffer==NULL) return(EMPTY_VALUE); //--- return(buffer.At(index)); }
3.3. Полиморфизм, перегрузка методов и виртуальные функции
В предыдущем разделе мы кратко рассмотрели тему инкапсуляции, которая является одной из наиболее важных особенностей объектно-ориентированного программирования. Классы, содержащиеся в Include\Indicators\Indicator.mqh и в файле Include\Indicators\Custom\Trend.mqh имеют дело с двумя другими аспектами ООП – полиморфизмом и перегрузкой методов.
Полиморфизм предоставляет возможность доступа к разнообразным методам через один и тот же интерфейс. Таким образом, идентификатор может принимать различные формы в зависимости от контекста. Полиморфизму требуется механизм наследования для своей реализации. Перегрузка методов – другая особенность ООП, позволяющая создавать несколько методов с одним именем, но разным количеством параметров.
Ограничимся этим кратким вступлением. Рамки статьи не позволяют подробнее рассмотреть эти темы. Эту задачу я оставляю вам в качестве упражнения. Пожалуйста, ознакомьтесь с разделами "Полиморфизм" и "Перегрузка" в Справочнике MQL5. В любом случае, как мы видим, стандартная библиотека использует все возможности ООП. Соответственно, чем лучше мы их знаем, тем лучше мы сможем расширить API под свои нужды.
Необходимо также отметить, что в MQL5 полиморфизм реализован с помощью виртуальных функций. Пожалуйста, изучите раздел "Виртуальные функции", чтобы понять, как они работают.
Вот почему мы реализуем метод инициализации CiZigZag таким образом:
//+------------------------------------------------------------------+ //| Инициализация индикатора с универсальными параметрами | //+------------------------------------------------------------------+ bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]) { return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value)); } //+------------------------------------------------------------------+ //| Инициализация индикатора со специальными параметрами | //+------------------------------------------------------------------+ bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period, const int depth,const int deviation_init,const int backstep) { if(CreateBuffers(symbol,period,3)) { //--- строка состояния отрисовки m_name ="ZigZag"; m_status="("+symbol+","+PeriodDescription()+","+ IntegerToString(depth)+","+IntegerToString(deviation_init)+","+ IntegerToString(backstep)+") H="+IntegerToString(m_handle); //--- сохраняем настройки m_depth=depth; m_deviation=deviation_init; m_backstep=backstep; //--- создаем буферы ((CIndicatorBuffer*)At(0)).Name("ZIGZAG"); ((CIndicatorBuffer*)At(1)).Name("HIGH"); ((CIndicatorBuffer*)At(2)).Name("LOW"); //--- ok return(true); } //--- ошибка return(false); }
4. Тестируем новый объектно-ориентированный ZigZag, уже доступный в стандартной библиотеке
Разумеется, вы должны прежде всего убедиться в том, что разработанные вами расширения работают именно так, как вы и планировали. Я рекомендую провести полное тестирование ваших пользовательских компонентов. Для упрощения понимания мы проведем простой тест трех основных методов CiZigZag: ZigZag(const int index), High(const int index) и Low(const int index).
Мы выведем значения, рассчитанные этими тремя методами на каждом тике советника, и сравним результаты процедурного советника ExpertOriginalZigZag.ex5 и объектно-ориентированного советника ExpertOOZigZag.ex5. Если результаты совпадают, мы можем заключить, что наше новое расширение в порядке и мы можем использовать наш объектно-ориентированный ZigZag, интегрированный в MQL5 API.
Рис. 4. Сравниваем результаты советников ExpertOriginalZigZag.ex5 и ExpertOOZigZag.ex5
Итак, прогоним оба советника, ExpertOriginalZigZag.ex5 и ExpertOOZigZag.ex5, представленных в начале данной статьи, в Тестере стратегий со следующим набором параметров:
- Пара: EURUSD, H1
- Дата: Выбор периода, с 2013.08.01 по 2013.08.15
- Режим торговли: Обычный, OHLC на М1
- Начальный депозит: 10000 USD, 1:100
- Оптимизация: Отключена
Поскольку оба советника показывают одинаковые результаты, мы можем заключить, что интеграция нашего CiZigZag прошла успешно и мы можем использовать его в наших разработках.
Логи советника ExpertOriginalZigZag.ex5:
DE 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:50:40 zigZagBuffer[0]: 1.32657 ML 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:50:40 zigZagLow[0]: 1.32657 FL 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:50:59 zigZagBuffer[0]: 1.32657 GE 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:50:59 zigZagLow[0]: 1.32657 KS 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:00 zigZagBuffer[0]: 1.32657 FR 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:00 zigZagLow[0]: 1.32657 GK 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:20 zigZagBuffer[0]: 1.32653 RJ 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:20 zigZagLow[0]: 1.32653 OR 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:40 zigZagBuffer[0]: 1.32653 FS 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:40 zigZagLow[0]: 1.32653 QJ 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:59 zigZagBuffer[0]: 1.32653 PH 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:51:59 zigZagLow[0]: 1.32653 JQ 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:52:00 zigZagBuffer[0]: 1.32653 KP 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:52:00 zigZagLow[0]: 1.32653 RH 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:52:20 zigZagBuffer[0]: 1.32653 GI 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:52:20 zigZagLow[0]: 1.32653 GP 0 18:45:39 ExpertOriginalZigZag (EURUSD,H1) 2013.08.01 08:52:40 zigZagBuffer[0]: 1.32614 // и так далее...
Логи советника ExpertOOZigZag.ex5:
RP 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:50:40 OO ZigZag buffer(0): 1.32657 HQ 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:50:40 OO ZigZag low(0): 1.32657 DI 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:50:59 OO ZigZag buffer(0): 1.32657 RH 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:50:59 OO ZigZag low(0): 1.32657 QR 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:00 OO ZigZag buffer(0): 1.32657 GS 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:00 OO ZigZag low(0): 1.32657 IK 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:20 OO ZigZag buffer(0): 1.32653 GJ 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:20 OO ZigZag low(0): 1.32653 EL 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:40 OO ZigZag buffer(0): 1.32653 OD 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:40 OO ZigZag low(0): 1.32653 OE 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:59 OO ZigZag buffer(0): 1.32653 IO 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:51:59 OO ZigZag low(0): 1.32653 DN 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:52:00 OO ZigZag buffer(0): 1.32653 RF 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:52:00 OO ZigZag low(0): 1.32653 PP 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:52:20 OO ZigZag buffer(0): 1.32653 RQ 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:52:20 OO ZigZag low(0): 1.32653 MI 0 18:48:02 ExpertOOZigZag (EURUSD,H1) 2013.08.01 08:52:40 OO ZigZag buffer(0): 1.32614 // и так далее...
Вывод
Стандартная библиотека MQL5 значительно упрощает жизнь разработчика. Однако она не может удовлетворить все требования абсолютно всех разработчиков в мире. Рано или поздно наступит момент, когда вам понадобится больше пользовательских элементов. По мере усложнения ваших торговых советников и индикаторов необходимость в усвоении понятий, связанных с разработкой фреймворков, будет только возрастать. Расширение стандартной библиотеки MQL5 может гарантировать вашим приложениям успешную жизнь.
Сначала мы воспользовались преимуществом повторного использования кода, скачав индикатор ZigZag из Code Base. Загрузив индикатор в терминал MetaTrader 5, мы использовали нисходящий анализ, чтобы начать разработку нашего нового объектно-ориентированного индикатора ZigZag. Мы окинули взглядом всю систему и приступили к подробному анализу. На первом этапе разработки мы сравнили тестовый советник, использующий процедурный индикатор ZigZag, с его объектно-ориентированным аналогом.
Мы добавили в индикатор ZigZag объектно-ориентированный класс, созданный в соответствии с принципами разработки компании MetaQuotes, которые использовались при создании стандартной библиотеки. И наконец, мы провели несколько простых тестов и пришли к выводу, что наш новый CiZigZag, уже интегрированный в MQL5 API, пригоден к использованию.