От начального до среднего уровня: Индикатор (III)
В предыдущей статье "От начального до среднего уровня: Индикатор (II)", мы узнали много нового, поскольку продемонстрировали, как реализовать скользящую среднюю очень простым, практичным и совершенно функциональным способом. Однако то, что было показано, можно считать лишь кратким введением в мир программирования на MQL5, поскольку материал достаточно базовый, простой и понятный. Но мы можем сделать гораздо больше.
Итак, постарайтесь разобраться в представленных здесь концепциях. Не стоит просто копировать код и не думайте, что если вы не можете сделать это, то никто другой тоже не сможет. Понимание концепции важнее, чем понимание самого кода, поскольку код может меняться в зависимости от того, кто его пишет, в то время как концепция всегда останется. Мы начнем с чего-то очень простого, поскольку то, что вы увидите, может стать очень сложным, если мы внезапно применим некоторые функциональные возможности.
Один индикатор и несколько графических представлений
Вы наверняка уже видели, как кто-то программирует или даже пытается создать систему или оперативную настройку для заработка на экономических рынках. Нередко многие из этих систем используют различные скользящие средние, которые во многих случаях применяются в обратном порядке. Кроме того, существуют канальные системы, такие как знаменитые полосы Боллинджера, которые основаны на двух скользящих средних: одна представляет собой верхнюю полосу, а другая - нижнюю. Но мы здесь не для того, чтобы объяснять, как данную систему можно использовать для торговли на рынке. Наша цель - показать, как можно сделать нечто подобное просто и практично.
В случае с полосами Боллинджера, которые мы используем в качестве примера (но это может быть что угодно другое), у нас есть две линии (иногда три), где одна представляет собой внутреннее среднее значение канала. Но мы сделаем проще и будем работать двумя линиями, чтобы можно было легче понять, как реализовать любое количество линий. Для начала мы воспользуемся приведенным ниже кодом.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 1 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buffer[]; 11. //+------------------------------------------------------------------+ 12. int OnInit() 13. { 14. SetIndexBuffer(0, gl_buffer, INDICATOR_DATA); 15. 16. return INIT_SUCCEEDED; 17. }; 18. //+------------------------------------------------------------------+ 19. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 20. { 21. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 22. gl_buffer[c] = High[c]; 23. 24. return rates_total; 25. }; 26. //+------------------------------------------------------------------+
Код 01
Я не думаю, что нужно показывать, что будет делать данный код при запуске и размещении на графике, так как это было подробно описано в предыдущих двух статьях. Всё, что мы должны сделать, это посмотреть, что делается в функции-обработчике события, в данном случае в функции OnCalculate. Можно увидеть, что здесь мы явно используем максимальное значение. Иными словами, у нас будет линия графического представления, которая будет следовать за максимумом каждого бара, поскольку мы не выполняем никаких сглаживающих расчетов. И да, расчеты скользящей средней как раз и направлены на то, чтобы сгладить кривую, которая будет графически представлена на экране, создавая среднее значение среди множества значений, которые использовались в расчете. Но это требует объяснения математического материала, что выходит за рамки данной статьи.
Хорошо, данный индикатор, который показан в коде 01, работает отлично. Прошу заметить, что мы используем расширенную версию функции OnCalculate. Причина этого сейчас станет понятна. Теперь у меня к вам вопрос: как можно добавить к графику вторую линию графического представления? Цель состоит в том, чтобы представить, например, минимумы каждого бара. Можно сказать, что достаточно создать новый индикатор и изменить код в строке 22 так, чтобы вместо High использовался Low. И вы были бы правы. Данная идея ни в коем случае не является ошибочной - она работает.
Правда это усложняет ситуацию, поскольку на графике будет два индикатора. Один маленький момент: каждый индикатор будет работать с одной из линий графического представления. Однако можно добиться большего - объединить эти два индикатора в один код. Демонстрация того, как это сделать, является целью данной темы. Я знаю, что сначала это может показаться сложным, но если понять то, что показано, можно будет создать любой индикатор с несколькими линиями графического представления. Помните, что на данный момент мы рассматриваем самый простой способ сделать это. Позже, если вы захотите, мы рассмотрим более сложную форму.
Итак, мы изменим код 01, чтобы создать вторую линия графического представления. Сделаем это шаг за шагом, чтобы каждый мог проследить и понять, как это происходит.
Первое, что нужно сделать, - это создать новый буфер, который будет содержать новые данные графического представления. Напомним, что тип DRAW_LINE, который мы используем, требует одного буфера для каждой части информации о графическом представлении. В результате мы получим следующее:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 1 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ . . .
Код 02
Код 02 - фрагмент содержимого, которое мы собираемся реализовать, ведь мы будем делать это шаг за шагом, так будет проще. Прошу заметить, что мы изменили название буфера в строке 10 и добавили новое в строке 11. Таким образом, мы начинаем реализовывать вторую линию графического представления. Следующий шаг мы реализуем быстрее, чтобы убедиться, что всё сделано правильно. После этого получим следующий код:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 1 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ 13. int OnInit() 14. { 15. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 16. SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); 17. 18. return INIT_SUCCEEDED; 19. }; 20. //+------------------------------------------------------------------+ 21. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 22. { 23. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 24. { 25. gl_buff_max[c] = High[c]; 26. gl_buff_min[c] = Low[c]; 27. } 28. 29. return rates_total; 30. }; 31. //+------------------------------------------------------------------+
Код 03
Хорошо, это основная часть. Однако у данного кода есть небольшая проблема, которую нам еще предстоит решить. Но прежде нужно понять, что это за проблема и почему она возникает. Обратите внимание, что в строке 16 мы создаем новый индексатор. Каждый буфер, используемый в индикаторе, который MetaTrader 5 должен будет поддерживать и наблюдать, нуждается в уникальном индексаторе. После того, строка 16 будет определена, буфер можно использовать, как показано в строке 26.
У этого буфера, используемого в системе графического представления, могут быть различные функции. Пока что мы будем использовать только тот тип, который предназначен для содержания данных, которые будут использоваться для представления каких-то элементов на графике. Хорошо, код 03 может быть скомпилирован. Однако при применении к графику результат получается таким:

Изображение 01
«Но что произошло здесь? Я не понимаю, почему мы видим только линию графического представления минимальных значений?» Причина в том, что мы сообщаем MetaTrader 5 о том, что индикатор содержит только буфер графического представления и информацию для представления. Можно увидеть это в строках 07 и 08. Поскольку на самом деле у нас два буфера и две линии, нам нужно лишь изменить информацию, упомянутую в строках 07 и 08. В этом случае давайте изменим код, как показано ниже:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 2 08. #property indicator_plots 2 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ . . .
Код 04
Прошу заметить, что мы изменили только те строки, о которых говорилось выше. Однако, когда индикатор накладывается на график, получается следующее:

Изображение 02
«Опять это? Теперь я действительно не понимаю. Разве код не должен был графически представлять две линии? Почему я вижу только одну?» Спокойно, дорогие читатели. Наберитесь терпения. Не надо беспокоиться. Причина, по которой вы видите только одну линию заключается в том, что ко второй линии не применяется цвет. Чтобы прояснить это, посмотрите, как настроен индикатор:

Анимация 01
Обратите внимание, что ДЛЯ ВТОРОЙ ЛИНИИ НЕТ ЦВЕТА. И даже при попытке приписать ему значение цвета, оно не появляется. Чтобы решить данную проблему, нужно указать компилятору, чтобы он зарезервировал и создал вторую линию. Для этого нужно еще раз изменить код, как показано ниже:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrRed 06. //+----------------+ 07. #property indicator_type2 DRAW_LINE 08. #property indicator_color2 clrGreen 09. //+----------------+ 10. #property indicator_buffers 2 11. #property indicator_plots 2 12. //+----------------+ 13. double gl_buff_max[], 14. gl_buff_min[]; 15. //+------------------------------------------------------------------+ . . .
Код 05
Давайте посмотрим, что было добавлено в код, который можно увидеть здесь, в коде 05. Чтобы сделать его более наглядным, мы использовали разные цвета. Таким образом, когда вы помещаете индикатор на график, можно увидеть это:

Изображение 03
Видите, как легко реализовать разные линии графического представления в одном и том же индикаторе? Всё, что нужно сделать, - это постепенно добавлять элементы, зная, что мы делаем. Поскольку мы не проводим здесь никаких вычислений, линии никогда не пересекутся. Это было бы примерно так же, как если бы мы внедряли индикатор полос. Разница в том, что одна из линий будет получать значения от одной полосы, а другая - от другой, создавая нечто похожее на знаменитые полосы Боллинджера. Это очень интересная тема, не так ли?
Я полагаю, что теперь вы сможете создавать различные типы и стили индикаторов, основываясь только на этих знаниях. Но прежде, чем мы углубимся в эту тему, поскольку эта часть программирования очень интересна, не хочется ли вам изменить индикатор на изображении 03 так, чтобы линии были цветными? «Это выглядит сложно». Но это действительно сложно или вы всё ещё не знаете, как поступить? Давайте посмотрим. Для этого мы переходим к новой теме.
Цветные линии графического представления
Один момент, который привлекает внимание людей и вызывает у них наибольший восторг, - это индикатор с линиями, которые меняют цвет. До этого момента мы создавали очень простую систему, в которой можно использовать либо один, либо другой цвет, но как насчет смены цветов? «Это кажется очень сложным в исполнении, особенно для меня, который только начинает изучать программирование на MQL5». Понятно, мой дорогой читатель. Но то, что вы только начинаете, это не значит, что вы не можете интересоваться тем, что будет здесь показано. И НЕТ, создавать индикатор, линии которого графически представлены в нескольких цветах, не сложно, это просто немного другое.
Чтобы дать вам представление о том, о чем мы говорим, давайте возьмем код, реализованный в предыдущей теме. Чтобы отобразить результат изображения 03, оно должно содержать нечто очень похожее на то, что видим ниже:
//+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed //+----------------+ #property indicator_type2 DRAW_LINE #property indicator_color2 clrGreen //+----------------+ #property indicator_buffers 2 #property indicator_plots 2 //+----------------+ double gl_buff_max[], gl_buff_min[]; //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); return INIT_SUCCEEDED; }; //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) { for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) { gl_buff_max[c] = High[c]; gl_buff_min[c] = Low[c]; } return rates_total; }; //+------------------------------------------------------------------+
Код 06
Код 06 является результатом всех модификаций, сделанных в коде 01, пока мы не смогли изобразить две линии на графике. Теперь, чтобы сделать эти линии разноцветными, просто выполним следующие действия.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_COLOR_LINE 05. #property indicator_color1 clrMaroon, clrTomato, clrBlue 06. //+----------------+ 07. #property indicator_type2 DRAW_COLOR_LINE 08. #property indicator_color2 clrGreen, clrPaleGreen 09. //+----------------+ . . .
Код 07
Теперь сравним код 06 с кодом 07. Прошу заметить, что мы изменили тип объекта, используемого в графическом представлении, с DRAW_LINE на DRAW_COLOR_LINE. После этого мы можем указать больше одного цвета в свойстве color каждой из линий. Количество цветов совершенно произвольно и, согласно документации MQL5, может иметь максимум 64 значения. На самом деле, в одной строке мы объявили три цвета, а в другой - два. Однако можно использовать любые цвета по своему усмотрению. Но этого недостаточно. Нам нужно реализовать ещё несколько вещей, чтобы MetaTrader 5 понял, что мы хотим сделать.
А теперь будьте внимательны. При использовании многоцветной графической системы нам необходим дополнительный буфер, как видно на изображении ниже, которое можно найти в документации.

Изображение 04
Как видите, все эти выделенные точки требуют наличия цветового буфера. Без этого буфера MetaTrader 5 НЕ БУДЕТ ЗНАТЬ, КАКОЙ ЦВЕТ ИСПОЛЬЗОВАТЬ. Поэтому следующее изменение нам нужно внести в объявление буфера. Это можно увидеть в приведенном ниже фрагменте кода:
. . . 09. //+----------------+ 10. #property indicator_buffers 4 11. #property indicator_plots 2 12. //+----------------+ 13. double gl_buff_max[], 14. gl_buff_min[], 15. gl_color_max[], 16. gl_color_min[]; 17. //+------------------------------------------------------------------+ . . .
Код 08
Во фрагменте кода 08 мы фактически определяем наши буферы. Прошу заметить, что в строке 10 мы указываем, что нам нужно четыре буфера, но почему именно четыре, если мы собираемся изобразить графически только две линии? Причина в том, что нам нужен буфер для представляемых значений и ещё один буфер для каждого цвета. Представьте себе небольшую двухзначную структуру. Хотя в MetaTrader 5 для этого не используется структура, мы должны думать именно так. А поскольку MetaTrader 5 не использует структуры для такого моделирования, в итоге нам понадобится два буфера. Но, поскольку нам нужно построить две линии, в конечном итоге нам понадобится четыре буфера. Они объявляются, начиная со строки 30 и далее, как видно из фрагмента кода 08.
Отлично, теперь осталось реализовать последний шаг. Показываем это в приведенном ниже фрагменте:
. . . 17. //+------------------------------------------------------------------+ 18. int OnInit() 19. { 20. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 21. SetIndexBuffer(1, gl_color_max, INDICATOR_COLOR_INDEX); 22. SetIndexBuffer(2, gl_buff_min, INDICATOR_DATA); 23. SetIndexBuffer(3, gl_color_min, INDICATOR_COLOR_INDEX); 24. 25. return INIT_SUCCEEDED; 26. }; 27. //+------------------------------------------------------------------+ 28. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 29. { 30. double mhs = 0, 31. mhi = 0, 32. ml = 0; 33. const double desv = 0.01; 34. 35. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 36. { 37. gl_color_max[c] = (mhi > High[c] ? 0 : (mhs < High[c] ? 1 : 2)); 38. mhs = mhi = gl_buff_max[c] = High[c]; 39. mhs += (mhs * desv); 40. mhi -= (mhi * desv); 41. gl_color_min[c] = (ml < Low[c] ? 0 : 1); 42. ml = gl_buff_min[c] = Low[c]; 43. } 44. 45. return rates_total; 46. }; 47. //+------------------------------------------------------------------+
Код 09
Прежде, чем объяснить, что мы делаем во фрагменте кода 09, давайте посмотрим на результат работы данного индикатора при применении к графику любого инструмента. Это можно увидеть на изображении ниже:

Изображение 05
То, что мы видим, предназначено только для демонстрации, так как при создании данного индикатора у нас были исключительно образовательные цели. Но можно видеть, что код этапа инициализации индикатора практически не изменился, добавлены только строки 21 и 23. Однако очень важно, чтобы вы понимали, что делает каждая из этих новых линий. Прежде всего, обратите внимание, что каждый буфер имеет свой идентификатор. Неважно, что именно мы собираемся в них поместить; у каждого из них должен быть собственный идентификатор, иначе MetaTrader 5 будет путаться при их использовании.
В таком случае очень важно объявлять всё в определенном порядке. То есть, ДО ТОГО, КАК объявить следующий буфер данных, мы должны объявить все буферы данных, которые будут использоваться в данной линии графического представления. В этом случае это цветовой буфер. Если мы объявим данные или цветовые буферы не в логическом порядке, ВЫ НЕ получите желаемого результата. Поэтому будьте внимательны при объявлении элементов здесь. Порядок вещей влияет на конечный результат. После инициализации мы можем сосредоточиться на процедуре, которая будет обрабатывать событие Calculate, запускаемое MetaTrader 5.
Обратите внимание, что в этом случае мы выполняем некоторые расчеты и проверки. Это связано с тем, что нам нужно указать MetaTrader 5, какой из цветов, определенных в коде 07, будет использован при рисовании линии на экране. «Но подождите, я не понимаю, как это делается. Здесь у нас только числа, а в коде 07 были значения цветов. Как MetaTrader 5 узнает, какой цвет использовать?»
Итак, мой дорогой читатель, на этом этапе важно понять то, что уже объяснялось в другой статье: что такое массивы. То, что у нас есть в коде 07, - это массивы цветов. Каждый из них будет находиться в определенном индексе массива. Поэтому в строках 21 и 23 мы используем перечисление INDICATOR_COLOR_INDEX. МЫ ГОВОРИМ НЕ О ТОМ, КАКОЙ ЦВЕТ ИСПОЛЬЗОВАТЬ, но о том, каков индекс цвета в определенном массиве. Но в каком массиве? Если у нас их два в коде 07, как MetaTrader 5 узнает, какой из них использовать?
И тут в игру вступает другой вопрос, который мы недавно обсуждали. Другими словами, порядок составляющих влияет на конечный результат. Поскольку мы обычно используем данный тип графического представления в единичном виде (т.е. один индикатор, одна линия), MetaTrader 5 будет использовать цветовую схему, непосредственно связанную с идентификатором представляемого типа. Я знаю, что это может показаться запутанным, но прошу заметить, что в строках 04 и 05 у нас есть значение идентификатора, в данном случае - число один. В строках 07 и 08 у нас есть ещё один идентификатор, в данном случае число два. Таким образом, когда мы связываем значение с индикатором, который должен быть представлен графически, компилятор будет использовать данный идентификатор, чтобы знать, какую цветовую схему использовать.
Чтобы показать это, мы определили разное количество цвета в каждом из объявлений, встречающихся в коде 07, чтобы вы могли понять это, когда начнете практиковаться с реальным кодом.
Хотя эта часть немного запутанная, именно потому, что мы используем всё статически и размещаем более одной линии графического представления одновременно, на практике вы увидите, что на самом деле довольно просто понять, как объявлять и использовать подобные вещи.
В любом случае, когда пользователь захочет изменить цветовую схему, он получит доступ к интерфейсу, подобному этому:

Изображение 06
Обратите внимание, что благодаря объявлениям, сделанным в строках 05 и 08 из кода 07, пользователь сможет настроить более одного цвета. Поэтому желательно, чтобы интерфейс был как можно более понятным и простым. Иначе, хотя код может быть весьма полезен для определенного типа операций, у пользователя будет плохой опыт его использования.
Коды будут в приложении, так что вы сможете изучить, как поступать в таких ситуациях. Но прежде, чем закончить сегодняшнюю статью, я хочу рассказать о другом индикаторе, который находится как бы между одним и другим понятием, в зависимости от того, как мы его применяем, - это может быть индикатор полос или даже индикатор пересечения средних. Но, чтобы не путаться, мы рассмотрим это в новой теме.
Индикатор типа DRAW_FILLING
Данный индикатор довольно интересен, поскольку в зависимости от того, как он реализован, он может привести к индикатору пересечения средних или даже индикатору полос. Однако у начинающих программистов он часто вызывает сомнения именно из-за того, как его нужно объявлять. Чтобы вы поняли, насколько просто объявить и использовать данный тип индикатора, возьмем за основу код 06, приведенный в начале статьи. С этого момента будет гораздо проще понять, что мы пытаемся сделать с помощью индикатора DRAW_FILLING.
Получив код 06 в качестве отправной точки, мы изменим его для понимания индикатора DRAW_FILLING. По сути, код 06 будет выглядеть таким образом:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_FILLING 05. #property indicator_color1 clrRed, clrGreen 06. //+----------------+ 07. #property indicator_buffers 2 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ 13. int OnInit() 14. { 15. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 16. SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); 17. 18. return INIT_SUCCEEDED; 19. }; 20. //+------------------------------------------------------------------+ 21. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 22. { 23. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 24. { 25. gl_buff_max[c] = Open[c]; 26. gl_buff_min[c] = Close[c]; 27. } 28. 29. return rates_total; 30. }; 31. //+------------------------------------------------------------------+
Код 10
«Интересно. Насколько мне известно, код 06 претерпел очень мало изменений. Но у меня есть некоторые сомнения относительно нескольких аспектов, например: почему в процедуре, которая работает с событием Calculate, мы используем цену открытия и закрытия?» Это делается для того, чтобы вызвать поворот или пересечение максимальных и минимальных значений, как они называются в коде 10. Прошу заметить, дорогие читатели: время от времени мы имеем бар Sell, а время от времени - бар Buy.
Теперь представьте, что данный индикатор DRAW_FILLING - это ткань, с обоих сторон которой нанесен принт. Когда значения в буферах, определенных в строках 15 и 16, пересекаются, происходит поворот, который заставляет MetaTrader 5 показывать ту или иную сторону ткани. Информация, которая будет отображаться или печататься на ткани, объявляется в строке 05. Поэтому мы можем окрасить область в тот или иной цвет. Если бы не было пересечения или поворота, мы бы увидели только один из принтов или цветов, определенных в строке 05.
Однако мы должны учитывать маленькую деталь: несмотря на чрезвычайную простоту кода 10, при применении на графике он выглядит так, как показано на рисунке ниже:

Изображение 07
Выглядит это не очень привлекательно и, на самом деле, может быть довольно запутанным в зависимости от типа информации, которая вычисляется и представляется графически. Однако в строке 05 у пользователя будет возможность настроить некоторые данные, как показано на рисунке ниже:

Изображение 08
То есть, в зависимости от типа планируемой работы, этот индикатор типа DRAW_FILLING может быть весьма интересным. Однако именно из-за того, что заметно на рисунке 07, данный индикатор чаще всего отображается не прямо на основном графике, а в отдельном окне. Тогда человек начинает задумываться: «Друг мой, всё становится очень сложным. Я едва научился создавать цветовой индикатор, а теперь вы начинаете рассказывать о том, как поместить его в другое окно? Вы излагаете такое количество информации, что мне придется упорно заниматься».
Не волнуйтесь, это не страшно. На самом деле MQL5, предназначенный для программирования в MetaTrader 5, предоставляет очень много интересных и практичных ресурсов.
Среди них есть и такой, как размещение индикатора в другом окне. Однако это окно останется привязанным к главному. Один из самых простых и легких способов сделать это - указать компилятору сгенерировать код индикатора таким образом, чтобы при его применении к графику, MetaTrader 5 почувствовал, что нужно открыть новое окно или подокно. Это достигается путем добавления одной строки в код индикатора. Таким образом, код 10, показанный выше, будет выглядеть так:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_separate_window 05. //+----------------+ 06. #property indicator_type1 DRAW_FILLING 07. #property indicator_color1 clrRed, clrGreen 08. //+----------------+ 09. #property indicator_buffers 2 10. #property indicator_plots 1 11. //+----------------+ 12. double gl_buff_max[], 13. gl_buff_min[]; 14. //+------------------------------------------------------------------+ 15. int OnInit() 16. { 17. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 18. SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); 19. 20. return INIT_SUCCEEDED; 21. }; 22. //+------------------------------------------------------------------+ 23. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 24. { 25. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 26. { 27. gl_buff_max[c] = Open[c]; 28. gl_buff_min[c] = Close[c]; 29. } 30. 31. return rates_total; 32. }; 33. //+------------------------------------------------------------------+
Код 11
Прошу заметить, что единственное различие между кодами 10 и 11 заключается именно в строке 04, которой нет в коде 10, но она есть в коде 11. Скомпилировав данный код, вы можете попросить MetaTrader 5 добавить его на график. При этом изображение 07, которое раньше могло быть довольно запутанным, будет выглядеть так:

Изображение 09
Изображение 09, конечно, гораздо проще, хотя поначалу оно может немного смутить некоторых пользователей при интерпретации данного графика.
Заключительные идеи
В этой статье мы показали, как работать с двумя разными типами индикаторов, которые можно адаптировать по-разному. Цель - создать некое приложение для своих целей. Несмотря на кажущуюся простоту материала, я верю, что, если проявить творческий подход и любопытство, можно понять, что это содержание можно распространить и на другие типы индикаторов: DRAW_SECTION, DRAW_HISTOGRAM, DRAW_ARROW, DRAW_ZIGZAG, DRAW_BARS и DRAW_CANDLES. Все они работают так же, как и увиденные в этой статье, хотя мы рассмотрели только два, или три, если считать, что мы используем тип DRAW_COLOR_LINE. Но это уже мелочи.
На самом деле важно, чтобы вы практиковались и понимали, что всё, что изображено на графике, каким бы сложным оно ни казалось, довольно просто в своем построении. По сути, нужно просто указать компилятору, как должен быть создан индикатор, используя полностью статическую реализацию. Создание статических индикаторов - это просто и даже увлекательно, но настоящее удовольствие можно найти в динамических индикаторах. Об этом мы узнаем совсем скоро. А пока вы можете изучать и применять на практике то, что мы увидели в этой статье, ведь скоро мы сделаем этот вид реализации гораздо более увлекательным и интересным.
Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/15828
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Возможности Мастера MQL5, которые вам нужно знать (Часть 53): Market Facilitation Index
Нейросети в трейдинге: Спайково-семантический подход к пространственно-временной идентификации (S3CE-Net)
От начального до среднего уровня: Индикатор (IV)
Автоматизация торговых стратегий на MQL5 (Часть 4): Построение многоуровневой системы зонального восстановления
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования