Расширение стандартной библиотеки MQL5 и повторное использование кода
Введение
Стандартная библиотека 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, пригоден к использованию.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/741
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Базовый класс CIndicator имеет метод GetData, с помощью которого можно получить данные из индикаторного буфера.
Получает данные из буфера индикатора по стартовой позиции и количеству
int GetData(
const int start_pos, // позиция
const int count, // количество
const int buffer_num, // номер буфера
double& buffer[] // массив
) const
После этого задавайте для вашего массива нужное направление индексации с помощью ArraySetAsSeries
Я Вас правильно понял???
Получается что надо на каждом тике нужно копировать всю историю?Я Вас правильно понял???
Получается что надо на каждом тике нужно копировать всю историю?1. Можно на открытие нового бара
2. А зачем все значения индикатора получать каждый раз, и при этом еще заботиться о направлении индексации? какая вообще задача стоит?
Зачем оборачивать простой индикатор в класс если он используется потом или на графике или через iCustom?
Второе решение лучше, потому что является объектно-ориентированным
ООП ради ООП, ну ок.
1. Можно на открытие нового бара
2. А зачем все значения индикатора получать каждый раз, и при этом еще заботиться о направлении индексации? какая вообще задача стоит?
Проблему решил по условиям цикла, теперь все работает как хотелось. спасибо!
Зачем оборачивать простой индикатор в класс если он используется потом или на графике или через iCustom?
ООП ради ООП, ну ок.
Все верно))
Очень удобно, всем советую