От начального к среднему уровню: Подокна (I)
Введение
В предыдущей статье От начального к среднему уровню: технические индикаторы (II) я показал, как легко добавить несколько скользящих средних к одному и тому же индикатору, почти не изменяя исходный код. Такой способ организации кода очень полезен, когда нужно быстро и без лишних сложностей изменить его поведение.
Однако, хотя этот метод полезен и интересен, он представляет собой лишь небольшую часть того, что мы можем делать с индикаторами, добавляемыми на график.
Бывают ситуации, когда нужен более продуманный подход и более эффективное использование возможностей MQL5. Когда и этого недостаточно, нам также нужно хорошо понимать, как работает MetaTrader 5, поскольку MQL5 в первую очередь служит для управления поведением платформы и получения нужных нам результатов. Многие считают, что MQL5 — это язык общего назначения, как C или C++, но это не так. Поэтому мы должны понимать, до каких пределов можно дойти с помощью MQL5, прежде чем прибегать к более радикальным решениям.
В некоторых из моих первых статей, опубликованных в этом сообществе, я представил один из возможных вариантов реализации в MetaTrader 5. Тогда я совершил ошибку, предположив, что участники сообщества уже имели достаточный опыт программирования. Поэтому я не объяснил должным образом, почему эта реализация работала и что нужно было учитывать перед её добавлением на график. Возможно, многим она показалась интересной, но они не смогли ею воспользоваться, потому что ещё не обладали необходимыми знаниями.
И, пожалуйста, не поймите меня неправильно, когда я говорю, что вы, вероятно, ещё не готовы понять, как работают эти приложения. Напротив: сохраняйте мотивацию и готовность учиться. Недостаток знаний лечится не гордостью, а смирением, позволяющим признать, что нам ещё многому предстоит научиться друг у друга.
Что ж, если вам не совсем ясно, о чём я говорил во введении, можете обратиться к статье «Несколько индикаторов на одном графике (Часть 03): Разработка определений для пользователей». А теперь пора отбросить всё, что отвлекает, и сосредоточиться на этой статье.
Использование подокон (I)
Во многих случаях нам нужно отобразить индикатор в подокне или, по крайней мере, так нам удобнее. Возможно, «подокно» — не самое удачное название, но, как однажды сказал мой друг:
Программистам плохо дается придумывание названий.
В любом случае, используется именно этот термин, и мы тоже будем его использовать. Вопреки распространённому мнению, создать индикатор для отображения в подокне обычно несложно, по крайней мере в наиболее типичных случаях. Однако некоторые ситуации могут вызывать путаницу, если не применять правильные понятия: у вас формируются определённые ожидания от работы системы, а потом вы обнаруживаете, что всё работает совершенно иначе. Такое часто случалось в моих первых статьях, которые в итоге порождали больше вопросов, чем давали ответов. Как я уже говорил, это была моя ошибка.
Я полагал, что статьи всегда рассчитаны на людей с определённым опытом, но это было не так. Поэтому я решил создать новый профиль, посвящённый исключительно объяснению мелких деталей, которые влияют на выбор при реализации практической задачи. Кроме того, я хотел показать новичкам и энтузиастам, как мыслить при написании кода. Так и появились эти статьи.
Мы уже рассмотрели темы от самых базовых, таких как синтаксис основных инструкций, до более сложных, например перегрузки операторов. Осталось объяснить некоторые детали базового программирования, но это не мешает нам делать интересные и увлекательные вещи. Я хочу дать вам время, чтобы освоить перегрузку операторов — это, без сомнения, самая сложная тема из всех, которые мы рассматривали до сих пор. Поэтому в нескольких следующих статьях мы будем рассматривать темы, которые легче понять, постепенно повышая уровень сложности.
Так все смогут читать их без переутомления, поскольку делать это в каком-то определённом порядке не обязательно. Считайте эти статьи дополнением к документации MQL5, к которой вам всегда следует обращаться, когда возникают вопросы.
Итак, о чём пойдёт речь в этой статье? Мы сделаем первые шаги в работе с подокном. Посмотрим, как наш код может использовать подокно, даже если мы специально не программировали это. Понимание этого крайне важно для того, чтобы разобраться в других, более сложных аспектах, которые мы рассмотрим далее.
Поскольку я не хочу писать код с нуля и тратить время на объяснение того, как он работает, мы возьмём код из предыдущей статьи, чтобы изучить эти первые шаги.
Ниже приведён исходный код.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property description "DEMO Indicator" 05. //+------------------------------------------------------------------+ 06. const struct stAverange 07. { 08. uint nPeriods; 09. ENUM_MA_METHOD Method; 10. color cor; 11. }Averange[] = 12. { 13. {9, MODE_EMA, clrRed}, 14. {20, MODE_SMA, clrGreen}, 15. {50, MODE_SMA, clrBlue}, 16. {200, MODE_SMA, clrBlack} 17. }; 18. //+----------------+ 19. #property indicator_chart_window 20. #property indicator_applied_price PRICE_CLOSE 21. #property indicator_buffers Averange.Size(); 22. #property indicator_plots Averange.Size(); 23. //+------------------------------------------------------------------+ 24. struct stInfos 25. { 26. double Buff_iMA[]; 27. int Handle; 28. }Infos[Averange.Size()]; 29. //+------------------------------------------------------------------+ 30. int OnInit(void) 31. { 32. for (uint c = 0; c < Averange.Size(); c++) 33. { 34. SetIndexBuffer(c, Infos[c].Buff_iMA, INDICATOR_DATA); 35. PlotIndexSetInteger(c, PLOT_DRAW_TYPE, DRAW_LINE); 36. PlotIndexSetInteger(c, PLOT_LINE_STYLE, STYLE_SOLID); 37. PlotIndexSetInteger(c, PLOT_LINE_WIDTH, 2); 38. PlotIndexSetInteger(c, PLOT_LINE_COLOR, Averange[c].cor); 39. PlotIndexSetString(c, PLOT_LABEL, StringFormat("%s of %d", (Averange[c].Method == MODE_EMA ? "Exponential" : "Arithmetica"), Averange[c].nPeriods)); 40. if ((Infos[c].Handle = iMA(NULL, NULL, Averange[c].nPeriods, 0, Averange[c].Method, _AppliedTo)) == INVALID_HANDLE) 41. { 42. Print("Could not start the indicator..."); 43. return INIT_FAILED; 44. }; 45. } 46. 47. return INIT_SUCCEEDED; 48. }; 49. //+------------------------------------------------------------------+ 50. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 51. { 52. for (uint c = 0; c < Averange.Size(); c++) 53. { 54. ArrayInitialize(Infos[c].Buff_iMA, EMPTY_VALUE); 55. CopyBuffer(Infos[c].Handle, 0, 0, Averange[c].nPeriods, Infos[c].Buff_iMA); 56. } 57. 58. return rates_total; 59. }; 60. //+------------------------------------------------------------------+ 61. void OnDeinit(const int reason) 62. { 63. for (uint c = 0; c < Averange.Size(); c++) 64. IndicatorRelease(Infos[c].Handle); 65. }; 66. //+------------------------------------------------------------------+
Код 01
В коде 01 есть интересное указание для компилятора: строка 19. В ней говорится, что индикатор будет использовать окно, к которому он применён. «Ах, но это же очевидно». Возможно, вы не обратили внимания на то, что это означает, дорогой читатель. Я НЕ ГОВОРИЛ, что индикатор будет использовать окно, в котором рисуются бары. Я сказал, что он будет использовать то окно, в которое вы его добавите. Многие упускают из виду это различие, совершают серьёзную ошибку и в итоге заявляют, что MetaTrader 5 — ужасная платформа.
Чтобы это было проще понять, мы изменим код 01, добавив приведённый ниже фрагмент.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property description "DEMO Indicator" 05. //+------------------------------------------------------------------+ 06. const struct stAverange 07. { 08. uint nPeriods; 09. ENUM_MA_METHOD Method; 10. color cor; 11. }Averange[] = 12. { 13. // {9, MODE_EMA, clrRed}, 14. {20, MODE_SMA, clrGreen}, 15. // {50, MODE_SMA, clrBlue}, 16. // {200, MODE_SMA, clrBlack} 17. }; 18. //+----------------+ . . .
Фрагмент 01
Теперь будет построена только одна из скользящих средних. Если вам непонятно, в чём заключается это изменение, обратитесь к предыдущим статьям, где я уже это объяснял. Здесь я не буду снова останавливаться на этих деталях. После добавления индикатора на график мы увидим результат, показанный на следующем изображении.

Изображение 01
Давайте продлим линию этой скользящей средней, чтобы она охватывала больше баров. Достаточно изменить код, как показано в следующем фрагменте.
. . . 49. //+------------------------------------------------------------------+ 50. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 51. { 52. for (uint c = 0; c < Averange.Size(); c++) 53. { 54. ArrayInitialize(Infos[c].Buff_iMA, EMPTY_VALUE); 55. CopyBuffer(Infos[c].Handle, 0, 0, Bars(NULL, NULL), Infos[c].Buff_iMA); 56. } 57. 58. return rates_total; 59. }; 60. //+------------------------------------------------------------------+ . . .
Фрагмент 02
Результат показан ниже.

Изображение 02
Всё это уже объяснялось ранее. Мы подошли к моменту, с которого я хотел начать рассматривать другой аспект.
Прежде чем писать код, использующий подокно, нужно понять, как MetaTrader 5 работает с такими подокнами. И да, хотя вам это и может показаться простым, дорогой читатель, многие программисты и трейдеры НЕ ЗНАЮТ, КАК METATRADER 5 РАБОТАЕТ С ПОДОКНАМИ. Тем не менее некоторые с полной уверенностью заявляют, что обладают большим опытом работы с MetaTrader 5. Ну, это, как минимум, трагично.
Среди предустановленных индикаторов MetaTrader 5 есть несколько таких, которые используют подокно. Для наших целей мы выберем классический вариант — индикатор объёма. После добавления его на график показанный на изображении 02 вид изменится и станет таким, как на следующем изображении.

Изображение 03
Окно, которое вы видите в нижней части графика, — это подокно. А теперь внимание. Подокно некоторым образом связано с главным окном, но имеет собственные механизмы и настройки. Мы даже можем изменить его так, чтобы оно работало как то, что мы считали бы главным окном. "Подождите, теперь вы меня запутали. Вы хотите сказать, что окно в нижней части графика можно использовать так, как если бы оно было главным окном?". Да, дорогой читатель, именно так. Но если вы это сделаете, вам придётся учитывать последствия.
Поскольку это лишь первая статья, в которой мы затрагиваем эту тему, я пока не буду вдаваться в подробности. Вы поймёте это лучше по мере публикации новых статей.
Вернёмся к нашему главному вопросу. Помните строку 19 нашего кода? Итак, теперь мы хотим сделать кое-что, что, насколько мне известно, довольно распространено. Многие трейдеры не следят напрямую за объёмом, отображаемым в подокне: они добавляют скользящую среднюю и анализируют уже её. Но постойте, как построить скользящую среднюю по этому объёму?
Именно это и есть один из шагов, который многие не умеют выполнять. И когда они пытаются это сделать, то обычно ошибаются, что существенно вредит анализу, который они хотели провести.
Чтобы увидеть проблему, посмотрите следующую анимацию.

Анимация 01
В некотором смысле анимация 01 показывает правильный способ добавить индикатор в подокно. Однако обратите внимание на кривую, которую рисует скользящая средняя. На следующем изображении это видно более ясно.

Изображение 04
Здесь видно, что кривая скользящей средней НЕ ОТРАЖАЕТ КРИВУЮ ОБЪЁМА. Скользящая средняя, отображаемая в подокне, повторяет динамику котировок в главном окне. Это не то, чего хотел трейдер. Итак, опираясь на свой опыт работы с MetaTrader 5, он делает то, что показано в следующей анимации.

Анимация 02
Но что же произошло? Где скользящая средняя объёма? Что-то произошло. Чтобы это выяснить, трейдер открывает терминал и видит следующее сообщение.

Изображение 05
"Ну, вот теперь у нас действительно проблема. А, понятно: виновата платформа". Подождите минутку, дорогой читатель. Виновата не платформа, а вы — или, точнее, программист, который написал код индикатора. "Постойте, это мы его запрограммировали? Вы хотите сказать, что мы некомпетентны?". Дело не в этом, дорогой читатель. Как я уже говорил в начале статьи, нужно со смирением признать, что мы не знаем всего и что всегда можем чему-то научиться друг у друга.
Проблема действительно заключается в коде индикатора. Помните, как в предыдущих статьях я объяснял, как и почему работают технические индикаторы? Его расчёты работают хорошо, как показывают изображения: кривая скользящей средней правильно отображается в главном окне графика. Однако ОНИ НЕ ПОДХОДЯТ для расчёта на основе данных других индикаторов, значения которых MetaTrader 5 не знает. Если мы изменим источник данных и будем использовать другой индикатор, в данном случае индикатор объёма, то применяемый нами технический индикатор iMA в таком случае просто не вычисляется. MetaTrader 5 не знает, какие значения содержит индикатор объёма; поэтому код даёт сбой, и получается результат, показанный на изображении 05. Так что признайте: мы не всегда знаем, что делаем. Признать это со смирением обычно помогает нам правильно понять ситуацию.
"М-м-м, хорошо. Но тогда я спрошу вас: как мы можем это решить? Должно же быть какое-то решение, не так ли?". Да, есть, дорогой читатель. Вот здесь тема становится более интересной, хотя и немного более сложной. Нам придётся самостоятельно реализовать расчёт скользящей средней, не полагаясь на помощь MetaTrader 5; то есть мы не сможем воспользоваться уже имеющимися техническими индикаторами. В этом и заключается сложность: при программировании таких вычислений многие допускают ошибки — либо в самом расчёте, либо при написании кода, который потребляет гораздо больше ресурсов, чем необходимо.
Поэтому делайте то, что мы здесь будем делать, только в крайнем случае или если вы абсолютно уверены в том, что делаете. Любая ошибка, которую вы допустите, будет вашей ответственностью. Теперь, когда это прояснили, мы можем приступить к написанию кода.
Для начала мы немного упростим код 01. Он будет выглядеть так, как показано ниже.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property description "DEMO Indicator" 05. //+------------------------------------------------------------------+ 06. const struct stAverange 07. { 08. int nPeriods; 09. ENUM_MA_METHOD Method; 10. color cor; 11. }Averange[] = 12. { 13. {9, MODE_EMA, clrRed}, 14. {20, MODE_SMA, clrGreen}, 15. }; 16. //+----------------+ 17. #property indicator_chart_window 18. #property indicator_applied_price PRICE_CLOSE 19. #property indicator_buffers Averange.Size(); 20. #property indicator_plots Averange.Size(); 21. //+------------------------------------------------------------------+ 22. struct stInfos 23. { 24. double Buff_iMA[]; 25. }Infos[Averange.Size()]; 26. //+------------------------------------------------------------------+ 27. int OnInit(void) 28. { 29. for (uint c = 0; c < Averange.Size(); c++) 30. { 31. SetIndexBuffer(c, Infos[c].Buff_iMA, INDICATOR_DATA); 32. PlotIndexSetInteger(c, PLOT_DRAW_TYPE, DRAW_LINE); 33. PlotIndexSetInteger(c, PLOT_LINE_STYLE, STYLE_SOLID); 34. PlotIndexSetInteger(c, PLOT_LINE_WIDTH, 2); 35. PlotIndexSetInteger(c, PLOT_LINE_COLOR, Averange[c].cor); 36. PlotIndexSetString(c, PLOT_LABEL, StringFormat("%s of %d", (Averange[c].Method == MODE_EMA ? "Exponential" : "Arithmetica"), Averange[c].nPeriods)); 37. } 38. 39. return INIT_SUCCEEDED; 40. }; 41. //+------------------------------------------------------------------+ 42. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 43. { 44. for (uint c = 0; c < Averange.Size(); c++) 45. { 46. } 47. 48. return rates_total; 49. }; 50. //+------------------------------------------------------------------+
Код 02
Это код, от которого мы будем отталкиваться. Я удалил несколько частей, прежде всего ту, которая давала нам доступ к техническому индикатору iMA. Теперь мы добавим несколько элементов, которые помогут нам в вычислениях. Для этого мы изменим код 02, как показано в следующем фрагменте.
. . . 21. //+------------------------------------------------------------------+ 22. struct stInfos 23. { 24. double Buff_iMA[], 25. f_Expo; 26. }Infos[Averange.Size()]; 27. //+------------------------------------------------------------------+ 28. int OnInit(void) 29. { 30. for (uint c = 0; c < Averange.Size(); c++) 31. { 32. SetIndexBuffer(c, Infos[c].Buff_iMA, INDICATOR_DATA); 33. Infos[c].f_Expo = (double) (2.0 / (1.0 + Averange[c].nPeriods)); 34. PlotIndexSetInteger(c, PLOT_DRAW_TYPE, DRAW_LINE); 35. PlotIndexSetInteger(c, PLOT_LINE_STYLE, STYLE_SOLID); 36. PlotIndexSetInteger(c, PLOT_LINE_WIDTH, 2); 37. PlotIndexSetInteger(c, PLOT_LINE_COLOR, Averange[c].cor); 38. PlotIndexSetString(c, PLOT_LABEL, StringFormat("%s of %d", (Averange[c].Method == MODE_EMA ? "Exponential" : "Arithmetica"), Averange[c].nPeriods)); 39. } 40. 41. return INIT_SUCCEEDED; 42. }; 43. //+------------------------------------------------------------------+ . . .
Фрагмент 03
Теперь мы можем сосредоточиться на вычислениях, так как у нас уже есть необходимая основа. Мы реализуем это, как показано в следующем фрагменте.
. . . 43. //+------------------------------------------------------------------+ 44. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 45. { 46. int c0 = 0; 47. 48. for (uint c = 0; c < Averange.Size(); c++) 49. { 50. if (prev_calculated == 0) 51. { 52. double loc = 0; 53. for (int c1 = 0; c1 < Averange[c].nPeriods; c1++) loc += price[Averange[c].nPeriods - c1]; 54. Infos[c].Buff_iMA[Averange[c].nPeriods] = loc / Averange[c].nPeriods; 55. } 56. switch (Averange[c].Method) 57. { 58. case MODE_EMA: 59. for (c0 = (prev_calculated > 0 ? prev_calculated - 1 : 0); c0 < rates_total; c0++) 60. Infos[c].Buff_iMA[c0] = (c0 > 0 ? (((price[c0] - Infos[c].Buff_iMA[c0 - 1])) * Infos[c].f_Expo) + Infos[c].Buff_iMA[c0 - 1] : Infos[c].Buff_iMA[c0]); 61. break; 62. case MODE_SMA: 63. for (c0 = (prev_calculated > 0 ? prev_calculated - 1 : Averange[c].nPeriods + 1); c0 < rates_total; c0++) 64. Infos[c].Buff_iMA[c0] = ((Infos[c].Buff_iMA[c0 - 1] * Averange[c].nPeriods) - price[c0 - Averange[c].nPeriods] + price[c0]) / Averange[c].nPeriods; 65. break; 66. } 67. } 68. 69. return rates_total; 70. }; 71. //+------------------------------------------------------------------+
Фрагмент 04
Я не буду вдаваться в подробности этих расчётов, чтобы не затягивать изложение. На этом этапе я уверен, что вы уже понимаете, что они делают. Помните, что этот пример носит учебный характер и не является самым эффективным способом расчёта: сам MQL5 предлагает гораздо более быстрые варианты.
После компиляции кода 02 с изменениями из обоих фрагментов мы сможем увидеть, как он работает. Сначала добавим индикатор непосредственно в главное окно, как показано в следующей анимации.

Анимация 03
Обратите внимание, что всё работает. Чтобы проверить, правильно ли рассчитываются скользящие средние, воспользуйтесь тем же принципом, который мы показывали в предыдущих статьях. Всегда полезно убедиться, что в расчётах нет ошибок. Затем мы сможем перейти к следующему шагу: добавить индикатор в подокно, где отображается объём. Мы сделаем это так же, как и раньше, как показано в следующей анимации.

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

Изображение 06
Итак, следующий шаг — внести изменение, показанное в следующей анимации.

Анимация 05
Наконец-то всё получилось! Возможно, анимация слишком быстрая, чтобы это заметить, поэтому давайте спокойно рассмотрим последние кадры анимации 05, показанные на следующем изображении.

Изображение 07
Теперь у нас действительно есть индикатор, который работает правильно и подходит для гораздо большего числа ситуаций, в том числе для применения в подокнах. Но подождите, прежде чем закончить статью, не могли бы вы объяснить мне кое-что из того, что мы рассмотрели? Конечно, дорогой читатель. Скажите, какие у вас есть сомнения.
У меня первый вопрос такой: я заметил, что и код 01, и код 02 используют свойство indicator_chart_window. Насколько я понимаю из документации, это свойство указывает, что индикатор будет отображаться в главном окне, а не в каком-либо другом окне. Однако здесь вы сказали, что некоторые индикаторы создают новое окно, или подокно. В анимациях индикатор объёма создаёт подокно, и в нём появляется наш индикатор. Почему? Разве он не должен оставаться привязанным к главному окну, где отображаются бары? Отличный вопрос, дорогой читатель. Прежде чем перейти к следующему вопросу, давайте разберёмся, почему наш индикатор отображается в подокне, несмотря на использование свойства indicator_chart_window. Именно этот момент часто сбивает с толку многих новичков.
Чтобы ответить на ваш вопрос, не слишком усложняя объяснение, давайте ещё раз рассмотрим анимации, прежде всего 02 и 04, в которых мы добавляли индикатор на график. Обратите внимание, что в обоих случаях мы перетаскиваем индикатор и отпускаем его в определённом месте: внутри подокна, созданного индикатором объёма.
Обратите особое внимание на эту деталь, потому что именно она играет решающую роль. MetaTrader 5 определяет, где мы отпустили индикатор, и при загрузке индикатора, использующего свойство indicator_chart_window, рассматривает это подокно как главное окно для данного индикатора. Именно здесь и возникает большая часть путаницы: MetaTrader 5 НЕ БУДЕТ АВТОМАТИЧЕСКИ МЕНЯТЬ ИСТОЧНИК ДАННЫХ ИНДИКАТОРА, чтобы он использовал значения этого подокна. Вы, как трейдер, должны вручную изменить источник данных, который использует индикатор, как мы видели в анимациях.
Многие пользователи переходят с других платформ, где эта настройка выполняется автоматически, например с PROFIT, которая широко используется трейдерами в Бразилии. Увидев, что скользящая средняя ведёт себя не так, как они ожидали, они в итоге остаются недовольны MetaTrader 5.
"Пожалуй, я всё понял. Но у меня есть ещё один вопрос. В анимациях 02 и 05, когда вы меняете параметр расчёта, вы выбираете «FIRST INDICATOR'S DATA», хотя можно было бы выбрать и «PREVIOUS INDICATOR'S DATA». Почему вы предпочитаете один вариант другому?". Ого, у нас тут очень внимательный читатель. Мне нравится этот вопрос. Пока ещё рано объяснять это подробно, но я постараюсь показать вам причину, не вдаваясь во все детали. Этим мы займёмся позже.
Чтобы вы поняли, почему я выбрал один параметр, а не другой в этих анимациях, мы изменим код 02, как показано ниже. Это простое изменение, но оно поможет вам понять суть.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property description "DEMO Indicator" 05. //+------------------------------------------------------------------+ 06. const struct stAverange 07. { 08. int nPeriods; 09. ENUM_MA_METHOD Method; 10. color cor; 11. }Averange[] = 12. { 13. {3, MODE_SMA, clrBlack} 14. }; 15. //+----------------+ . . .
Фрагмент 05
Обратите внимание, что теперь код вычисляет среднее арифметическое за очень короткий период. Так мы убедимся, что эффект будет заметен. Возможно, это не лучшее объяснение, но, по крайней мере, оно поможет частично удовлетворить ваше любопытство.
После создания и компиляции мы можем добавить индикатор на график. Результат показан на следующем изображении.

Изображение 08
Теперь мы настроим его так, чтобы он использовал параметр, показанный на следующем изображении.

Изображение 09
После этого мы получим следующий результат.

Изображение 10
Обратите внимание, что я изменил цвет и толщину линии, чтобы было проще понять, что произойдёт дальше. Теперь мы добавим ещё один экземпляр того же индикатора. Результат показан ниже.

Изображение 11
Обратите внимание на эту настройку; я объясню её подробнее чуть позже. Поскольку на экране отображаются две средние, мы настроим чёрную так, чтобы она использовала параметр, показанный на следующем изображении.

Изображение 12
На этот раз мы выберем другой параметр. Тем не менее, результат будет таким, как показано ниже.

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