English 中文 Español Deutsch 日本語 Português
Горная карта, или График "Айсберг"

Горная карта, или График "Айсберг"

MetaTrader 5Индикаторы | 23 декабря 2022, 11:21
2 517 0
Daniel Jose
Daniel Jose

Введение

Как вам идея добавить новый тип графика в платформу MetaTrader 5? Многие говорят, что в ней не хватает несколько вещей, которые есть в других платформах. Но на самом деле MetaTrader 5 — очень практичная платформа, которая позволяет делать то, что невозможно сделать во многих других платформах, или по крайней мере, в них это сделать не так легко.

Одна из жалоб о, которой я чаще всего читаю, это наличие только трех типов графиков в MetaTrader 5: свечи, бары и линии. Но так ли это на самом деле? Или это просто недостаток знаний о реальной работе платформы либо о возможностях, предоставляемых языком MQL5?

Чаще всего именно те, кто больше всего жалуется, изучают платформу меньше всех. Все хотят, чтобы всё было в готовом виде, а если чего-то нет, начинают жаловаться.

В данной статье (не очень длинной на этот раз), мы рассмотрим, как создать график в другом, очень полезном стиле для тех, кто предпочитает определенные виды трейдинга, такие как swing trade, position trade и даже создание и сопровождение портфеля.

Сегодня рассмотрим график «Горная карта», однако мы не будем ограничиваться простым горным графиком, а выйдем за рамки возможностей этого графика и узнаем немного больше о том, как работать с MQL5. При этом мы разработаем очень интересный график для отслеживания позиций, с которым не нужно будет постоянно проверять, прибыльна ли сделка или нет — достаточно будет посмотреть на график, чтобы определить, находимся ли мы в прибыли или убытке по данной позиции.

Горный график очень похож на линейный, хотя в нем есть несколько небольших отличий. В случае линейного графика (который показан на рисунке 01), всё, что у нас есть — это простое указание на то, движется ли цена вверх или вниз, но не более того. Однако, в случае с горной картой мы можем сделать гораздо больше. Горный график показан на рисунке 02.


Рисунок 01

Рисунок 01 - Типичный линейный график


Рисунок 02

Рисунок 02 - Типичный горный график


График, показанный на рисунке 02, является наиболее распространенным типом "Горной карты". Однако, существует несколько его разновидностей, которые в некоторых случаях могут называться по-разному. Один из самых основных вариантов показан на рисунке 03.


Рисунок 03

Рисунок 03 - График "Айсберг" для позиций на покупку


На рисунке 03 изображен тип графика, который является одним из самых простых для чтения; в конкретном случае график, показанный на рисунке 03, предназначен для позиций на покупку, но такой же может быть для позиций на продажу. Такой график показан ниже на рисунке 04.


Рисунок 04

Рисунок 04 - График "Айсберг" для позиций на продажу


Это может быть не сразу понятно, но, наблюдая за графиками айсберга, можно сразу же увидеть, принесет ли позиция прибыль или убытки. Здесь все дело в цветах, которые сразу позволяют определить прибыльность/убыточность. То есть просто добавив цвета в горный график, можно реализовать другой стиль, который гораздо легче читать для тех пользователей, кто только начинает изучать рынок — особенно полезен он в ситуациях, когда нужно установить долгосрочную позицию.

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


Рисунок 05

Рисунок 05 - Линейный график анализа позиции


При этом также можно изменить стиль линии, то есть мы не ограничены сплошной линией. Можно получить график, как показан ниже на рисунке 06.


Рисунок 06

Рисунок 06 - Линейный график для анализа позиции на покупку


Вы могли подумать, что придется создать какой-то очень сложный код, чрезвычайно трудный для исполнения или понимания. Однако код, который мы собираемся создать, довольно прост и очень легок для понимания даже для новичков в языке MQL5. Поэтому он может стать хорошей отправной точкой для тех, кто хочет узнать больше о том, как работает платформа, и дальше уже создавать вещи немного сложнее.

То, что делает наш код для создания горной карты или айсберга, очень похоже на то, что делает индикатор Heiken-Ashi. Но, в отличие от Heiken-Ashi наша система будет создавать 100% чистый график, как можно видеть на изображениях выше — в нем не будет ничего лишнего, вроде стандартного графика, присутствующего по умолчанию в MetaTrader 5.

При этом факт создания другого графика не означает, что мы не сможем разместить на нем любимые индикаторы: с этим новым стилем графика можно будет использовать все индикаторы, советники, скрипты или что-либо еще, что мы использовали раньше, без необходимости адаптировать или изменять что-либо в коде. Всё это просто замечательно, учитывая количество вещей, которые могут возникнуть со временем.

Достаточно рассуждений, давайте теперь посмотрим, как реализовать эту новую систему графиков для MetaTrader 5.


Реализация

Глядя на приведенные выше рисунки, должно быть вы уже задаетесь вопросом о том, каким будет процесс создания графика, по крайней мере той его части, о которой мы говорим (она показана на рисунках 05 и 06). Сразу приходит на ум, что речь идет о скользящей средней. И это так, ведь у нас скользящая средняя изображена как на рисунке 05, так и на рисунке 06. Это нечто очень похожее на рисунок 01, но по какой-то причине на ней разные цвета. А как насчет других фигур?

В чем секрет создания графика на рисунке 02, рисунке 03 и рисунке 04? Можно ли придумать способ сделать это так, чтобы не перегружать платформу MetaTrader 5?

На самом деле, все графики, кроме рисунка 01, который на самом деле является линейным графиком и присутствует по умолчанию на платформе MetaTrader 5, создаются одинаково с использованием скользящей средней. Даже графики айсберга создаются таким же способом.

Чтобы понять это, для начала просто посмотрим на код. Он очень простой и начинается со следующих строк:

#property copyright "Daniel Jose"
#property icon "\\Images\\Icons\\Mountain Chart.ico"
#property description "This indicator allows you to create a mountain chart"
#property description "Whose average price can be indicated facilitating market analysis"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 1


В этой строке мы определяем место, где находится файл изображения, который будет использоваться в качестве иконки нашей системы. Мы также говорим, что будем пользоваться индикатором (да, график будет индикатором) в главном окне графика финансового инструмента.

Теперь наступает важный момент: мы будем использовать 2 буфера, НО ( акцент на этом слове) они не будут использоваться так, как можно было бы подумать, поэтому обратите внимание на эту часть. Мы будем строить график 1 индикатора, и опять же всё не совсем так, как указано здесь в начале.

Не забудьте, что у нас есть 3 возможных типа графиков: график с разноцветными линиями, график айсберга и горная карта... Поэтому не стоит слишком привязываться к информации, указанной в начале.

Сразу после этого идет несколько простых и необходимых нам объявлений, чтобы всё работало правильно:

double Buff1[], Buff2[];
//+------------------------------------------------------------------+
enum eType {Fill, Contour};
//+------------------------------------------------------------------+
input double    user01 = 0.0;   //Analysis price
input eType     user02 = Fill; //Type of Mountain
//+------------------------------------------------------------------+
struct st0
{
        long    id;
        color 	CandleBear,
                CandleBull,
                CandleLine,
                LineUp,
                LineDown;
}_memConfig;


Здесь мы объявляем два буфера, которые будем использовать. Затем создаем перечисление, чтобы помочь выбрать тип графика: с линиями, айсберг или горная карта. Теперь наступает момент, который связан именно с взаимодействием с пользователем. Здесь поймем, как будет представлен график и какой тип мы увидим на экране. У нас имеются следующие сочетания:

Тип графика     Значение, содержащееся в user01    
Значение, содержащееся в user02
Одноцветный линейный график Значение равно 0 Значение, указывающее на контур
Многоцветный линейный график       
Значение пороговой цены Значение, указывающее на контур
Горная карта Значение равно 0  Значение, указывающее на заполнение     
График "Айсберг" Значение цены ватерлинии Значение, указывающее на заполнение

Понимание этой таблицы поможет выбрать тип графика, который можно отобразить на экране.

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

Не стоит переживать за структуру, ведь она служит только как память для хранения определенной информации, которую можно будет увидеть позже.

Итак, мы с этим закончили, давайте перейдем к первой функции нашей графической системы:

int OnInit()
{
        IndicatorSetString(INDICATOR_SHORTNAME, "Mountain Chart");
        Init_MountainChart();
        
        return INIT_SUCCEEDED;
}


Эта функция очень проста — нужно просто указать имя нашего индикатора и вызвать функцию для запуска графика. Можно было бы поместить содержимое вызываемой функции здесь, но я люблю разделять вещи и делать код как можно более организованным.

Ниже показана следующая функция в последовательности:

int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{       
        for (int c0 = (prev_calculated == 0 ? 0 : prev_calculated - 1); c0 < rates_total; c0++)
        {
                Buff1[c0] = price[c0];
                Buff2[c0] = (user02 == Fill ? user01 : (price[c0] > user01 ? 0 : 1));
        }

        return rates_total;
}


Это очень простая функция, и она действительно должна быть очень простой, потому что она будет исполняться при каждом ценовом тике или изменении цены. Платформа MetaTrader 5 будет генерировать событие, результатом которого будет вызов функции OnCalculate, поэтому функция должна выполняться очень быстро.

Не хотелось бы пересчитывать всю серию данных с самого начала, поэтому в каждом вызове функции мы используем этот простой расчет, который просто будет корректировать значение. Поэтому у нас всегда будет максимально быстрое исполнение. В самом начала может быть небольшая задержка, но после этого всё происходит крайне быстро.

Теперь обратите внимание на следующее: здесь мы будем получать от платформы MetaTrader 5 только один тип значения, который выбирается в окне сообщений индикатора. Возможные значения, которые MetaTrader 5 будет передавать нашему индикатору, показаны на рисунке 08.

Рисунок 08

Рисунок 08 - Виды значений, передаваемых из MetaTrader 5 в индикатор


Это значение будет использовано в buffer01, это тот буфер, который нам нужен и который мы будем использовать. Buffer02 будет получать значение в зависимости от того, что мы создаем. Почему именно так?

Причина в том, что мы будем использовать два разных стиля рисования. В одном из стилей buffer02 получит значение, которое является пороговым значением или ватерлинией. Когда значение ватерлинии выше 0, такое происходит, потому что ни один актив не может торговаться ниже этого значения, и поэтому нет смысла держать актив с отрицательным значением. В результате у нас будет горная карта, если используется режим заполнения, как график на изображении 02.

Но если значение ватерлинии отличное от нуля, мы будем иметь график айсберга как на рисунках 03 и 04. Аналогично, если мы используем режим контура и ватерлиния равна 0, то у нас будет линейный график, который однако будет отличаться от линейного графика по умолчанию в MetaTrader 5.

Можно указать толщину и стиль линии и в в результате получить график, похожий на график на рисунках 05 и 06, хотя там значение ватерлинии отличается  от нуля, и именно поэтому та разные цвета на разных участках линии.

Ниже показана следующая функция:

void OnDeinit(const int reason)
{
        ShowBars();
}


Она просто завершает работу индикатора, заставляя график вернуться в исходное состояние. Давайте теперь рассмотрим еще одну функцию, работу которой стоит объяснить.

void Init_MountainChart(void)
{
        _memConfig.id = ChartID();
        PlotIndexSetInteger(0, PLOT_DRAW_TYPE, (user02 == Fill ? DRAW_FILLING : DRAW_COLOR_LINE));
        SetIndexBuffer(0, Buff1, INDICATOR_DATA);
        SetIndexBuffer(1, Buff2, (user02 == Fill ? INDICATOR_DATA : INDICATOR_COLOR_INDEX));
        PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 2);
        PlotIndexSetString(0, PLOT_LABEL, "MidPoint");  
        PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, clrForestGreen);
        PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, clrFireBrick);       
        PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, 0);
        HideBars();
}




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

Именно поэтому код выглядит немного иначе, чем можно было подумать в начале. Дело в одной детали — обе модели используют два буфера, но модель DRAW_FILLING использует оба буфера с данными, а модель DRAW_COLOR_LINE использует один буфер с данными, а другой с цветом. Именно поэтому нужно правильно произвести расчет в функции, которая отвечает за отображение индикатора.

Обязательно в любом случае должен использоваться первый буфер данных buffer01. Buffer02 же будет зависеть от того, что нужно построить, он может содержать данные или цветовой индекс. Обратите внимание, я не говорю, что buffer02 будет содержать используемый цвет, НЕ нужно пытаться указать там цвет. В этом буфере указывается индекс, который и определит, какой цвет будет использоваться. Вот почему в функции расчета я не использовал никакой информации о цвете и только значения 0 и 1, так как мы собираемся работать только с двумя цветами.

                Buff2[c0] = (user02 == Fill ? user01 : (price[c0] > user01 ? 0 : 1));


Пока пойдем дальше. Следующее, что мы сделаем, это определимся с использованием двухцветной матрицы.Метка, которую мы используем здесь, будет видна на ватерлинии при наведении мыши и при выборе и определении цвета. Я добавил эту возможность просто, чтобы показать, как можно сохранить информацию, которая может понадобиться в будущем.

Теперь определяем цвета, используемые по умолчанию, которые пользователь не может изменить — придется сначала прикрепить индикатор на график и только потом изменить цвета. Это тоже показано на видео в конце статьи.

И в финале указываем, с какой позиции будет строиться наш график. На самом деле сейчас в этом нет необходимости, я просто хочу показать, как это можно сделать.

После этого можно перейти к последним двум функциям нашей системы микро-графиков. Функция HideBars отвечает за скрытие стандартной схемы графиков MetaTrader 5, то есть мы скроем сам график в MetaTrader 5. Это сделать очень просто. Но мы же не хотим разозлить пользователя, если что-то пойдет не так, поэтому сохраним исходные данные, чтобы восстановить их позже, когда индикатор будет удален с графика финансового инструмента. Позже можно будет легко вернуть исходную цветовую схему.

void HideBars(void)
{
        _memConfig.CandleBear   = (color) ChartGetInteger(_memConfig.id, CHART_COLOR_CANDLE_BEAR);
        _memConfig.CandleBull   = (color) ChartGetInteger(_memConfig.id, CHART_COLOR_CANDLE_BULL);
        _memConfig.CandleLine   = (color) ChartGetInteger(_memConfig.id, CHART_COLOR_CHART_LINE);
        _memConfig.LineUp       = (color) ChartGetInteger(_memConfig.id, CHART_COLOR_CHART_UP);
        _memConfig.LineDown     = (color) ChartGetInteger(_memConfig.id, CHART_COLOR_CHART_DOWN);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CANDLE_BEAR, clrNONE);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CANDLE_BULL, clrNONE);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CHART_LINE, clrNONE);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CHART_UP, clrNONE);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CHART_DOWN, clrNONE);
        ChartRedraw();
}
//+------------------------------------------------------------------+
void ShowBars(void)
{
        ChartSetInteger(_memConfig.id, CHART_COLOR_CANDLE_BEAR, _memConfig.CandleBear);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CANDLE_BULL, _memConfig.CandleBull);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CHART_LINE, _memConfig.CandleLine);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CHART_UP, _memConfig.LineUp);
        ChartSetInteger(_memConfig.id, CHART_COLOR_CHART_DOWN, _memConfig.LineDown);
        ChartRedraw();
}


В конечном итоге после сброса данных пользователь даже не заметит, что что-то не так. Не нужно будет настраивать все заново, и это всегда здорово, ведь это дает больший уровень удобства при использовании системы.

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


Демонстрация работы (ВАЖНО ПРОСМОТРЕТЬ)

Заключение

В этой статье я показал, что и MQL5, и сама платформа MetaTrader 5 способны создать гораздо больше, чем многие себе представляют. В статье все сделано просто, и все же это может помочь понять некоторые другие моменты.

Самая большая проблема заключается в том, что многие люди говорят то или иное о платформе или о языке MQL5, хотя на самом деле они даже не изучают возможности платформы и в действительности не знают, что можно или нельзя сделать. Они просто продолжают говорить и повторять то, что говорят многие, просто не разобравшись в возможностях.

Каждый раз, когда вы услышите, что платформа MetaTrader 5 или язык MQL5 ограничены, что у них нет определенных возможностей, покажите эту статью тем, кто так говорит. Единственное, что действительно ограничено — это их творческие способности или знания, а говорят они так, потому что ничего не знают о программировании и не понимают цели платформы MetaTrader 5, которая должна быть функциональной, безопасной, быстрой платформой, но прежде всего платформой, где уровень настройки находится на такой высоте, что платформа может подстраиваться под каждого из нас.


Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/11078

Прикрепленные файлы |
Mountain_Chart.zip (12.8 KB)
Машинное обучение и Data Science (Часть 9): Алгоритм k-ближайших соседей (KNN) Машинное обучение и Data Science (Часть 9): Алгоритм k-ближайших соседей (KNN)
Это ленивый алгоритм, который не учится на обучающей выборке, а хранит все доступные наблюдения и классифицирует данные сразу же, как только получает новую выборку. Несмотря на простоту, этот метод используется во множестве реальных приложений.
DoEasy. Элементы управления (Часть 31): Прокрутка содержимого элемента управления "ScrollBar" DoEasy. Элементы управления (Часть 31): Прокрутка содержимого элемента управления "ScrollBar"
В статье создадим функционал прокрутки содержимого контейнера кнопками горизонтальной полосы прокрутки.
Возможности Мастера MQL5, которые вам нужно знать (Часть 04): Линейный дискриминантный анализ Возможности Мастера MQL5, которые вам нужно знать (Часть 04): Линейный дискриминантный анализ
Современный трейдер почти всегда находится в поиске новых идей. Он постоянно пробует новые стратегии, модифицирует их и отбрасывает те, что не оправдали себя. В этой серии статей я постараюсь доказать, что Мастер MQL5 является настоящей опорой трейдера в его поисках.
Машинное обучение и Data Science (Часть 8): Кластеризация методом k-средних в MQL5 Машинное обучение и Data Science (Часть 8): Кластеризация методом k-средних в MQL5
Для всех, кто работает с данными, включая трейдеров, data mining может открыть совершенно новые возможности, ведь зачастую данные не такие простые, какими кажутся. Человеческому глазу сложно увидеть глубинные закономерности и отношения в наборе данных. Одно из решений — алгоритм К-средних. Давайте посмотрим, полезен ли он.