От начального до среднего уровня: Индикатор (IV)
Введение
В предыдущей статье "От начального до среднего уровня: Индикатор (III)", мы рассмотрели, как создать любой тип индикатора простым и практичным способом, используя директивы компиляции. Однако мы не всегда можем или должны поступать именно так. Такой подход называется статической реализацией, поскольку, определив тип индикатора, мы не можем (вернее, не позволяем) пользователю изменить тип выполняемой отрисовки.
Однако количество индикаторов может быть гораздо больше, чем было показано до настоящего момента. Правда, для широкого спектра деятельности такого типа реализации уже будет более чем достаточно. Но бывают ситуации, когда для торговли или анализа рынка нам могут понадобиться несколько иные индикаторы.
В этой статье мы узнаем, как создать несколько различных индикаторов. Данные индикаторы очень полезны для общения с другими трейдерами и для автоматизированного анализа определенных типов движения, если это можно так назвать.
Итак, начнем с очень простого и, на мой взгляд, довольно интересного. Мы можем создать множество других индикаторов, используя очень простую и понятную концепцию.
Индикатор внутреннего бара
Существует тип индикатора или, скорее, операционная методология, которая использует так называемый внутренний бар. Внутренний бар - это буквально бар или свеча, которые находятся внутри того, что расположено непосредственно до них. Однако, в зависимости от трейдера и символа, любой бар, находящийся внутри другого бара, не обязательно непосредственно предшествующего ему, может считаться внутренним баром, если движение не нарушило этот же бар и может находиться на некотором расстоянии. Но последний способ рассматривать что-то как внутренний бар не является принципом, принятым большинством трейдеров.
В любом случае, данная оперативная методология существует и в разное время проявляет себя очень убедительно. Хотя постоянно анализировать график, чтобы понять, видим ли мы внутренний бар или нет, - это, мягко говоря, довольно сложно для многих людей, особенно для новичков. Поэтому мы можем использовать индикатор, который следует за графиком и показывает нам, есть ли такая формация, когда график открыт и активен.
Важный момент: внутренний бар НЕ обязательно является Доджи.
«Хорошо, но почему вы решили показать, как создать этот индикатор?» Причина очень проста, друг мой. Многие начинающие трейдеры пытаются создать индикаторы, чтобы добавлять цветовые паттерны к свечам или барам, как их часто называют. И эти начинающие программисты в конце концов сдаются из-за того, как должен быть объявлен индикатор. Дело не в том, что создание цветового паттерна в свечах является сложной задачей. Проблема заключается в другом: Создание самого индикатора - довольно простая задача, как можно себе представить.
Однако, как и в случае с другими индикаторами, которые были показаны в предыдущих статьях, при объявлении буферов следует соблюдать осторожность. Если вы уже пытались создать цветовой паттерн на свечах, то хорошо знаете, что это может оказаться непростой задачей для любого новичка. Поэтому, если мы сделаем это не в правильном порядке или введем буферные индексы не в той последовательности, то MetaTrader 5 изобразит на графике нечто отличное от того, что мы ожидали увидеть. Нельзя винить ни MetaTrader 5, ни программиста, потому что, в зависимости от того, что мы хотим реализовать, для одних это будет ошибкой, а для других окажется именно тем, что нужно.
Итак, мы начнем с объявления самого индикатора, ещё до создания индикатора внутреннего бара. Как правило, можно объявить всё по-разному, как показано в приведенном ниже коде:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_COLOR_CANDLES 05. #property indicator_color1 clrRed, clrRoyalBlue, clrGreen 06. //+----------------+ 07. #property indicator_buffers 5 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_Buff_High[], 11. gl_Buff_Open[], 12. gl_Buff_Close[], 13. gl_Buff_Low[], 14. gl_Buff_Color[]; 15. //+------------------------------------------------------------------+ 16. int OnInit() 17. { 18. SetIndexBuffer(0, gl_Buff_High, INDICATOR_DATA); 19. SetIndexBuffer(1, gl_Buff_Open, INDICATOR_DATA); 20. SetIndexBuffer(2, gl_Buff_Close, INDICATOR_DATA); 21. SetIndexBuffer(3, gl_Buff_Low, INDICATOR_DATA); 22. SetIndexBuffer(4, gl_Buff_Color, INDICATOR_COLOR_INDEX); 23. 24. return INIT_SUCCEEDED; 25. }; 26. //+------------------------------------------------------------------+ 27. 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[]) 28. { 29. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 30. { 31. gl_Buff_High[c] = High[c]; 32. gl_Buff_Open[c] = Open[c]; 33. gl_Buff_Close[c] = Close[c]; 34. gl_Buff_Low[c] = Low[c]; 35. 36. gl_Buff_Color[c] = (Open[c] > Close[c] ? 0 : 2); 37. } 38. 39. return rates_total; 40. }; 41. //+------------------------------------------------------------------+
Код 01
А теперь я спрашиваю вас, дорогие читатели: правильно или нет то, что мы видим в коде 01? Правильный ответ на этот вопрос: всё зависит от цели, которую мы преследуем. В любом случае, такая реализация кода 01 не является совсем уж неправильной, поскольку код будет скомпилирован и пригодится для использования. Но в зависимости от поставленной цели этот код может быть неправильным. Поэтому обратите внимание на то, что произойдет, когда вы будете использовать данный код на любом графике. Это можно увидеть на анимации далее:

Анимация 01
Другими словами, результат оказался не совсем таким, как ожидалось. Почему? «Я не понял. Судя по всему, код верен. Я не сделал ничего плохого при объявлении буферов. Однако результат оказался ожидаемым: бары изменились не только по цвету, но и по формату. Я не могу понять, что не так, есть ли какой-то трюк, чтобы заставить всё работать и получить желаемый результат?» В данном случае - да, дорогие читатели.
Хотя код правильный, поскольку он изменил цвет баров, как и ожидалось, то же самое нельзя сказать об изменении форматирования. Если целью было изменить цвета и в то же время модифицировать бары, то да. Однако, это не то, что мы задумали. Причина именно в том, что порядок объявления буферов неправильный. Таким образом, когда MetaTrader 5 использует буферы, он будет делать это в определенном порядке. При неправильном порядке формат баров был изменен. Зная это, нам остается только изменить данный порядок на подходящий. Это простое изменение можно увидеть в приведенном ниже коде:
. . . 18. SetIndexBuffer(1, gl_Buff_High, INDICATOR_DATA); 19. SetIndexBuffer(0, gl_Buff_Open, INDICATOR_DATA); 20. SetIndexBuffer(3, gl_Buff_Close, INDICATOR_DATA); 21. SetIndexBuffer(2, gl_Buff_Low, INDICATOR_DATA); . . .
Код 02
Прошу заметить, что во фрагменте кода 02 единственное, что изменилось, - это значение индекса каждого буфера. Используя данную последовательность буферов (Open, High, Low и Close), результат, который сгенерирует код 01, можно увидеть чуть ниже:

Анимация 02
Вы заметили, как MetaTrader 5 теперь понимает, как должен быть нарисован каждый бар или свеча? Это очень простая задача для тех, кто уже знает, как её решить. Однако для тех, кто не понимает, это, безусловно, самое сложное на свете. В любом случае, теперь вы знаете, как это сделать, и можете приступать к построению цветовых паттернов для создания индикаторов и моделирования нужной торговой системы. Чтобы продемонстрировать, как это можно сделать, давайте рассмотрим, решение задачи и укажем внутренний бар прямо на графике.
Чтобы решить этот вопрос, посмотрите на строку 36, где описано, как мы вычисляем индекс цвета. Это будет индекс ноль для бара Sell или индекс два для бара Buy. Но какая нам польза от данного индекса? Мы оставляем этот индекс для того, что будет внутренним баром.
Теперь наступает ключевой момент. Цикл строки 29 начинается со старой точки, которая может быть (или нет) первым баром на графике, и переходит к поиску самого последнего бара, присутствующего на графике. Это важно знать и понимать, потому что внутренний бар может быть обозначен только при наличии предыдущего бара с определенными характеристиками. Иначе текущий бар не сможет рассматриваться и отображаться на графике как внутренний бар.
Итак, всё понятно, осталось только реализовать критерии проверки. Для этого мы должны модифицировать приведенный выше код, чтобы он мог задавать цвет баров и свечей и, кроме того, проверять наличие или отсутствие внутреннего бара. Это увеличение показано во фрагменте кода 03:
. . . 36. gl_Buff_Color[c] = (Open[c] > Close[c] ? 0 : 2); 37. if ((c - 1) > 0) 38. gl_Buff_Color[c] = ((High[c - 1] > High[c]) && (Low[c - 1] < Low[c]) ? 1 : gl_Buff_Color[c]); 39. } 40. 41. return rates_total; 42. }; 43. //+------------------------------------------------------------------+
Код 03
Теперь при каждом событии Calculate, которое получает наш индикатор, мы будем проверять, есть ли на графике внутренний бар. Но подождите, почему мы должны пытаться сделать это на каждом шагу? Причина проста: во время торговой фазы на графике может появиться внутренний бар. Однако нередко случается, что он может стать неправильно настроенным. Это связано с тем, что мы можем рассматривать наличие или отсутствие внутреннего бара только после закрытия бара или свечи. До этого момента преждевременно говорить о том, что на графике есть внутренний бар.
Однако, поскольку строка 38 периодически проверяет, можно ли применить условие внутреннего бара или нет, получается так, что в итоге, если внутренний бар становится ненастроенным, тест проваливается. Поэтому, поскольку мы уже обновили цвет в строке 36, вышеупомянутая индикация больше не отображается на графике.
Хотя известно, что это работает, в идеале мы должны увидеть, как это происходит на практике, чтобы понять, почему мы выполнили реализацию именно таким образом. Однако на анимации ниже мы можем увидеть, как происходит начальный процесс. Но показать второй шаг - деконфигурацию того, что должно быть внутренним баром, - не так-то просто, поскольку для этого требуется очень конкретный момент, а чтобы зафиксировать точную точку, потребуется много времени.

Анимация 03
Отлично, здесь мы видим, как должен выглядеть внутренний бар. Однако, как уже говорилось выше, есть трейдеры, которые рассматривают несколько баров и считают все эти новые бары внутренними, пока новые бары находятся внутри предыдущего. И тут возникает вопрос: как мы могли бы реализовать такой же вид индикатора, просто модифицировав предыдущий?
На этот вопрос могут быть разные ответы, точнее, разные способы реализации задействованного механизма. Настоящая проблема заключается не в точной реализации кода, а в том, чтобы придумать, как сохранить значение в течение длительного периода времени. Ниже приводится возможное предложение. Конечно, в зависимости от случая, можно использовать другое, которое покажется вам более интересным или подходящим.
Поскольку мы хотим максимально упростить процесс, мы внесем только одно изменение в реализацию обработчика события OnCalculate. Таким образом, исходный код, создавший анимацию 03, будет изменен следующим образом:
. . . 26. //+------------------------------------------------------------------+ 27. 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[]) 28. { 29. static double high = DBL_MIN, 30. low = DBL_MAX; 31. 32. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 33. { 34. gl_Buff_High[c] = High[c]; 35. gl_Buff_Open[c] = Open[c]; 36. gl_Buff_Close[c] = Close[c]; 37. gl_Buff_Low[c] = Low[c]; 38. 39. gl_Buff_Color[c] = (Open[c] > Close[c] ? 0 : 2); 40. if ((c - 1) > 0) 41. { 42. high = (High[c - 1] > high ? High[c - 1] : high); 43. low = (Low[c - 1] < low ? Low[c - 1] : low); 44. gl_Buff_Color[c] = ((high > High[c]) && (low < Low[c]) ? 1 : gl_Buff_Color[c]); 45. if (gl_Buff_Color[c] != 1) 46. { 47. high = DBL_MIN; 48. low = DBL_MAX; 49. } 50. } 51. } 52. 53. return rates_total; 54. }; 55. //+------------------------------------------------------------------+
Код 04
А теперь внимание. Если фрагмент, который показан в коде 04, поместить в код, сгенерировавший анимацию 03, результат будет отличаться от предыдущей анимации. Чтобы убедиться в этом, давайте посмотрим внимательно и сравним анимацию ниже с анимацией выше.

Анимация 04
В анимации 04 мы делаем именно то, что многие трейдеры считают внутренним баром. То есть до тех пор, пока нет «нарушения» максимума или минимума предыдущего бара или свечи, мы будем считать анализируемый бар внутренним. Я знаю, что это кажется очень запутанным, особенно если вы не привыкли торговать или наблюдать за внутренними барами. Но фрагмент кода 04 способен распознать паттерн, даже если появляется несколько баров и все они находятся внутри гораздо более старого бара.
Но как же тогда работает данный фрагмент кода и как ему удается обнаружить внутренний бар так, как показано в анимации 04? Чтобы понять это, сначала нужно разобраться в том, как работает более ранний и простой индикатор. Только тогда вы сможете понять данный вопрос. Кроме того, вы должны понимать, как работают статические переменные. Поскольку этому вопросу уже посвящена отдельная статья, я предположу, что вы уже разбираетесь в статических переменных.
Если вы ещё не читали эту статью, вот она: "От начального к среднему уровню: Переменные (II)". Теперь, глядя на код 04, становится ясно, что необходимое изменение было внесено именно в тест внутреннего бара. Тест всё ещё проводится там. Однако он изменил свое положение, потому что теперь, прежде чем это произойдет, мы проведем ещё два теста. Первый находится в строке 42, где мы проверяем, было ли нарушение максимума. В строке 43 мы выполняем аналогичную проверку, но в этом случае мы проверяем нарушение минимума. Таким образом, мы учитываем границу, при которой внутренний бар может существовать между несколькими разными барами, а не только непосредственно предшествующим ему. Только зная эти границы, мы можем проверять, есть ли бар продолжения в анализируемом баре. Это делается в строке 44.
Важным моментом является ещё и строка 45. Здесь мы проверяем, показал ли тест в строке 44 наличие внутреннего бара. Если внутреннего бара нет, нужно разрушить наложенные границы, чтобы поискать наличие нового построения внутреннего бара. Если бы эта проверка строки 45 не проводилась, то постоянно выдавались бы ложные показания.
Для того чтобы вы поняли, что такое индикатор внутреннего бара, который мы здесь показали, давайте посмотрим на анимацию ниже.

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

Изображение 01
Прошу заметить, что символ торгуется обратно в бар или свечу, которая сгенерировала три предыдущих индикации внутреннего бара. Однако, согласно критериям, реализованным в индикаторе, последний бар уже нельзя было считать внутренним. Короче говоря, индикатор работает, но нам необходимо определить и четко сформулировать принимаемые критерии, чтобы предоставить нам соответствующую и желаемую информацию.
Очень хорошо, уже было доступно объяснено, как применять цветовые индикаторы на свечах. Теперь мы можем заняться другими вопросами, которые могут быть связаны (или нет) с индикаторами. Однако из-за природы самой концепции того, что является индикатором, я считаю уместным показать и другие вещи в рамках этого же типа сценария.
Что смотреть и чего не смотреть
Нередко мы используем разные профили для одной и той же торговой методики на рынке. Немало трейдеров предпочитает, чтобы на графике постоянно отображалась различная информация. Другие предпочитают иметь минимум информации. Решение о том, что именно отображать, зависит от каждого трейдера или профиля работы. Однако для нас, как программистов, это совершенно неважно. Нам неважно, как мы предпочитаем настраивать свой график. Всё, о чем мы заботимся, - это предоставить простые и удобные средства, чтобы каждый мог настроить график по своему вкусу.
MetaTrader 5 позволяет нам настроить многое из этого без необходимости использования внешнего приложения. Но всё же есть элементы, которые нельзя удалить или изменить с помощью опций, предлагаемых MetaTrader 5, и здесь на помощь приходит программирование. Вы, будучи программистами, должны понимать, что НЕТ НИКАКИХ ОГРАНИЧЕНИЙ на то, что мы можем сделать и чего нельзя. То, что на самом деле существует - это большая или меньшая техническая мощность каждого программиста. Кто-то обойдется более простым способом, а кому-то понадобятся средства посложнее.
В любом случае, цель состоит в том, чтобы разработать приложение, которое сможет преобразовать график в то, что нам нужно, даже если для других трейдеров это будет полной неразберихой. Но если вы понимаете созданное и зарабатываете на торговле, это действительно важно.
Итак, с помощью MQL5 мы можем определять и управлять различными элементами графика. Для начала мы внесем несколько простых изменений, которые могут быть интересны в определенное время. Цель - показать, что при использовании MQL5 мы имеем полную свободу и контроль над любым элементом графика. Например, знали ли вы, что мы можем удалить из графика ту область, где наблюдаются котировки и часовой пояс? Если мы попытаемся сделать это прямо из MetaTrader 5, у нас ничего не получится. Однако одним из способов сделать это является код. Кстати, код, который нам нужно реализовать, довольно прост. Так что давайте начнем отсюда. Начальный код показан ниже:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. int OnInit() 05. { 06. ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false); 07. ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false); 08. 09. return INIT_SUCCEEDED; 10. }; 11. //+------------------------------------------------------------------+ 12. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 13. { 14. return rates_total; 15. }; 16. //+------------------------------------------------------------------+
Код 05
Обратите внимание на уровень простоты кода 05. Нам не нужно ничего объяснять, можно четко понять, что мы делаем. На самом деле, если запустить этот код на графике, мы получим такой результат:

Анимация 06
Правда, мы поступаем очень грубо, поскольку, удалив шкалу цен и времени без разрешения пользователя, мы не возвращаем их на график, даже когда индикатор удален. Хотя многим это может показаться уместным, другие считают такие действия неуважительным отношением к приложению, поскольку для восстановления временной и ценовой шкалы требуется закрыть график и открыть его заново, чего большинство не захочет делать.
Но возникает вопрос: как вернуть график в исходное состояние? И если можно, то когда лучше всего это сделать? Что ж, на самом деле есть способ сделать это, перехватив событие Deinit. Однако мы должны понимать следующее: нет лучшего времени для этого, есть только нужное время. Я говорю это, потому что может случиться так, что наше приложение сделает то, что заставит MetaTrader 5 удалить его с графика. Если это произойдет, событие Deinit не будет выполнено, поскольку удаление будет принудительным. Таким образом, все изменения, внесенные нашим приложением, останутся на графике, и нам придется закрыть его и открыть снова, чтобы вернуть всё на свои места.
Поэтому такие изменения всегда следует вносить осторожно. И, когда это будет возможно, дайте пользователю возможность выбрать, что удалить из графика, особенно если ваше приложение нацелено на облегчение работы.
Хорошо, давайте создадим более вежливый способ реализовать то, что было показано на анимации 06. Для этого мы изменим код 05 таким образом:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. input bool user01 = true; //Show time scale 05. input bool user02 = true; //Show price scale 06. //+----------------+ 07. struct st_Mem 08. { 09. long View_DateScale, 10. View_PriceScale; 11. }gl_StyleGraphic; 12. //+------------------------------------------------------------------+ 13. int OnInit() 14. { 15. gl_StyleGraphic.View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE); 16. gl_StyleGraphic.View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE); 17. 18. ChartSetInteger(0, CHART_SHOW_DATE_SCALE, user01); 19. ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, user02); 20. 21. return INIT_SUCCEEDED; 22. }; 23. //+------------------------------------------------------------------+ 24. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 25. { 26. return rates_total; 27. }; 28. //+------------------------------------------------------------------+ 29. void OnDeinit(const int reason) 30. { 31. ChartSetInteger(0, CHART_SHOW_DATE_SCALE, gl_StyleGraphic.View_DateScale); 32. ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, gl_StyleGraphic.View_PriceScale); 33. }; 34. //+------------------------------------------------------------------+
Код 06
Теперь, обратите внимание, что мы стали гораздо вежливее. Это происходит так, потому что в строках 04 и 05 мы даем пользователю разрешение на удаление как ценовой, так и временной шкалы. В строке 07 мы используем структуру для хранения исходных значений, чтобы вернуть график в состояние, в котором он находился до применения индикатора, независимо от изменений, сделанных пользователем.
Здесь действуем также как и в коде 05, который был прост и понятен. Однако я хотел бы обратить ваше внимание на другое: обработчик события Deinit. Он находится на строке 29. Проблема заключается в том, что даже после удаления индикатора с графика, MetaTrader 5 требуется некоторое время для обновления графика, на котором находился бы индикатор, иногда секунды, иногда чуть больше. В течение этого короткого промежутка времени часть информации может отсутствовать, а другая информация ещё не будет удалена. Это может создать впечатление, что платформа работает медленно или что оборудование пользователя устарело. Однако проблема заключается именно в том, что MetaTrader 5 занят чем-то ещё.
Чтобы всё было более приятно, я предлагаю использовать вызов стандартной библиотеки MQL5 в определенные моменты времени, чтобы заставить MetaTrader 5 обновлять график как можно быстрее. В разное время это будет совершенно не нужно. Но если вы заметили задержку между событиями, вы можете использовать этот вызов, чтобы пропустить очередь событий, с которой на данный момент работает MetaTrader 5.
В приведенном ниже фрагменте кода можно увидеть изменения, которые необходимо внести:
. . . 28. //+------------------------------------------------------------------+ 29. void OnDeinit(const int reason) 30. { 31. ChartSetInteger(0, CHART_SHOW_DATE_SCALE, gl_StyleGraphic.View_DateScale); 32. ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, gl_StyleGraphic.View_PriceScale); 33. ChartRedraw(); 34. }; 35. //+------------------------------------------------------------------+
Код 07
Простого добавления строки 33, которую можно увидеть в коде 07, будет достаточно, чтобы пользователь, да и вы сами, почувствовали явное улучшение работы MetaTrader 5, хотя следует помнить, что данное улучшение только кажущееся. Реального улучшения производительности нет. Вызов строки 33 сообщит MetaTrader 5 о том, что мы хотим пропустить очередь событий, чтобы график был обновлен как можно быстрее. Однако помните: пропуская очередь, мы откладываем событие, которое может оказаться важным и сработать в другое время. Поэтому будьте осторожны при изменении порядка выполнения.
Заключительные идеи
В этой статье мы увидели, как легко создать и внедрить оперативную методологию для окрашивания свечей - концепцию, которая очень ценится многими трейдерами. При реализации такого рода вещей необходимо проявлять осторожность, чтобы бары или свечи сохраняли свой первоначальный вид и не затрудняли чтение свечи за свечой.
Кроме того, мы продемонстрировали, как можно изменять различные элементы графика, хотя в статье было показано, как это сделать только с двумя свойствами: временной и ценовой шкалами. Шкалы, которые, в свою очередь, не могут быть удалены с помощью какого-либо ресурса, напрямую доступного обычному пользователю. Однако это вполне возможно и осуществимо с помощью кода. Но следует помнить, что при любой возможности нужно возвращать график в исходное состояние, так как это делает работу пользователя более приятной и свидетельствует о том, что приложение хорошо спланировано.
Поскольку существует несколько атрибутов и свойств, которые можно изменять, и было бы сложно рассматривать их по одному, я предлагаю вам потренироваться и поэкспериментировать с использованием и изменением данных свойств с помощью кода MQL5. Чтобы облегчить себе задачу, можете воспользоваться списком свойств графика, поскольку многие отображаемые элементы и значения будут доступны только через MQL5-код. Не забывайте, что в приложении будут только те коды, которые действительно нужны для практики и изучения того, что показано в статье.
Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/15833
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Автоматизация торговых стратегий на MQL5 (Часть 13): Создание торгового алгоритма для паттерна "Голова и Плечи"
Возможности Мастера MQL5, которые вам нужно знать (Часть 53): Market Facilitation Index
От начального до среднего уровня: Struct (III)
От начального до среднего уровня: Индикатор (III)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования