Введение в MQL5 (часть 9): Использование объектов на графике
Введение
Представляю вашему вниманию очередную статью из нашей серии, посвященной MQL5. Сегодня мы обсудим очень важную тему, которая, я уверен, еще и будет очень полезной и интересной. Кроме того, мы начнем проект, в котором будем работать с различными объектами графиков. Эта разработка станет основой для наших будущих проектов. Это будет отправная точка, от которой мы будем двигаться к более сложным проектам, например, к использованию различных гармонических моделей. Объекты графика в MQL5 — это графические элементы, которые можно размещать на графиках торговых инструментов для визуального представления различных типов данных, таких как уровни цен, торговые зоны и текстовые метки. Сущность объектов позволяет создавать гибко настраиваемые визуальные элементы, которые помогают анализировать графики, определять рыночные тренды, ключевые ценовые уровни и торговые возможности в целом.
В MQL5 существуют различные объекты графиков: от простых линий и фигур до сложных компонентов, таких как текст, стрелки и пользовательские индикаторы. Изменяя цвет, размер, положение и другие атрибуты каждого объекта, можно создать подстроенную конкретно под вас торговую среду. Объекты графиков — это не просто графика, это эффективные инструменты для создания понятных визуальных представлений рыночных данных. Например, может быть проще определить возможные точки разворота, если уровни поддержки и сопротивления выделены прямоугольниками. В этой статье представлен практический пример, который должен помочь раскрыть идею объектов в MQL5 показать, как их использовать.
В этом проекте мы разработаем советник, который будет отображать понятную визуализацию прямо на графике. Советник будет автоматически отображать путь от точки входа до зон стоп-лосса и тейк-профита. Такое визуальное представление позволит быстро оценить риски и прибыли вашей сделки. Кроме того, советник будет обновляться в режиме реального времени и отражать текущую прибыль или убыток по мере движения рынка. Также он будет показывать цены входа, уровни стоп-лосса и тейк-профита для текущей позиции, чтобы можно было быстро оценить ситуацию.
Одной из важных характеристик этого советника является его способность адаптироваться к изменениям в торговых настройках. Все визуальные подсказки всегда будут актуальными, поскольку советник быстро обновит график, если вы измените уровни тейк-профита или стоп-лосса. Также он будет учитывать продолжительность сделки. При более длительном удержании сделки советник будет постепенно подстраиваться так, чтобы визуальные элементы стали более заметными. Это позволит эффективно отслеживать торговлю на разных таймфреймах, хотя сразу после открытия на младшем таймфрейме метка может быть не очень заметна на более старших. С такой динамической адаптацией проще управлять сделками с младших таймфреймов и отслеживать любые изменения.
С этим экспертом вы сможете изучать и прошлые сделки, чтобы получить глубокий исторический анализ. Так вы сможете оценить эффективность вашей торговли на основе прибылей и убытков от прошлых сделок и принимать более взвешенные решения. Исторические данные по выбранному вами диапазону также будут отображаться прямо на графике. Таким образом вы получаете полный обзор истории вашей торговли и возможность детализировать отдельные сделки для более глубокого анализа.
Визуализация текущей торговли:Визуализация торговой истории:
В этой статье мы поговорим о следующем:
- Создание и изменение объектов на графике для расширенного визуального анализа
- Цикл по позициям для эффективного управления и отображения сделок на графике
- Использование исторических данных о сделках для размещения объектов на графике
- Визуализация прибыли/убытка по сделкам из истории на графике
- Использование datetime для точного размещения объектов на графике
- Метки для данных входа, тейк-профита (TP) и стоп-лосса (SL) на графике
- Использование входных параметров для настройки советника
Целью этого проекта является знакомство с полезными способами использования объектов в MQL5. Вы на практике научитесь управлять сделками, использовать визуальный анализ и отображать торговые данные прямо на графиках с помощью интерактивных объектов прямо из эксперта. Мы подробно рассмотрим все этапы работы с объектами на графике: создание, изменение и управление.
1. Графические объекты в MQL5
1.1. Что такое графические объекты?
В MQL5 это визуальные компоненты, которые можно добавить на график, чтобы визуализировать ту или иную информацию. Эти объекты могут быть более сложными элементами, такими как каналы или стрелки, или более простыми фигурами, линиями и текстом. Объекты в основном используются для визуального представления важных данных, используемых трейдерами при планировании сделок, оценке рыночных условий и отслеживании открытых позиций. Они используются для выделения значимых уровней цен и построения на графике линий тренда, указывающих направление рынка. Визуализация таких данных на графике помогает трейдерам принимать более обоснованные торговые решения и быстрее оценивать рыночные условия, ведь быстрее определить на взгляд, чем анализировать числовые данные.
1.2. Зачем настраивать объекты на графике?
Настройка объектов графика помогает повысить его визуальную четкость и облегчить восприятие. Вы можете изменять цвета, размеры и расположение объектов, чтобы адаптировать график под собственные предпочтения и стиль торговли. Это позволяет выделить наиболее важную информацию, чтобы она сразу бросалась в глаза.
Например, если для вас особенно важны уровни поддержки и сопротивления, целесообразно использовать толстые линии ярких цветов, которые легко заметить даже при быстром просмотре графика. Это снизит вероятность пропустить ключевые сигналы во время напряженной торговой сессии. Аналогично, выделение текстовых меток может служить визуальной подсказкой, помогая запоминать важные торговые решения или запланированные стратегии.
1.3. Какие объекты будут использоваться в проекте
В данном проекте мы будем использовать некоторые основные объекты графиков в MQL5 для улучшения анализа торговли. Сюда входят:
1.3.1. Трендовые линии
Один из важнейших инструментов в проекте — линия тренда. Она используется для отслеживания текущей рыночной цены относительно значимых уровней тренда и для определения точки входа. Чтобы определить общее направление рынка, мы будем строить трендовую линию между важными ценовыми точками. По мере изменения рыночной цены (тиков) линия тренда обновляется в реальном времени от начальной цены входа до последней актуальной рыночной цены.
Таким образом, она гарантированно отражает самые последние данные, помогая точно отслеживать динамику торговли и принимать соответствующие решения при управлении позицией. Как правило, построение линии тренда начинается с цены входа в позицию, то есть с начальной точки сделки. Затем она продолжается до текущей рыночной цены или цены Ask. Это позволяет видеть, как изменилась цена с момента открытия сделки.
1.3.2. Текстовые метки
Текстовые метки предоставляют четкую и понятную информацию о различных аспектах сделки, это как комментарии на графике. На них можно отображать важные данные, такие как точки входа, уровни стоп-лосса, цели тейк-профита и другие пометки относительно торговой стратегии. Вы можете добавлять текстовые метки к значимым областям графика и легко получать важную информацию. При этом не нужно сверяться с внешними записями или пытаться вспомнить. Этот визуальный инструмент, который позволяет отображать на графике необходимые сведения в текстовом виде.
Текстовая метка с текущей прибылью или убытком открытой позиции будет обновляться на каждом тике. Благодаря этому в режиме реального времени можно отслеживать эффективность сделки и мгновенно понимать, движется ли она в правильном направлении. Например, метка вида +$100 или −$50 рядом со сделкой покажет текущий финансовый результат. Значение будет обновляться при каждом изменении рыночной цены. Это позволит следить за динамикой сделки и при необходимости вносить коррективы.
1.3.3. Объект "Прямоугольник"
Прямоугольники на графике могут использоваться для обозначения уровней поддержки и сопротивления. Но в данном проекте они будут применяться только для выделения зон прибыли и убытка в сделке. Если позиция находится в убытке, мы будем рисовать прямоугольник от точки входа до уровня стоп-лосса. Это позволит быстро определить, когда сделка приближается к критическому уровню. Мы визуально будем обозначать область, где торговля идет в отрицательном направлении. Когда позиция будет выходить в прибыль, будем рисовать прямоугольник от точки входа до уровня тейк-профита. Это поможет отслеживать прогресс сделки, вы будете видеть зоны, где она идет в положительном направлении и приближается к установленной цели.
В MQL5 доступно множество различных объектов, с которыми анализировать графики проще и эффективнее. Однако охватить их все в одной статье было бы слишком объемно. Поэтому сосредоточимся только на тех, которые будут использоваться в нашем проекте. Помимо того, что выбранные объекты (прямоугольник, тредовая линия и текстовая метка) являются основой данного проекта, они еще имеют схожие процессы создания и модификации с другими объектами MQL5. Поэтому если вы научитесь работать с этим набором, вы получите базовые знания, необходимые для работы с различными графическими объектами в MQL5, а также сможете использовать аналогичные методы для их создания и настройки.
2. Создание и настройка объектов
В этом разделе мы посмотрим, как создавать и изменять различные объекты в MQL5. Вы научитесь создавать прямоугольники, линии тренда и текстовые метки, а также настраивать их цвета, стиль и ширину.
2.1. Псевдокод
В этом проекте мы используем псевдокод, поскольку позволяет структурированно и кратко изложить логику и последовательность действий перед написанием кода. Он помогает разбить сложные задачи на более простые компоненты, что облегчает планирование, выявление потенциальных проблем и гарантирует, что код будет эффективным и хорошо организованным. Использование псевдокода позволяет визуализировать весь процесс работы советника, упрощая реализацию объектов и других функций.
Вот базовый псевдокод для нашего советника:
1. Инициализация:
- Определение цветов для зоны SL, зоны TP и линии тренда.
- Установка индекса позиции.
- Определение параметра отображения исторических данных.
- Задание начальной и конечной даты для исторических данных.
- Установка времени закрытия зоны.
- Получение идентификатора текущего графика.
- Инициализация переменных для хранения параметров позиции (цена открытия, стоп-лосс, тейк-профит, прибыль, время открытия).
2. На каждом тике:
- Конвертация строкового значения времени в объект datetime для зоны закрытия.
- Получение текущей цены ask.
- Перебор всех открытых позиций.
- Получение номера тикета позиции.
- Проверка соответствия символа позиции текущему графику.
- Извлечение данных: цена открытия, стоп-лосс, тейк-профит, время открытия, прибыль.
- Если позиция соответствует указанному индексу.
- Создание и настройка прямоугольника для зоны стоп-лосса.
- Установка параметров (цвет, стиль, толщина, заливка).
- Создание и настройка прямоугольника для зоны тейк-профита.
- Установка параметров (цвет, стиль, толщина, заливка).
- Создание и настройка линии тренда.
- Установка параметров (цвет, стиль, толщина).
- Вычисление и отображение текущей прибыли позиции.
- Форматирование и вывод прибыли в виде текста.
- Создание и настройка текстовых объектов для точек Entry, TP и SL.
- Установка параметров (цвет, размер шрифта).
3. Если включено отображение исторических данных:
- Очистка предыдущих комментариев.
- Выбор и перебор исторических сделок в заданном диапазоне дат:
- Получение данных для каждой сделки (цена открытия, цена закрытия, SL, TP, прибыль, время).
- Отображение информации о прибыли/убытке.
- Создание и настройка зон сто-лосса, тейк-профита и линии тренда для исторических сделок:
- Установка параметров (цвет, стиль, толщина).
2.2. Практическое применение: создание и настройка объектов
2.2.1 Создание объектов
В MQL5 одной из ключевых функций для создания различных объектов на торговом графике является ObjectCreate(). С помощью этой функции можно добавлять на график объекты, которые помогают трейдерам лучше визуализировать рыночные данные, анализировать тренды и отмечать важные точки на графике. К таким объектам относятся линии тренда, прямоугольники, текстовые метки, стрелки и многое другое.
Настройка расположения объектов
Функция ObjectCreate() позволяет не только добавлять объекты на график, но и точно управлять их расположением. Используя параметры функции, вы можете размещать объекты в определенных местах на графике, где они будут наиболее удобными. Два основных фактора, определяющих расположение объектов на графике, это время и цена. Эти параметры служат точкой привязки, обеспечивая точное отображение объекта в нужном месте графика.
Синтаксис:
ObjectCreate(chart_id, object_name, object_type, sub_window, time1, price1, time2, price2, time3, price3);
Взаимосвязь времени и цены при размещении объектов
Каждая точка на торговом графике в MQL5 определяется пересечением цены (вертикальная ось) и времени (горизонтальная ось). Эти две координаты используются для точного размещения объектов на графике при их создании с помощью ObjectCreate().
Точки привязки: time1, price1, time2, price2, time3, price3
При использовании ObjectCreate() для создания объектов часто необходимо определить одну или несколько точек привязки. Эти точки определяют точное местоположение объекта на графике. В зависимости от типа создаваемого объекта могут потребоваться одна или несколько точек, которые задаются параметрами time1, price1, time2, price2, time3 и price3.
- time1, price1 — задают начальную точку привязки объекта. Например, если вы рисуете линию тренда, то time1 указывает на временную отметку (момент на свечном графике), а price1 определяет уровень цены в этой точке.
- time2, price2 — определяют вторую точку привязки объекта. Для линии тренда это будет конечная точка. time2 указывает время второго узла, а price2 – соответствующий уровень цены.
time3, price3 — третий узел, который требуется для более сложных объектов (например, каналов или треугольников). Эти параметры используются при создании фигур, которым необходимо три координаты для построения.
// Get the ID of the current chart long chart_id = ChartID(); //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { // Define the first anchor point for the trendline // 'time1' is the datetime for the first point, and 'price1' is the price at that time datetime time1 = D'2024.08.21 16:00'; double price1 = 8766.01; // Define the second anchor point for the trendline // 'time2' is the datetime for the second point, and 'price2' is the price at that time datetime time2 = D'2024.08.28 08:00'; double price2 = 8854.51; // Create a trendline object on the chart // 'chart_id' is the ID of the chart where the object will be placed // "Trend Line" is the name of the trendline object // 'OBJ_TREND' specifies that the object is a trendline // The last four parameters (0, time1, price1, time2, price2) specify the anchor points of the trendline ObjectCreate(chart_id, "Trend Line", OBJ_TREND, 0, time1, price1, time2, price2); }
Результат:
Текстовые метки (OBJ_TEXT) можно размещать на графике, используя всего одну точку привязки. Эта точка определяет положение текста на основе заданных координат времени и цены. Например, можно разместить текстовую метку с надписью "Buy Here" в определенный момент времени и на конкретном ценовом уровне.
Пример:
// Get the ID of the current chart long chart_id = ChartID(); //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { // Define the time for the text label's position (August 21, 2024, at 16:00) datetime time1 = D'2024.08.21 16:00'; // Define the price level for the text label's position (8766.01) double price1 = 8766.01; // Create a text object named "Text" on the chart at the specified time and price ObjectCreate(chart_id, "Text", OBJ_TEXT, 0, time1, price1); // Set the text content of the object to display "Buy Here" ObjectSetString(chart_id, "Text", OBJPROP_TEXT, "Buy Here"); }
Результат:
2.3. Настройка объектов
Вы можете настраивать визуальные параметры объектов на графике, адаптируя их под свои предпочтения. Это включает изменение размера, цвета и стиля объектов. Например, линию тренда можно визуально выделить путем изменения цвета, толщины и расположения так, чтобы она соответствовала ключевым уровням рынка. Для текстовых меток можно настроить шрифт и цвет, чтобы выделить важные элементы, например, целевые уровни прибыли или точки входа.
Пример:
// Define the time for the text label's position (August 21, 2024, at 16:00) datetime time1 = D'2024.08.21 16:00'; // Define the price level for the text label's position (8766.01) double price1 = 8766.01; // Create a text object named "Text" on the chart at the specified time and price ObjectCreate(chart_id, "Text", OBJ_TEXT, 0, time1, price1); // Set the text content of the object to display "Buy Here" ObjectSetString(chart_id, "Text", OBJPROP_TEXT, "Buy Here"); // Set the color of the text object to Medium Blue ObjectSetInteger(chart_id, "Text", OBJPROP_COLOR, clrMediumBlue);
Этот код отображает текст "Buy Here", добавляет текстовую метку на график в указанное время и по указанной цене, а также меняет цвет текста на Medium Blue.
Результат:
2.3.1. Функции для настройки объектов в MQL5
Объекты на графике в MQL5 можно настраивать с помощью специальных функций. Эти функции позволяют изменять внешний вид, характеристики и расположение объектов и подстраивать их под ваши потребности.
Используется для установки свойств объектов, представленных целочисленными значениями: цвет, толщина линии, стиль.
Пример:// Get the ID of the current chart long chart_id = ChartID(); //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { datetime time1 = D'2024.08.21 16:00'; double price1 = 8766.01; // Define the second anchor point for the trendline // 'time2' is the datetime for the second point, and 'price2' is the price at that time datetime time2 = D'2024.08.28 08:00'; double price2 = 8854.51; // Create a trend line object on the chart with the name "Trend Line" // The trend line will be drawn from time1/price1 to time2/price2 ObjectCreate(chart_id, "Trend Line", OBJ_TREND, 0, time1, price1, time2, price2); // Set the style of the trend line to a dashed line ObjectSetInteger(chart_id, "Trend Line", OBJPROP_STYLE, STYLE_DASH); // Set the width of the trend line to 2 ObjectSetInteger(chart_id, "Trend Line", OBJPROP_WIDTH, 2); }
Результат:
Эта функция задает свойства объектов, представленные числовыми значениями с плавающей запятой (double). Чаще всего она используется для работы с ценами и временем. Например, позволяет изменять координаты точек привязки.
Позволяет устанавливать строковые свойства объектов, например, текст, отображаемый в текстовой метке.
Например, добавляет аннотации или заметки непосредственно на график.
// Create a text object named "Text" on the chart at the specified time and price ObjectCreate(chart_id, "Text", OBJ_TEXT, 0, time1, price1); // Set the text content of the object to display "Buy Here" ObjectSetString(chart_id, "Text", OBJPROP_TEXT, "Buy Here");
В MQL5 доступно множество функций для создания, настройки и управления объектами. С помощью них вы можете настроить кастомное отображение информации на графиках. Для нашего проекта важны ObjectCreate и ObjectSetInteger, но есть и множество других функций. Более детальное описание всех доступных функций для работы с объектами представлено в документации MQL5.
3. Реализация объектов в нашем проекте
3.1. Создание объектов для текущих позиций
В этом разделе мы разберем, как настроить объекты для отображения на графике данных о текущих позициях. В частности, в нашем проекте мы будем работать с прямоугольниками (визуализация зон SL и TP), линиями тренда (отображение динамики) и текстовыми метками (аннотации важных уровней).
3.1.1. Использование прямоугольников для выделения зон
Мы создадим два прямоугольника для выделения ключевых зон на графике: зона стоп-лосса и зона тейк-профита. Эти прямоугольники будут динамически отображать зоны стоп-лосс и тейк-профит, так что вы сможете легко и быстро отслеживать уровни риска и прибыли.
a. Выделение зоны стоп-лосса:
- Первая точка привязки — начальная точка прямоугольника, цена входа и время открытия позиции.
- Вторая точка привязки — уровень стоп-лосс, горизонтально растянутая до 23:59 текущего дня. Мы растягиваем ее, чтобы прямоугольник гарантированно динамически обновлялся каждый день, расширяясь и визуально охватывая зону стоп-лосс до тех пор, пока сделка не будет закрыта или не закончится день.
- Цель — визуально показать зону риска, чтобы быстро оценивать, насколько текущая цена близка к уровню стоп-лосс.
b. Выделение зоны тейк-профита:
- Первая точка привязки — начальная точка прямоугольника, вход в позицию.
- Вторая точка привязки — горизонтально растянут до 23:59 текущего дня, на уровне цены тейк-профита. Как и зона стоп-лосс, область потенциальной прибыли будет постоянно подсвечиваться расширяющимся прямоугольником в течение дня.
Прежде чем создать прямоугольники по зонам стоп-лосса и тейк-профита, нам нужно программно извлечь необходимую информацию по каждой позиции. Это цена открытия, уровень стоп-лосса, уровень тейк-профита и время открытия сделки. Эти данные нужны для правильного расположения прямоугольников на графике. Обратите внимание на код — мы в автоматическом режиме динамически обновляем расположение прямоугольника, чтобы не приходилось каждый раз при движении цены размещать новый объект.
Пример:
// Variables to store position details double open_price; // Variable to store the entry price of the position double stop_loss; // Variable to store the Stop Loss level of the position double take_profit; // Variable to store the Take Profit level of the position datetime position_open_time; // Variable to store the open time of the position //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Loop through all open positions for(int i = 0; i < PositionsTotal(); i++) { // Get the ticket number of the position at index 'i' ulong ticket = PositionGetTicket(i); // Retrieve and store the entry price of the position open_price = PositionGetDouble(POSITION_PRICE_OPEN); // Retrieve and store the Stop Loss level of the position stop_loss = PositionGetDouble(POSITION_SL); // Retrieve and store the Take Profit level of the position take_profit = PositionGetDouble(POSITION_TP); // Retrieve and store the open time of the position position_open_time = (int)PositionGetInteger(POSITION_TIME); // Print the retrieved values for debugging or verification Print("Open Price index ",i,": ",open_price); Print("SL index ",i,": ",stop_loss); Print("TP index ",i,": ",take_profit); Print("Open time index ",i,": ",position_open_time); } }
Объяснение:
Каждый раз, когда цена торгового инструмента изменяется, функция OnTick() запускает код. При работы она извлекает информацию о каждой открытой позиции на торговом счете. Мы здесь проходимся в цикле по всем открытым позициям на торговом счете. Функция PositionsTotal() возвращает конкретную информацию о каждой позиции на основе ее индекса в общем списке позиций. Для получения этих данных используются функции PositionGetDouble() и PositionGetInteger(). Для отладки или проверки полученные данные выводятся в терминал перед добавлением любых визуальных элементов на график (перед отрисовкой прямоугольников для зон стоп-лосса и тейк-профита). Это гарантирует, что собираемая информация является точной.
При текущей реализации мы сталкиваемся с двумя проблемами:
- Определение конкретной позиции — в текущей версии советник не знает, через какую именно позицию он проходит в процессе получения данных о времени и цене. Это означает, что когда требуется информация только по одной конкретной позиции, код извлекает данные из всех открытых позиций, что может запутать и показать использование некорректных данных.
- Данные по инструменту, отображаемому на графике — извлекаемая информация должна соответствовать открытым позициям и сделкам, связанным с инструментом, который в данный момент отображается на графике. Если символ на графике не фильтруется, советник может получить данные о позициях, относящихся к другим инструментам, что приведет к неточным или вводящим в заблуждение визуальным отображениям.
Чтобы решить эти проблемы, можно добавить входной параметр, в котором пользователь сможет выбрать индекс позиции, с которой нужно работать. На основе этого индекса советник выберет нужную позицию и отобразит соответствующие объекты. Также необходимо добавить проверку, соответствует ли выбранная позиция символу текущего графика.
Пример:
// Variables to store position details double open_price; // Variable to store the entry price of the position double stop_loss; // Variable to store the Stop Loss level of the position double take_profit; // Variable to store the Take Profit level of the position datetime position_open_time; // Variable to store the open time of the position // Define the position index for the first position input int position_index = 0; // POSITION INDEX (Index starts from 0) // Get the ID of the current chart long chart_id = ChartID(); //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Loop through all open positions for(int i = 0; i < PositionsTotal(); i++) { // Get the ticket number of the position at index 'i' ulong ticket = PositionGetTicket(i); if(PositionGetInteger(POSITION_TICKET) == PositionGetTicket(position_index) && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { // Retrieve and store the entry price of the position open_price = PositionGetDouble(POSITION_PRICE_OPEN); // Retrieve and store the Stop Loss level of the position stop_loss = PositionGetDouble(POSITION_SL); // Retrieve and store the Take Profit level of the position take_profit = PositionGetDouble(POSITION_TP); // Retrieve and store the open time of the position position_open_time = (int)PositionGetInteger(POSITION_TIME); // Print the retrieved values for debugging or verification Print("Open Price index ",i,": ",open_price); Print("SL index ",i,": ",stop_loss); Print("TP index ",i,": ",take_profit); Print("Open time index ",i,": ",position_open_time); } } }
Алгоритм перебирает каждую открытую позицию, определяет, соответствует ли она выбранному индексу и символу графика, а затем извлекает соответствующую информацию. Теперь можно создать два прямоугольника, которые будут обозначать зоны стоп-лосса и тейк-профита на основе информации о цене и времени для данной позиции. Теперь, чтобы отобразить прямоугольники на нужных позициях, необходимо передать полученные значения позиции в параметрах функции ObjectCreate().
Пример:// Variables to store position details double open_price; // Variable to store the entry price of the position double stop_loss; // Variable to store the Stop Loss level of the position double take_profit; // Variable to store the Take Profit level of the position datetime position_open_time; // Variable to store the open time of the position // Define the position index for the first position input int position_index = 1; // POSITION INDEX (Index starts from 0) // Get the ID of the current chart long chart_id = ChartID(); // Store the ID of the current chart string time = "23:59"; // Define a specific time as a string // Define the color for the losing zone input color sl_zonez_color = clrPink; // Choose a color for Losing Zone // Define the color for the winning zone input color tp_zonez_color = clrSpringGreen; // Choose a color for Winning Zone //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Convert the string time to datetime datetime close_zone = StringToTime(time); // Loop through all open positions for(int i = 0; i < PositionsTotal(); i++) { // Get the ticket number of the position at index 'i' ulong ticket = PositionGetTicket(i); // Check if the position matches the specified index and symbol of the current chart if(PositionGetInteger(POSITION_TICKET) == PositionGetTicket(position_index) && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { // Retrieve and store the entry price of the position open_price = PositionGetDouble(POSITION_PRICE_OPEN); // Retrieve and store the Stop Loss level of the position stop_loss = PositionGetDouble(POSITION_SL); // Retrieve and store the Take Profit level of the position take_profit = PositionGetDouble(POSITION_TP); // Retrieve and store the open time of the position position_open_time = (int)PositionGetInteger(POSITION_TIME); // Print the retrieved values for debugging or verification Print("Open Price index ",i,": ",open_price); Print("SL index ",i,": ",stop_loss); Print("TP index ",i,": ",take_profit); Print("Open time index ",i,": ",position_open_time); // Create a rectangle to represent the Stop Loss (SL) zone on the chart ObjectCreate(chart_id, "SL Zone", OBJ_RECTANGLE, 0, position_open_time, open_price, close_zone, stop_loss); // Create a rectangle to represent the Take Profit (TP) zone on the chart ObjectCreate(chart_id, "TP zone", OBJ_RECTANGLE, 0, position_open_time, open_price, close_zone, take_profit); // Set properties for the SL zone rectangle ObjectSetInteger(chart_id, "SL Zone", OBJPROP_COLOR, sl_zonez_color); // Set color to the selected SL zone color ObjectSetInteger(chart_id, "SL Zone", OBJPROP_STYLE, STYLE_SOLID); // Set style to solid ObjectSetInteger(chart_id, "SL Zone", OBJPROP_WIDTH, 1); // Set the width of the rectangle border ObjectSetInteger(chart_id, "SL Zone", OBJPROP_FILL, sl_zonez_color); // Fill the rectangle with the selected SL zone color ObjectSetInteger(chart_id, "SL Zone", OBJPROP_BACK, true); // Set the rectangle to appear behind the chart objects // Set properties for the TP zone rectangle ObjectSetInteger(chart_id, "TP zone", OBJPROP_COLOR, tp_zonez_color); // Set color to the selected TP zone color ObjectSetInteger(chart_id, "TP zone", OBJPROP_STYLE, STYLE_SOLID); // Set style to solid ObjectSetInteger(chart_id, "TP zone", OBJPROP_WIDTH, 1); // Set the width of the rectangle border ObjectSetInteger(chart_id, "TP zone", OBJPROP_FILL, tp_zonez_color); // Fill the rectangle with the selected TP zone color ObjectSetInteger(chart_id, "TP zone", OBJPROP_BACK, true); // Set the rectangle to appear behind the chart objects } } }
Объяснение:
Здесь код получает время открытия позиции, значения стоп-лосс, тейк-профит и цену открытия каждой позиции. На основе этой информации на графике строятся два прямоугольника: один для области возможных убытков, а другой для области потенциальной прибыли. Если же мы не укажем уровни тейк-профита и стоп-лосса, невозможно будет определить точками привязки этих прямоугольников, и соответственно невозможно будет разместить их на графике. Чтобы такого не случилось, добавим вот такой код.
if(stop_loss > 0) { // Create a rectangle to represent the Stop Loss (SL) zone on the chart ObjectCreate(chart_id, "SL Zone", OBJ_RECTANGLE, 0, position_open_time, open_price, close_zone, stop_loss); } if(take_profit > 0) { // Create a rectangle to represent the Take Profit (TP) zone on the chart ObjectCreate(chart_id, "TP zone", OBJ_RECTANGLE, 0, position_open_time, open_price, close_zone, take_profit); }
Объяснение:
Перед созданием соответствующих прямоугольников на графике этот код проверяет, что уровни Stop Loss и Take Profit больше нуля. Если уровень стоп-лосс установлен (т.е. больше 0), рисуется прямоугольник, представляющий зону SL, отмечающий потенциальную область убытков; если установлен тейк-профит, создается еще один прямоугольник, представляющий зону TP, отмечающий потенциальную область прибыли. Таким образом, с помощью таких проверок мы не даем создать прямоугольники с некорректными опорными точками.
Результат:3.1.2. Создание трендовой линии
Чтобы отобразить движение цены с момента открытия сделки, построим линии тренда от цены открытия позиции до текущей цены. Легко увидеть, как изменился рынок вокруг этих двух точек входа. Это позволяет более тщательно изучить ход торговли.
Пример:// Get the current ask price double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Create a trend line object on the chart from the position's open time and price to the current time and ask price ObjectCreate(chart_id, "Trend Line", OBJ_TREND, 0, position_open_time, open_price, TimeCurrent(), ask); // Set the color of the trend line ObjectSetInteger(chart_id, "Trend Line", OBJPROP_COLOR, clrYellow); // Set the style of the trend line to dashed ObjectSetInteger(chart_id, "Trend Line", OBJPROP_STYLE, STYLE_DASH); // Set the width of the trend line ObjectSetInteger(chart_id, "Trend Line", OBJPROP_WIDTH, 2);
Результат:
3.1.3. Добавление текстовых меток
На этом этапе мы добавим на график четыре отдельные текстовые метки. На этих метках будут отображаться цена входа, тейк-профит (TP), стоп-лосс (SL) и текущая прибыль. Такое представление информации позволит легко отслеживать текущий статус сделки прямо с графика.
Пример:// Variables to store position details double open_price; // Variable to store the entry price of the position double stop_loss; // Variable to store the Stop Loss level of the position double take_profit; // Variable to store the Take Profit level of the position datetime position_open_time; // Variable to store the open time of the position // Define the position index for the first position input int position_index = 1; // POSITION INDEX (Index starts from 0) // Get the ID of the current chart long chart_id = ChartID(); // Store the ID of the current chart string time = "23:59"; // Define a specific time as a string // Define the color for the losing zone input color sl_zonez_color = clrPink; // Choose a color for Losing Zone // Define the color for the winning zone input color tp_zonez_color = clrSpringGreen; // Choose a color for Winning Zone // Define the color for the trend line input color line_zonez_color = clrYellow; // Choose a color for the line //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Get the current ask price double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Convert the string time to datetime datetime close_zone = StringToTime(time); // Loop through all open positions for(int i = 0; i < PositionsTotal(); i++) { // Get the ticket number of the position at index 'i' ulong ticket = PositionGetTicket(i); // Check if the position matches the specified index and symbol of the current chart if(PositionGetInteger(POSITION_TICKET) == PositionGetTicket(position_index) && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { // Retrieve and store the entry price of the position open_price = PositionGetDouble(POSITION_PRICE_OPEN); // Retrieve and store the Stop Loss level of the position stop_loss = PositionGetDouble(POSITION_SL); // Retrieve and store the Take Profit level of the position take_profit = PositionGetDouble(POSITION_TP); // Retrieve and store the open time of the position position_open_time = (int)PositionGetInteger(POSITION_TIME); if(stop_loss > 0) { // Create a rectangle to represent the Stop Loss (SL) zone on the chart ObjectCreate(chart_id, "SL Zone", OBJ_RECTANGLE, 0, position_open_time, open_price, close_zone, stop_loss); } if(take_profit > 0) { // Create a rectangle to represent the Take Profit (TP) zone on the chart ObjectCreate(chart_id, "TP zone", OBJ_RECTANGLE, 0, position_open_time, open_price, close_zone, take_profit); } // Set properties for the SL zone rectangle ObjectSetInteger(chart_id, "SL Zone", OBJPROP_COLOR, sl_zonez_color); // Set color to the selected SL zone color ObjectSetInteger(chart_id, "SL Zone", OBJPROP_STYLE, STYLE_SOLID); // Set style to solid ObjectSetInteger(chart_id, "SL Zone", OBJPROP_WIDTH, 1); // Set the width of the rectangle border ObjectSetInteger(chart_id, "SL Zone", OBJPROP_FILL, sl_zonez_color); // Fill the rectangle with the selected SL zone color ObjectSetInteger(chart_id, "SL Zone", OBJPROP_BACK, true); // Set the rectangle to appear behind the chart objects // Set properties for the TP zone rectangle ObjectSetInteger(chart_id, "TP zone", OBJPROP_COLOR, tp_zonez_color); // Set color to the selected TP zone color ObjectSetInteger(chart_id, "TP zone", OBJPROP_STYLE, STYLE_SOLID); // Set style to solid ObjectSetInteger(chart_id, "TP zone", OBJPROP_WIDTH, 1); // Set the width of the rectangle border ObjectSetInteger(chart_id, "TP zone", OBJPROP_FILL, tp_zonez_color); // Fill the rectangle with the selected TP zone color ObjectSetInteger(chart_id, "TP zone", OBJPROP_BACK, true); // Set the rectangle to appear behind the chart objects // Create a trend line object on the chart from the position's open time and price to the current time and ask price ObjectCreate(chart_id, "Trend Line", OBJ_TREND, 0, position_open_time, open_price, TimeCurrent(), ask); // Set Trend Line properties ObjectSetInteger(chart_id, "Trend Line", OBJPROP_COLOR, line_zonez_color); ObjectSetInteger(chart_id, "Trend Line", OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(chart_id, "Trend Line", OBJPROP_WIDTH, 2); // Calculate the profit of the current position double profit = PositionGetDouble(POSITION_PROFIT); // Variables to store the formatted profit text string curent_profits; string profit_to_string; // Check if the profit is positive or zero if(profit >= 0) { // Convert the profit to a string with 2 decimal places profit_to_string = DoubleToString(profit, 2); // Format the profit as a positive amount with a '+' sign curent_profits = StringFormat("+$%s", profit_to_string); } // Check if the profit is negative else if(profit < 0) { // Convert the negative profit to a positive number double profit_to_positive = MathAbs(profit); // Convert the positive profit to a string with 2 decimal places profit_to_string = DoubleToString(profit_to_positive, 2); // Format the profit as a negative amount with a '-' sign curent_profits = StringFormat("-$%s", profit_to_string); } // Create a text label on the chart to display the current profit string text_object_name = "Profit"; ObjectCreate(chart_id, text_object_name, OBJ_TEXT, 0, TimeCurrent(), ask); ObjectSetString(chart_id, text_object_name, OBJPROP_TEXT, curent_profits); // Set the color of the profit text based on whether the profit is positive or negative if(profit > 0) { ObjectSetInteger(chart_id, text_object_name, OBJPROP_COLOR, clrMediumBlue); // Positive profit in blue } else if(profit < 0) { ObjectSetInteger(chart_id, text_object_name, OBJPROP_COLOR, clrRed); // Negative profit in red } // Display the Take Profit (TP) level on the chart string tp_display = "TP"; string t_display = StringFormat("Take Profit: %.5f", take_profit); ObjectCreate(chart_id, tp_display, OBJ_TEXT, 0, close_zone, take_profit); ObjectSetString(chart_id, tp_display, OBJPROP_TEXT, t_display); ObjectSetInteger(chart_id, tp_display, OBJPROP_COLOR, clrBlue); // TP text in blue ObjectSetInteger(chart_id, tp_display, OBJPROP_FONTSIZE, 8); // Set font size for TP // Display the Stop Loss (SL) level on the chart string sl_display = "SL"; string s_display = StringFormat("Stop Loss: %.5f", stop_loss); ObjectCreate(chart_id, sl_display, OBJ_TEXT, 0, close_zone, stop_loss); ObjectSetString(chart_id, sl_display, OBJPROP_TEXT, s_display); ObjectSetInteger(chart_id, sl_display, OBJPROP_COLOR, clrRed); // SL text in red ObjectSetInteger(chart_id, sl_display, OBJPROP_FONTSIZE, 8); // Set font size for SL // Display the Entry Price on the chart string en_display = "Entry Price"; string e_display = StringFormat("Entry Point: %.5f", open_price); ObjectCreate(chart_id, en_display, OBJ_TEXT, 0, close_zone, open_price); ObjectSetString(chart_id, en_display, OBJPROP_TEXT, e_display); ObjectSetInteger(chart_id, en_display, OBJPROP_COLOR, clrPaleVioletRed); // Entry Price text in pale violet red ObjectSetInteger(chart_id, en_display, OBJPROP_FONTSIZE, 8); // Set font size for Entry Price } } }
Объяснение:
В коде выше реализовано выбранных данных о сделке непосредственно на графике. Здесь производится расчет текущей прибыли по позиции, которая затем представляется ее в виде текстовых меток с информацией, отображаемой красным цветом в случае убытка и синим в случае прибыли. Чтобы визуально различать уровни тейк-профита и лосса, а также цену входа, мы также добавляем соответствующие текстовые метки. Для меток используются разные цвета. При размещении на графике такая информация помогает трейдерам быстро определить основные уровни и текущую прибыльность своей позиции.
Результат:3.2. Создание объектов для исторических данных
До сих пор в главе 3 мы рассматривали создание объектов, основанных на текущем положении. Теперь поработаем с историческими данными, чтобы отобразить на графике историю торговли. Это позволит изучать предыдущие сделки и строить новые планы на основе исторических знаний.
Пример:// Define the position index for the first position input int position_index = 1; // POSITION INDEX (Index starts from 0) // Get the ID of the current chart long chart_id = ChartID(); // Store the ID of the current chart string time = "23:59"; // Define a specific time as a string // Define the color for the losing zone input color sl_zonez_color = clrPink; // Choose a color for Losing Zone // Define the color for the winning zone input color tp_zonez_color = clrSpringGreen; // Choose a color for Winning Zone // Define the color for the trend line input color line_zonez_color = clrYellow; // Choose a color for the line // Define whether to show past history or not input string show_history = "no"; // Type yes to show past history // Define the start date to show history input datetime date1 = D'1970.08.10 00:00:00'; // Show history from this date // Define the end date to show history input datetime date2 = D'2024.08.15 00:00:00'; // To this date //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check if history display is enabled if(show_history == "yes") { Comment(""); // Clear previous comments // Select deal history within the specified date range bool deal_history = HistorySelect(date1, date2); // Variables to store deal details double deal_close_price = 0.0; double deal_open_price = 0.0; double deal_sl = 0.0; double deal_tp = 0.0; double deal_profit = 0.0; datetime deal_close_time = 0; datetime deal_open_time = 0; // Check if deal history is available if(deal_history) { // Loop through all history deals for(int i = 0; i < HistoryDealsTotal(); i++) { ulong ticket = HistoryDealGetTicket(i); // Check for deal entry in if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_IN) { if(HistoryDealGetString(ticket, DEAL_SYMBOL) == ChartSymbol(chart_id)) { deal_open_price = HistoryDealGetDouble(ticket, DEAL_PRICE); deal_open_time = (datetime)HistoryDealGetInteger(ticket, DEAL_TIME); } } // Check for deal entry out if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT) { deal_profit = HistoryDealGetDouble(ticket, DEAL_PROFIT); deal_close_price = HistoryDealGetDouble(ticket, DEAL_PRICE); deal_sl = HistoryDealGetDouble(ticket, DEAL_SL); deal_tp = HistoryDealGetDouble(ticket, DEAL_TP); deal_close_time = (datetime)HistoryDealGetInteger(ticket, DEAL_TIME); if(HistoryDealGetString(ticket, DEAL_SYMBOL) == ChartSymbol(chart_id)) { string deal_string; string current_deal_profit; string object_name; // Display deal profit/loss if(deal_profit > 0) { deal_string = DoubleToString(deal_profit, 2); current_deal_profit = StringFormat("YOU WON +$%s", deal_string); object_name = StringFormat("PROFIT %d", i); ObjectCreate(chart_id, object_name, OBJ_TEXT, 0, deal_close_time, deal_close_price); ObjectSetString(chart_id, object_name, OBJPROP_TEXT, current_deal_profit); ObjectSetInteger(chart_id, object_name, OBJPROP_COLOR, clrMediumBlue); ObjectSetInteger(chart_id, object_name, OBJPROP_FONTSIZE,8); } else if(deal_profit < 0) { double deal_to_positive = MathAbs(deal_profit); deal_string = DoubleToString(deal_to_positive, 2); object_name = StringFormat("PROFIT %d", i); current_deal_profit = StringFormat("YOU LOST -$%s", deal_string); ObjectCreate(chart_id, object_name, OBJ_TEXT, 0, deal_close_time, deal_close_price); ObjectSetString(chart_id, object_name, OBJPROP_TEXT, current_deal_profit); ObjectSetInteger(chart_id, object_name, OBJPROP_COLOR, clrRed); ObjectSetInteger(chart_id, object_name, OBJPROP_FONTSIZE,8); } // Display deal SL zone string sl_obj_name = StringFormat("SL ZONE %d", i); if(deal_sl > 0) { ObjectCreate(chart_id, sl_obj_name, OBJ_RECTANGLE, 0, deal_open_time, deal_open_price, deal_close_time, deal_sl); } ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_COLOR, sl_zonez_color); ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_WIDTH, 1); ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_FILL, sl_zonez_color); ObjectSetInteger(chart_id, sl_obj_name, OBJPROP_BACK, true); // Display deal TP zone string tp_obj_name = StringFormat("TP ZONE %d", i); if(deal_tp > 0) { ObjectCreate(chart_id, tp_obj_name, OBJ_RECTANGLE, 0, deal_open_time, deal_open_price, deal_close_time, deal_tp); } ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_COLOR, tp_zonez_color); ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_WIDTH, 1); ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_FILL, tp_zonez_color); ObjectSetInteger(chart_id, tp_obj_name, OBJPROP_BACK, true); // Display deal trend line string line_obj_name = StringFormat("line %d", i); ObjectCreate(chart_id, line_obj_name, OBJ_TREND, 0, deal_open_time, deal_open_price, deal_close_time, deal_close_price); ObjectSetInteger(chart_id, line_obj_name, OBJPROP_COLOR, line_zonez_color); ObjectSetInteger(chart_id, line_obj_name, OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(chart_id, line_obj_name, OBJPROP_WIDTH, 2); } } } } } }
Объяснение:
Этот фрагмент кода сначала проверяет переменную show_history, чтобы выяснить, включена ли функция отображения истории. Если выбрано значение "yes", код использует Comment(""), чтобы удалить любые предыдущие комментарии с графика, оставив только самые последние данные. Результат сохраняется в булевой переменной deal_history. Затем вызывается метод HistorySelect(date1, date2) для выбора исторических сделок в заданном диапазоне дат. Это позволяет использовать данные о прошлых сделках. Информация о каждой предыдущей сделке затем сохраняется в различных переменных. Цена закрытия и открытия сделки записываются в переменные deal_close_price и deal_open_price. Переменные deal_sl и deal_tp используются для записи значений Take Profit и Stop Loss. Переменные deal_close_time и deal_open_time фиксируют моменты закрытия и открытия сделки, а deal_profit отслеживает прибыль или убыток по сделке.
Далее код проверяет, доступна ли история сделок. Если доступна, начинается цикл, который использует HistoryDealGetTicket(i) для получения номера тикета каждой сделки при итерации по всем возможным сделкам. Для каждого тикета код различает входные и выходные сделки. В выходных сделках извлекаются данные о цене закрытия, прибыли, стоп-лоссе и тейк-профите, а в сделках на вход — информация о цене открытия и времени. Эти данные используются для создания различных объектов на графике, таких как трендовые линии, которые показывают движение цены во время сделки, текстовые метки, которые указывают на прибыль или убыток, и прямоугольники, представляющие зоны для тейк-профита и стоп-лосса. Этот метод обеспечивает эффективное отображение исторических данных о сделках на экране, предоставляя важные сведения о предыдущей торговой деятельности.
Результат:
Заключение
В этой статье мы рассмотрели работу с объектами в MQL5. В частности, мы научились создавать и изменять элементы графика для улучшения анализа торговли. Мы научились создавать прямоугольников для зон тейк-профита и стоп-лосса, линии тренда для отслеживания изменений цен и текстовых меток для важных торговых данных. Мы также разобрали, как отображать предыдущие сделки с помощью меток и визуальных средств, чтобы отобразить на графике историю торговли.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/15764





