От начального к среднему уровню: Технические индикаторы (I)
Введение
В предыдущей статье «От начального к среднему уровню: Перегрузка операторов (VI)» был показан способ работы с перегрузкой операторов на наиболее интересном уровне, вплоть до момента, когда нам приходилось писать всё меньше кода и при этом мы могли создавать код, который становился всё более понятным. По крайней мере, именно так я вижу конечный результат. Возможно, это связано с моим опытом работы с C и C++, где код, как правило, довольно насыщен символическими конструкциями. Это немного отличается от того, что мы обычно видим в коде, написанном на MQL5 или на других языках, например Python. В отличие от Python, где нельзя использовать возможности самого языка, чтобы сделать код более символичным, в MQL5 мы можем создать нечто подобное тому, что видели в предыдущих статьях.
Я должен признать одну вещь. Идея создателей MQL5 дать более опытным программистам возможность показать, как можно делать подобные вещи, была действительно великолепной. К этому, конечно же, добавляется то, что MQL5 во многих отношениях похож на C и C++. Это значительно облегчает обучение для таких специалистов, хотя C и C++ — языки, освоить которые гораздо труднее, чем MQL5. Но это сейчас не главное.
В этой статье мы затронем немного более лёгкую и необычную тему. Возможно, для многих из вас это будет даже гораздо интереснее, поскольку последние статьи были довольно насыщенными и содержали материал, который не так просто изучить и усвоить сразу. Итак, в этой статье мы рассмотрим гораздо более приятную и значительно более простую тему. Кроме того, это то, чем вы сможете начать пользоваться практически сразу.
Итак, пришло время отложить в сторону всё, что может нас отвлекать, и сосредоточиться на том, что мы рассмотрим и объясним в этой статье. Итак, начнём.
Технические индикаторы (I)
Пожалуй, одной из вещей, на понимание которой у начинающих изучать MQL5 с целью создать какой-либо механизм торгового сетапа, ускоряющий анализ при торговле на рынке, уходит больше всего времени, — это то, как создавать или, точнее, программировать любой индикатор. Также необходимо знать, как связать его с советником. Но это мы подробно рассмотрим позже.
Мы уже видели в статье «От начального к среднему уровню: Индикатор (IV)», как реализовать простой индикатор, цель которого состояла в том, чтобы указывать, когда один бар находится внутри предыдущего, формируя тем самым так называемый паттерн inside bar. Хотя весь приведённый здесь код носит учебный характер и предназначен для обучения, не могу отрицать, что в некоторых случаях мы можем создать очень простое приложение. Тем не менее, оно может быть запрограммировано не должным образом и ни в коем случае не должно считаться завершённым на 100 %. Именно этот случай мы и рассмотрим далее. Поэтому будьте осторожны, используя на реальном счёте то, что мы здесь реализуем, поскольку, по понятным причинам, это может привести к финансовым потерям. То, что мы собираемся сделать, — это исключительно учебное приложение.
Если вы только начинаете программировать на MQL5, то наверняка уже искали, как создавать индикаторы для тех или иных задач. Однако MetaTrader 5 уже по умолчанию предоставляет нам различные индикаторы, расчёты которых выполняются внутри самой платформы. И нет, я не имею в виду те индикаторы, которые можно найти, просматривая содержимое каталога индикаторов. Нет, не эти.
Индикаторы, о которых я говорю, можно найти в разделе «Функции технических индикаторов». Все индикаторы, перечисленные там, рассчитываются MetaTrader 5 по умолчанию. Вам не нужно писать весь код, необходимый для их расчёта. Всё, что вам нужно сделать, — это обратиться к ним из своего кода, чтобы использовать их. Это справедливо для любого приложения, разработанного для работы в MetaTrader 5.
Я понимаю, что для многих такой подход может показаться не слишком интересным, а для других — сложным в реализации. Когда вы только начинаете, вполне естественно думать, что вам нужно написать весь код, необходимый для расчёта индикатора. В других случаях вы также можете подумать, что, если нанесёте индикатор на график, не создав его с нуля, то не сможете полностью контролировать его поведение.
Что ж, такой образ мышления в какой-то степени является частью процесса обучения. Вряд ли вы по-настоящему чему-то научитесь, если будете ограничиваться использованием готовых решений. На самом деле это не обучение, а просто способ сэкономить время, пока вы пытаетесь заново изобрести велосипед. Как и любой хороший профессионал, вы должны стараться ставить перед собой цели и задачи, когда это возможно. Это не означает, что освоение всех возможностей, которые предлагает тот или иной инструмент, — пустая трата времени. Это не так. Поэтому я показываю много возможностей, которые вам, скорее всего, никогда не понадобятся. Одной из них была перегрузка операторов. Это довольно забавно, хотя, возможно, вам так и не придётся когда-нибудь применить эти знания на практике.
Почему я об этом говорю? Дело в том, мой дорогой читатель, что вы встретите огромное количество людей, которые покажут вам, как сделать то или иное. Однако лишь немногие из них действительно объяснят вам, почему стоит поступать так, а не иначе. Так вы сможете выбрать самый простой и быстрый путь к достижению своей цели.
Хорошо, давайте начнём с того, что я считаю самым простым индикатором из всех: скользящей средней. Чтобы создать нечто подобное с помощью технических индикаторов, нам нужно всего лишь написать код, подобный приведённому ниже.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property description "DEMO Indicator" 05. //+------------------------------------------------------------------+ 06. #property indicator_chart_window 07. #property indicator_applied_price PRICE_CLOSE 08. #property indicator_buffers 1 09. #property indicator_plots 1 10. #property indicator_type1 DRAW_LINE 11. #property indicator_color1 clrRed 12. #property indicator_style1 STYLE_SOLID 13. #property indicator_width1 1 14. //+------------------------------------------------------------------+ 15. #define def_nPeriods 9 16. //+------------------------------------------------------------------+ 17. double Buff_iMA[]; 18. int Handle; 19. //+------------------------------------------------------------------+ 20. int OnInit(void) 21. { 22. SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA); 23. if ((Handle = iMA(NULL, NULL, def_nPeriods, 0, MODE_EMA, _AppliedTo)) == INVALID_HANDLE) 24. { 25. Print("Could not start the indicator..."); 26. return INIT_FAILED; 27. }; 28. 29. return INIT_SUCCEEDED; 30. }; 31. //+------------------------------------------------------------------+ 32. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 33. { 34. CopyBuffer(Handle, 0, 0, Bars(NULL, NULL), Buff_iMA); 35. 36. return rates_total; 37. }; 38. //+------------------------------------------------------------------+ 39. void OnDeinit(const int reason) 40. { 41. if (Handle != INVALID_HANDLE) 42. IndicatorRelease(Handle); 43. }; 44. //+------------------------------------------------------------------+
Код 01
Этот код 01 содержит всё необходимое для создания скользящей средней и её отображения на графике. Действительно, мы не можем изменить тип скользящей средней или период, то есть количество баров, используемых в расчёте. Однако мы можем изменить ряд параметров, таких как цвет, толщина, стиль линии и тип используемой цены. И всё это с помощью этого кода, который до смешного прост.
"Подождите минутку. Вы говорите, что здесь можно изменить несколько вещей, но я не вижу ни одной строки, где было бы указано, как это сделать. На мой взгляд, если мы захотим что-то изменить, нам придётся перекомпилировать код". Итак, у нас есть скептик (СМЕХ). Отлично, мне нравится, когда люди поначалу сомневаются. Давайте посмотрим, как ведёт себя этот код, чтобы проверить, правда ли то, что я о нём говорю.
Для начала, прежде чем использовать на графике наш код 01, нам нужен код, который, как мы знаем, даст правильные данные. К счастью, в MetaTrader 5 есть для этого вполне подходящий вариант. Поэтому сначала мы добавим этот индикатор, чтобы использовать его в качестве эталона. Это показано в следующей анимации.

Анимация 01
Теперь у нас есть способ проверить, правильно ли работает код 01. Хорошо, давайте добавим его на график. Сделав это, мы получим результат, показанный в следующей анимации.

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

Анимация 03
Обратите внимание: хотя на первый взгляд казалось, что мы ничего не можем настроить, нам удалось внести все изменения, о которых я упоминал выше. Это доказывает, что код работает именно так, как и было указано. Однако этим мы не ограничены. Мы можем пойти немного дальше. Но давайте действовать постепенно. Сначала я хочу объяснить, почему этот код 01 работает именно так, как мы видели в анимациях. Значительная часть того, что вам нужно знать, уже была объяснена в другой статье.
Ознакомьтесь со статьями «От начального к среднему уровню: Индикатор (I)» — «От начального к среднему уровню: Индикатор (IV)», чтобы понять основы этого кода 01.
Возможно, вам также стоит обратиться к статье «От начального к среднему уровню: События (I)», где были объяснены основы событийно-ориентированного программирования. Это поможет вам понять, как и почему работает код 01.
Если у вас уже есть необходимые знания, чтобы понять дальнейшие объяснения, мы можем продолжить. Обратите внимание, что в строке 15 я задаю значение. Именно это значение будет использоваться для расчёта скользящей средней. Теперь переходим к творческой части кода. Называть её творческой частью может показаться странным, но вскоре вы поймёте почему. Как и в случае с любым индикатором, который должен что-то отображать на графике, нам нужно определить как минимум один буфер. Это делается в строке 22. В строке 23 мы пытаемся задать значение переменной, которая будет хранить идентификатор технического индикатора. А теперь обратите на это внимание, мой дорогой читатель. Каждый технический индикатор необходимо настроить, чтобы MetaTrader 5 знал, что с ним делать.
Недостаточно просто сказать: «Хочу индикатор» — и ожидать, что MetaTrader 5 создаст его именно таким, как вы хотите. Чтобы это произошло, нам нужно указать, как должен рассчитываться индикатор. Чтобы узнать, какую информацию нужно предоставить MetaTrader 5, обратитесь к документации по соответствующим техническим индикаторам. Однако в большинстве случаев можно использовать первые два аргумента, как показано в коде 01. Это позволит индикатору подстроиться под текущие символ и период графика. Если здесь указать период графика или даже конкретный символ, MetaTrader 5 найдет и будет использовать данные, соответствующие тому, что вы указали.
Это позволяет нам, например, иметь 10-минутный график, в то время как расчеты выполняются на основе данных 60-минутного графика или даже дневного графика. То же самое относится и к символу. Вы можете указать один символ и использовать индикатор на графике другого.
"Друзья, это просто потрясающе. Я не знал, что мы можем делать что-то подобное". Да, мой дорогой читатель, мы можем делать это и многое другое. Вопрос в следующем: зачем вообще делать что-то подобное на практике?
Итак, как видите, в случае iMA мы должны с помощью третьего аргумента указать, сколько баров будет использоваться в расчете. Далее мы указываем смещение, применяемое к скользящей средней. Обычно здесь используется значение 0, хотя в некоторых случаях может потребоваться другое значение, например, если вы реализуете скользящую среднюю для визуализации формирования разворота тренда. В пятом параметре, в случае iMA, мы указываем, какой тип скользящей средней следует рассчитывать. Наконец, мы указываем, какой тип цены будет использоваться при расчете.
Если идентификатор был успешно создан, следующий шаг будет выполняться в обработчике события OnCalculate. В случае возникновения ошибки об этом будет сообщено в сообщении в строке 25. В любом случае, произойдёт здесь ошибка или всё сработает правильно, в какой-то момент будет вызвано событие OnDeinit. Когда это произойдёт, мы освободим идентификатор в строке 42. Это хорошая практика программирования, поскольку, теоретически, если мы не освободим идентификатор, MetaTrader будет продолжать выполнять уже ненужные вычисления и расходовать ценные ресурсы.
А теперь давайте рассмотрим творческую часть кода. Она находится в событии OnCalculate. Но подождите-ка, а где же вычисления для построения скользящей средней? Что ж, вот здесь и начинается самое интересное, мой дорогой читатель. Вам не нужно программировать эти вычисления и даже беспокоиться о них, поскольку MetaTrader 5 выполняет их сам. По этой причине всё, что нам нужно сделать, — это попросить MetaTrader 5 передать рассчитанные значения в буфер индикатора. Это делается в строке 34.
"Хм. Я это вижу, но не понимаю. Даже после того, как я увидел результаты в анимациях, я всё ещё не до конца понимаю, что делает эта строка 34 и зачем она нам нужна". Хорошо, давайте разберёмся. Поскольку MetaTrader 5 выполняет вычисления за нас, результаты сохраняются во внутреннем буфере платформы. Чтобы получить доступ к этим данным, мы должны указать MetaTrader 5, какие данные хотим получить.
Для этого нам нужно знать идентификатор, связанный с этими вычислениями. Без него мы не сможем получить эти данные. "Но подождите-ка. Вы хотите сказать, что, если я знаю, где находятся данные, я могу прочитать их в любой момент?" Да, мой дорогой читатель, если данные доступны, вы сможете получить к ним доступ в любой момент, если знаете, какой идентификатор использовать. Интересно. Действительно, это довольно интересно, и чуть позже я покажу вам, как вы можете этим воспользоваться. Но давайте продолжим разбирать, что делает этот код 01.
Второй аргумент в строке 34 может меняться в зависимости от определённых обстоятельств. Обычно он будет равен нулю. Однако это не правило. Что касается третьего параметра, почти во всех случаях он тоже будет равен нулю, если только вы не захотите провести какой-либо анализ, чтобы попытаться обнаружить разворот тренда или изучить конкретное движение. Но в целом этот третий параметр будет равен нулю.
Что касается четвёртого параметра, здесь есть кое-что интересное. В зависимости от того, как вы настроите параметры, у нас может отображаться больше или меньше данных. Кроме того, в зависимости от того, как вы используете этот параметр, можно получить скользящую среднюю, которая на первый взгляд покажется довольно необычной. Последний параметр, в свою очередь, связан со вторым, поскольку оба они связаны с буфером, в котором будут храниться данные для отображения.
А теперь давайте немного с этим поэкспериментируем. Это как раз напрямую связано с четвёртым параметром в строке 34. Чтобы понять, что я только что говорил об этом любопытном и интересном поведении, давайте заменим код обработчика OnCalculate на приведённый ниже фрагмент.
. . . 31. //+------------------------------------------------------------------+ 32. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 33. { 34. CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA); 35. PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, Bars(NULL, NULL) - def_nPeriods); 36. 37. return rates_total; 38. }; 39. //+------------------------------------------------------------------+ . . .
фрагмент 01
А теперь внимание, мой дорогой читатель. Обычно можно увидеть, что скользящие средние строятся от самых старых баров до самого последнего бара на графике. Однако мы, как программисты, можем сделать всё совершенно иначе и тем самым избежать чрезмерной перегруженности графика или отображения ненужных данных.
Этот фрагмент 01 создаёт скользящую среднюю типа «червь», которая по мере появления новых баров продвигается вперёд и сохраняет длину, равную количеству периодов, используемых в расчётах. На следующей анимации вы можете увидеть это поведение.

Анимация 04
Обратите внимание, что внутри красной скользящей средней находится жёлтая. Красная скользящая средняя — это та, которую мы видели в начале статьи. Жёлтая скользящая средняя соответствует коду 01, но с использованием фрагмента 01. Как только появляется новый бар, скользящая средняя смещается так, чтобы её длина оставалась равной девяти барам или значению, заданному в строке 15 кода 01. Очень интересно, не правда ли? И обратите внимание, насколько просто было создать нечто подобное. Именно такую реализацию можно получить, когда вы учитесь программировать. Обычные пользователи не знают, что в MetaTrader 5 мы можем делать такие вещи.
Отлично. Но не могли бы мы сделать всё это немного интереснее? Я говорю это потому, что мне хотелось бы знать, как можно изменить количество баров, используемых в расчёте, или, возможно, тип скользящей средней, которая будет использоваться, без необходимости компилировать код несколько раз. Да, мой дорогой читатель, мы можем сделать это очень просто, легко и быстро.
Взяв за основу код 01, мы изменим его, используя фрагмент, показанный ниже.
. . . 14. //+------------------------------------------------------------------+ 15. input uint def_nPeriods = 9; 16. input ENUM_MA_METHOD def_MA_Method = MODE_EMA; 17. //+------------------------------------------------------------------+ 18. double Buff_iMA[]; 19. int Handle; 20. //+------------------------------------------------------------------+ 21. int OnInit(void) 22. { 23. SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA); 24. if ((Handle = iMA(NULL, NULL, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE) 25. { 26. Print("Could not start the indicator..."); 27. return INIT_FAILED; 28. }; 29. 30. return INIT_SUCCEEDED; 31. }; 32. //+------------------------------------------------------------------+ . . .
Фрагмент 02
Теперь, после повторной компиляции кода, вы получите доступ к тому, что показано на следующем изображении.

Изображение 01
Хотя это и работает, информация, выделенная на изображении 01, не слишком информативна для пользователя. Было бы целесообразно изменить сам фрагмент 02 на тот, что показан ниже. Таким образом, мы получим результат, показанный на следующем изображении.
. . . 14. //+------------------------------------------------------------------+ 15. input uint def_nPeriods = 9; //Период: 16. input ENUM_MA_METHOD def_MA_Method = MODE_EMA; //Метод: 17. //+------------------------------------------------------------------+ . . .
Фрагмент 03

Изображение 02
Теперь пользователь будет знать, как каждое значение влияет на расчёт, даже если он не имеет ни малейшего представления о том, как на самом деле работает код и как строится скользящая средняя. Действительно, этот индикатор работает. Однако в зависимости от того, как вы реализуете свой индикатор, при его добавлении на графике может появиться нечто довольно странное. Проблему можно увидеть на следующем изображении.

Изображение 03
Проблема выделена зелёным кружком. Но почему мой индикатор показал именно такой результат? Причина, мой дорогой читатель, — в данных, хранящихся внутри индикатора. В случае индикатора, который мы рассматриваем в этой статье, если бы код был написан так, как показано ниже, возникла бы точно такая же проблема.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property description "DEMO Indicator" 05. //+------------------------------------------------------------------+ 06. #property indicator_chart_window 07. #property indicator_applied_price PRICE_CLOSE 08. #property indicator_buffers 1 09. #property indicator_plots 1 10. #property indicator_type1 DRAW_LINE 11. #property indicator_color1 clrRed 12. #property indicator_style1 STYLE_SOLID 13. #property indicator_width1 1 14. //+------------------------------------------------------------------+ 15. input uint def_nPeriods = 9; //Период: 16. input ENUM_MA_METHOD def_MA_Method = MODE_EMA; //Метод: 17. //+------------------------------------------------------------------+ 18. double Buff_iMA[]; 19. int Handle; 20. //+------------------------------------------------------------------+ 21. int OnInit(void) 22. { 23. SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA); 24. if ((Handle = iMA(NULL, NULL, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE) 25. { 26. Print("Could not start the indicator..."); 27. return INIT_FAILED; 28. }; 29. 30. return INIT_SUCCEEDED; 31. }; 32. //+------------------------------------------------------------------+ 33. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 34. { 35. CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA); 36. 37. return rates_total; 38. }; 39. //+------------------------------------------------------------------+ 40. void OnDeinit(const int reason) 41. { 42. if (Handle != INVALID_HANDLE) 43. IndicatorRelease(Handle); 44. }; 45. //+------------------------------------------------------------------+
Код 02
"Но подождите. Этот код 02 почти такой же, как код 01. Однако я не заметил, чтобы эта проблема там проявлялась". Тем не менее, проблема там тоже присутствует, мой дорогой читатель. Дело в том, что, поскольку на графике много баров, он оказывается частично скрытым. Но он всё равно там есть. В этом коде 02 проблема становится ещё более очевидной именно потому, что в строке 35, где мы копируем значения в буфер индикатора, который будет отображаться, расстояние между началом и концом данных меньше. Я хочу этим показать, что даже если вы не обнаружили ошибку в своём коде, это не значит, что её нет; она может просто находиться там, где вы не можете её увидеть.
Итак, для устранения подобных проблем у нас, по сути, есть два варианта. Первый из них уже появлялся во фрагменте 01, где строка 35 как раз исправляет эту проблему. Ещё один способ решить ту же проблему заключается в инициализации буфера, содержащего данные, которые будут отображаться. Точное место, в котором вы инициализируете буфер данных индикатора, повлияет на то, какой результат мы сможем получить.
Чтобы это стало немного понятнее и вы могли лучше это понять, давайте проведём два теста. Первый тест будет состоять в инициализации буфера непосредственно в процедуре OnInit, как показано ниже.
. . . 20. //+------------------------------------------------------------------+ 21. int OnInit(void) 22. { 23. SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA); 24. ArrayInitialize(Buff_iMA, EMPTY_VALUE); 25. if ((Handle = iMA(NULL, 0, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE) 26. { 27. Print("Could not start the indicator..."); 28. return INIT_FAILED; 29. }; 30. 31. return INIT_SUCCEEDED; 32. }; 33. //+------------------------------------------------------------------+ 34. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 35. { 36. CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA); 37. 38. return rates_total; 39. }; 40. //+------------------------------------------------------------------+ . . .
Фрагмент 04
Проблема в том, что такой подход может привести к несколько странному поведению индикатора, как вы можете видеть на следующем изображении.

Изображение 04
Видите, как линия скользящей средней на этом изображении 04 выглядит совершенно хаотично? Обычно это происходит, когда вы принудительно обновляете индикатор между двумя вызовами функции OnCalculate, которые выполняет MetaTrader 5. Помните, что данные, которые будут отображаться, поступают из MetaTrader 5. Мы не вычисляем их локально. Мы просто используем данные, предварительно вычисленные MetaTrader 5. Даже после того, как MetaTrader 5 вызовет событие OnCalculate, это НЕ ПРИВЕДЁТ к исправлению отображения. Это связано с тем, что при копировании буфера мы будем получать только часть ранее вычисленных значений. Это можно увидеть в строке 36.
Однако если вы загрузите все данные, рассчитанные MetaTrader 5, проблема, показанная на изображении 04, не возникнет. Поэтому следует проявлять осторожность при программировании подобной логики, особенно если вы собираетесь использовать эти расчёты и приложения в коммерческих целях или для автоматизации торговли на финансовом рынке.
Хорошо, вернёмся к нашему основному вопросу. Помните, я говорил, что существует, по сути, два способа инициализации буфера? Итак, второй показан ниже.
. . . 20. //+------------------------------------------------------------------+ 21. int OnInit(void) 22. { 23. SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA); 24. if ((Handle = iMA(NULL, 0, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE) 25. { 26. Print("Could not start the indicator..."); 27. return INIT_FAILED; 28. }; 29. 30. return INIT_SUCCEEDED; 31. }; 32. //+------------------------------------------------------------------+ 33. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 34. { 35. ArrayInitialize(Buff_iMA, EMPTY_VALUE); 36. CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA); 37. 38. return rates_total; 39. }; 40. //+------------------------------------------------------------------+ . . .
Фрагмент 05
Преимущество этого второго метода заключается в том, что индикатор не будет вести себя непредсказуемо. Результат будет очень похож на то, что мы видели в анимации 04, где индикатор будет сопровождать развитие всего процесса. Однако, возможно, в анимации 04 это было показано недостаточно ясно. Если это так, посмотрите следующую анимацию.

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

Изображение 05
Такая информация совершенно неинформативна для пользователя. Однако можно сказать, что менять это не имеет особого смысла. И во многих случаях это действительно так. Тем не менее, я хочу напомнить вам — на случай, если вы этого не заметили, — что один и тот же индикатор может одновременно отображать несколько линий или наборов данных.
В статье «От начального к среднему уровню: индикатор (III)» я показал, как это можно сделать. Однако там я забыл объяснить, как изменить информацию, выделенную на изображении 05. Это делается довольно просто. Нам нужно лишь добавить в код то, что показано в строке 14 приведённого ниже фрагмента.
. . . 12. #property indicator_style1 STYLE_SOLID 13. #property indicator_width1 1 14. #property indicator_label1 "EMA" 15. //+------------------------------------------------------------------+ 16. input uint def_nPeriods = 9; //Период: 17. input ENUM_MA_METHOD def_MA_Method = MODE_EMA; //Метод: . . .
Фрагмент 06
В результате мы получим то, что показано на следующем изображении.

Изображение 06
Хотя это работает относительно хорошо, делает настройки более понятными и интересными и облегчает пользователю настройку параметров, здесь есть небольшое неудобство. Информация, выделенная на изображении 06, статична. То есть, если пользователь изменит тип скользящей средней, информация на изображении 06 не будет отражать это изменение. И если вы задаёте несколько скользящих средних в рамках одного индикатора, это в конечном итоге полностью испортит пользовательский опыт.
Решить эту проблему довольно просто. Однако я не буду затрагивать эту тему сейчас, так как сначала хочу показать ещё несколько моментов, связанных с возможностью более динамично управлять различными элементами информации. Но об этом мы поговорим в следующей статье.
Заключительные замечания
В этой статье мы рассмотрели, как использовать технические индикаторы, встроенные в MetaTrader 5 и поддерживаемые этой платформой. Знание и понимание подобных индикаторов может значительно упростить, ускорить и сделать более эффективной реализацию решения, поскольку вам не придется беспокоиться о необходимых вычислениях. Платформа сама выполняет их за нас.
Однако умение использовать технические индикаторы — это лишь часть гораздо более широкой темы. В следующей статье мы рассмотрим, как гораздо эффективнее использовать такой подход, чтобы значительно упростить реализацию определённых торговых моделей. Итак, до скорой встречи.
| Файл MQ5 | Описание |
|---|---|
| Код 01 | Базовая демонстрация |
| Код 02 | Базовая демонстрация |
Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/17025
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Особенности написания Пользовательских Индикаторов
Нейросети в трейдинге: Управление риском через распределение результатов (Объект верхнего уровня)
От простых кнопок закрытия до панели управления рисками на основе правил в MQL5
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования