preview
Разрабатываем мультивалютный советник (Часть 27): Компонент для вывода многострочного текста

Разрабатываем мультивалютный советник (Часть 27): Компонент для вывода многострочного текста

MetaTrader 5Примеры |
437 0
Yuriy Bykov
Yuriy Bykov

Содержание


Введение

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

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

В прошлый раз мы написали реализацию расчётной части, к которой не предъявлялось каких либо жестких требований по эффективности. Для вывода результатов расчётов мы воспользовались двумя простейшими способами, доступными "из коробки". Первый — это использование стандартной функции Comment(), которая отображает переданный текст прямо на графике. Второй — использование другой стандартной функции Print() для вывода текста в журнал советников. Это весьма удобно для простых задач.

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

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


Намечаем путь

Перечислим наши пожелания, которые хотелось бы реализовать:

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

  • Прокрутка текста — если весь текст не помещается в пределах доступной области для вывода, то при помощи колеса мыши можно осуществлять вертикальную и горизонтальную (при нажатой клавише Shift) прокрутку. Отображение полос прокрутки пока делать не будем, возможно добавим их позднее.

  • Изменение размера шрифта — с помощью клавиши Ctrl + колесом мыши можно уменьшать и увеличивать размер шрифта, используемого для вывода текста. 

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

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

  • Сворачивание — возможность минимизации и максимизации области вывода.

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


Класс CConsoleDialog

Создадим новый класс, назвав его CConsoleDialog. Сделаем его наследником существующего класса стандартной библиотеки CAppDialog, так как в этом родительском классе есть уже довольно много из того, что мы запланировали реализовать. Например, отображение окна с кнопками сворачивания/разворачивания и закрытия приложения советника уже готово. Нам остаётся позаботиться о внутреннем наполнении клиентской области окна — именно там будет выводиться текст.

Для вывода текста будем использовать объект класса CCanvas для отрисовки текста, а поддержка прокрутки и изменения размера шрифта будет реализована через обработку событий графика.

Вот как будет выглядеть описание нового класса:

//+------------------------------------------------------------------+
//| Класс диалогового окна на весь экран                             |
//| для вывода многострочного текста                                 |
//+------------------------------------------------------------------+
class CConsoleDialog : public CAppDialog {
protected:
   CCanvas           m_canvas;         // Объект холста для вывода текста

   string            m_lines[];        // Массив строк текста
   string            m_text;           // Текст для вывода в диалоговом окне

   int               m_startRow;       // Начальная строка видимого текста
   int               m_startCol;       // Начальный столбец (символ) видимого текста

   int               m_totalRows;      // Общее число строк текста
   int               m_totalCols;      // Общее число символов в самой длинной строке текста

   int               m_visibleRows;    // Максимальное количество видимых строк
   int               m_visibleCols;    // Максимальное количество видимых символов в строке

   string            m_fontName;          // Название шрифта для текста
   int               m_fontSize;          // Размер шрифта
   uint              m_fontColor;         // Цвет шрифта

   int               m_fontSymbolWidth;   // Ширина одного символа в пикселях
   int               m_fontSymbolHeight;  // Высота строки текста в пикселях

   uint              m_backgroundColor;   // Цвет фона

   bool              m_mouseWheel;        // Предыдущее состояние отслеживания событий прокрутки мышью

   bool              CreateCanvas();      // Создание холста
   void              UpdateCanvas();      // Вывод текста на холсте
   void              UpdateCanvasFont();  // Изменение шрифта холста

public:
                     CConsoleDialog();       // Конструктор
                    ~CConsoleDialog(void);   // Деструктор

   // Методы создания диалогового окна
   bool              Create(string name);
   virtual bool      Create(const long chart, const string name, const int subwin,
                            const int x1, const int y1, const int x2, const int y2);
   // Обработка событий
   virtual void      ChartEvent(const int id, const long &lparam,
                                const double &dparam, const string &sparam);

   virtual void      Minimize();             // Минимизация диалогового окна
   virtual void      Maximize();             // Максимизация диалогового окна

   virtual void      Text(string text);      // Установка нового текста

   virtual void      FontName(string p_fontName);  // Установка названия шрифта
   virtual bool      FontSize(int p_fontSize);     // Установка размера шрифта
   virtual void      FontColor(uint p_fontColor);  // Установка цвета шрифта

   // Установка цвета фона
   virtual void      BackgroundColor(uint p_backgroundColor);
};

Из всех перечисленных публичных методов мы, пока что, будем пользоваться в основном методом установки нового текста Text() и первым вариантом метода Create(), позволяющего создать диалоговое окно, указав только его имя. Оно же будет использовано в качестве надписи в заголовке окна. 


Конструктор и деструктор

При создании объекта класса CConsoleDialog, конструктор инициализирует шрифт по умолчанию — это моноширинный шрифт "Consolas" размером 13, с цветом текста, установленным в чёрный с небольшой прозрачностью. Такой шрифт выбран для того, чтобы можно было выводить табличные данные в виде текста, и они выглядели бы именно как таблицы с ровными столбцами. Если же шрифт будет не моноширинный, то ровных таблиц уже не получится.

Размер шрифта в 13 пикселей, с одной стороны, достаточно мал, чтобы отобразить большой объём текста, а с другой стороны, ещё не настолько мал, чтобы стать нечитаемым. С учётом запланированной возможности лёгкого изменения размера, выбор конкретного начального значения не играет особой роли. Цвет фона делается прозрачным, поэтому сквозь холст мы будем видеть стандартный серый цвет фона, используемый в классе CDialog.

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

//+------------------------------------------------------------------+
//| Конструктор                                                      |
//+------------------------------------------------------------------+
CConsoleDialog::CConsoleDialog() :
   m_fontName("Consolas"),
   m_fontSize(13),
   m_fontColor(ColorToARGB(clrBlack, 240)),
   m_backgroundColor(ColorToARGB(clrBlack, 0)) {
   FontSize(m_fontSize);
}

//+------------------------------------------------------------------+
//| Деструктор                                                       |
//+------------------------------------------------------------------+
CConsoleDialog::~CConsoleDialog() {
// Удаляем холст
   m_canvas.Destroy();

// Возвращаем прежнюю настройку обработки событий прокрутки мышью
   ChartSetInteger(m_chart_id, CHART_EVENT_MOUSE_WHEEL, (long)m_mouseWheel);
}


Создание диалогового окна

Для создания окна существует два варианта метода Create(). Первый вариант принимает только имя окна и автоматически задаёт позицию и размеры окна на весь экран графика с небольшим верхним отступом. Этот метод вычисляет размеры графика и вызывает второй вариант Create() с конкретными координатами.

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

//+------------------------------------------------------------------+
//| Метод создания диалогового окна только по имени                  |
//+------------------------------------------------------------------+
bool CConsoleDialog::Create(string name) {
// Устанавливаем положение угла и размеры окна
   int x1 = 0;
   int y1 = DIALOG_VERTICAL_MARGIN;
   int y2 = (int) ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0);
   int x2 = (int) ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0);

// Вызываем метод создания по заданным размерам
   return Create(0, name, 0, x1, y1, x2, y2);
}

//+------------------------------------------------------------------+
//| Метод создания диалогового окна                                  |
//+------------------------------------------------------------------+
bool CConsoleDialog::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) {
// Вызов родительского метода создания диалога
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) {
      return false;
   }

// Устновка размеров минимизированного окна диалога
   m_min_rect.SetBound(0, DIALOG_VERTICAL_MARGIN,
                       250, DIALOG_VERTICAL_MARGIN + CONTROLS_DIALOG_MINIMIZE_HEIGHT);

// Создание холста
   if(!CreateCanvas()) {
      return false;
   }

// Запоминаем прежнюю настройку обработки событий прокрутки мышью
   m_mouseWheel = ChartGetInteger(0, CHART_EVENT_MOUSE_WHEEL);

// Устанавливаем отслеживание событий прокрутки мышью
   ChartSetInteger(chart, CHART_EVENT_MOUSE_WHEEL, 1);

// Устанавливаем начальное положение текста в окне
   m_startRow = 0;
   m_startCol = 0;

   return true;
}

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


Обработка событий

Метод ChartEvent() отвечает за обработку различных событий графика. В основном, мы будем обрабатывать события прокрутки колесика мыши (CHARTEVENT_MOUSE_WHEEL). Если окно не минимизировано, происходит проверка нажатых клавиш: при зажатом Shift, происходит горизонтальная прокрутка текста, если текст по ширине превышает видимый диапазон; при отсутствии дополнительных клавиш — вертикальная прокрутка при превышении по высоте; а при зажатом Ctrl, можно изменять размер шрифта, масштабируя текст. В случае изменения размеров графика, метод автоматически адаптирует размеры окна, разворачивая его на всю доступную площадь при необходимости. Все остальные события обрабатываются в базовом классе CAppDialog.

//+------------------------------------------------------------------+
//| Обработка событий                                                |
//+------------------------------------------------------------------+
void CConsoleDialog::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {
// Обработка события прокрутки колёсика мыши
   if(id == CHARTEVENT_MOUSE_WHEEL) {
      // Если окно диалога минимизировано, то не обрабатываем это событие
      if(m_minimized) {
         return;
      }

      // Разбираем состояние кнопок и колесика мышки для этого события
      int flg_keys = (int)(lparam >> 32);       // флаг состояний клавиш Ctrl, Shift и кнопок мышки
      int delta    = (int)dparam;               // суммарное значение прокрутки колесика, 
                                                // срабатывает при достижении +120 или -120

      // Если нажата клавиша SHIFT, то
      if((flg_keys & 0x0004) != 0) {
         // Если количество символов в строке больше количества видимых
         // символов в диалоге, то выполняем горизонтальное смещение
         if(m_totalCols > m_visibleCols) {
            // На одно событие прокрутки будем смещаться на 2 символа (120 / 60 = 2)
            delta /= 60;

            // Если новая начальная позиция попадает в допустимый диапазон, то
            if(m_startCol - delta >= 0
                  && m_startCol - delta <= m_totalCols - m_visibleCols + 2) {
               // Запоминаем новую начальную позицию
               m_startCol -= delta;

               // Обновляем холст
               UpdateCanvas();
            }
         }
      } else if (flg_keys == 0) {
         // Иначе если количество строк текста больше количества видимых
         // строк в диалоге, то выполняем вертикальное смещение
         if(m_totalRows > m_visibleRows) {
            // На одно событие прокрутки будем смещаться на 1 строку (120 / 120 = 1)
            delta /= 120;

            // Если новая начальная позиция попадает в допустимый диапазон, то
            if(m_startRow - delta >= 0
                  && m_startRow - delta <= m_totalRows - m_visibleRows + 1) {
               // Запоминаем новую начальную позицию
               m_startRow -= delta;

               // Обновляем холст
               UpdateCanvas();
            }
         }
      } else if((flg_keys & 0x0008) != 0) {
         // Иначе если нажата клавиша CTRL, то пробуем установить новый размер шрифта
         if(FontSize(m_fontSize + delta / 120)) {
            // Обновляем холст
            UpdateCanvas();
         }
      }

      return;
   }

// Обработка события изменения графика
   if(id == CHARTEVENT_CHART_CHANGE) {
      // Если размеры отображаемой области изменились
      if(m_chart.HeightInPixels(m_subwin) != Height() + DIALOG_VERTICAL_MARGIN
            || m_chart.WidthInPixels() != Width()) {
         // Установить для диалогового окна новые размеры
         m_norm_rect.SetBound(0, DIALOG_VERTICAL_MARGIN, m_chart.WidthInPixels(), m_chart.HeightInPixels(m_subwin));

         // Если окно диалога не минимизировано, то
         if(!m_minimized) {
            // Разворачивем его на полный экран графика с новыми размерами
            Maximize();
         }
         return;
      }
   }

// Обработка отсальных событий в вышестоящем классе
   CAppDialog::ChartEvent(id, lparam, dparam, sparam);
}

Поскольку в этом диалоге мы не используем компоненты, являющиеся наследниками класса CWndObj, то мы не можем воспользоваться стандартными макросами для создания функции OnEvent(), в которой происходит связывание событий компонентов диалога и их функций-обработчиков. Используемый нами компонент CCanvas вынуждает использовать именно общий обработчик событий графика ChartEvent().


Сворачивание

При минимизации окна методом Minimize(), происходит уничтожение холста, что освобождает используемые ресурсы. После этого, вызывается базовая реализация для изменения состояния окна. Аналогично, при максимизации методом Maximize(), сначала вызывается родительский метод, который разворачивает окно, после чего, создаётся холст и обновляется отображение текста, чтобы обеспечить корректный вывод с учётом новых размеров клиентской области.

//+------------------------------------------------------------------+
//| Минмизация диалогового окна                                      |
//+------------------------------------------------------------------+
void CConsoleDialog::Minimize() {
// Удаляем холст
   m_canvas.Destroy();

// Вызываем родительский метод минимизации
   CAppDialog::Minimize();
}

//+------------------------------------------------------------------+
//| Максимизация диалогового окна                                    |
//+------------------------------------------------------------------+
void CConsoleDialog::Maximize() {
// Вызываем родительский метод максимизации
   CAppDialog::Maximize();

// Создаём холст
   CreateCanvas();

// Выводим текст на холсте
   UpdateCanvas();
}

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


Работа с текстом

Для установки или изменения отображаемого текста, используется метод Text(). Он проверяет, отличается ли новый текст от текущего. Если да, то исходная строка разбивается на массив строк по символу переноса строки '\n'. После этого, сохраняется количество строк и определяется максимальная длина самой длинной строки. Эти данные необходимы для правильной организации прокрутки и отображения. Затем вызывается обновление холста, чтобы отобразить новый текст.

//+------------------------------------------------------------------+
//| Установка текста                                                 |
//+------------------------------------------------------------------+
void CConsoleDialog::Text(string text) {
// Если текст изменяется, то
   if(text != m_text) {
      // Запомним новый тект
      m_text = text;

      // Делим текст на строки
      StringSplit(m_text, '\n', m_lines);

      // Запоминаем количество строк
      m_totalRows = ArraySize(m_lines);

      // Определяем максимальную длину строк
      m_totalCols = 0;
      FOREACH(m_lines) {
         m_totalCols = MathMax(m_totalCols, StringLen(m_lines[i]));
      }

      // Выводим текст на холсте
      UpdateCanvas();
   }
}


Настройка шрифта и цвета

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

Изменение размера шрифта реализовано в методе FontSize(), который принимает новое значение и проверяет, что оно находится в разумных пределах (от 8 до 72). При успешном изменении сбрасывается позиция прокрутки на начало текста, а параметры шрифта холста обновляются в соответствии с новым значением размера. Также для нового размера вычисляются и сохраняются значения ширины и высоты одного символа для правильного расчёта видимой части текста.

Метод FontColor() позволяет установить цвет шрифта.

//+------------------------------------------------------------------+
//| Установка названия шрифта                                        |
//+------------------------------------------------------------------+
void CConsoleDialog::FontName(string p_fontName) {
// Запоминаем новое имя шрифта
   m_fontName = p_fontName;

// Обновляем шрифт холста
   UpdateCanvasFont();
}

//+------------------------------------------------------------------+
//| Установка размера шрифта                                         |
//+------------------------------------------------------------------+
bool CConsoleDialog::FontSize(int p_fontSize) {
// Если размер находится в разумных пределах, то
   if (p_fontSize >= 8 && p_fontSize <= 72) {
      // Запоминаем новый размер шрифта
      m_fontSize = p_fontSize;

      // Сбрасываем начальную строку и столбец
      m_startRow = 0;
      m_startCol = 0;

      // Обновляем шрифт холста
      UpdateCanvasFont();

      return true;
   }

   return false;
}

//+------------------------------------------------------------------+
//| Установка цвета шрифта                                           |
//+------------------------------------------------------------------+
void CConsoleDialog::FontColor(uint p_fontColor) {
   m_fontColor = p_fontColor;
}


Работа с холстом

За создание холста отвечает метод CreateCanvas(), который инициализирует объект CCanvas с размерами клиентской области диалогового окна и задаёт формат цвета с альфа-каналом. При успешном создании холста, сразу устанавливается шрифт и параметры символов. Метод UpdateCanvas() отвечает за непосредственную отрисовку текста на холсте: он очищает фон, после чего выводит видимые строки, учитывая текущие позиции прокрутки по строкам и символам. Для каждой видимой строки производится обрезка начала строки при необходимости, а текст выводится с небольшими отступами от краёв. После завершения отрисовки, вызывается обновление холста, чтобы изменения стали видны пользователю.

Наконец, метод UpdateCanvasFont() обновляет параметры шрифта на холсте, вычисляет размеры одного символа на основе буквы "M" и рассчитывает, сколько строк и символов можно уместить в текущих размерах окна, что необходимо для организации прокрутки.

//+------------------------------------------------------------------+
//| Создание холста                                                  |
//+------------------------------------------------------------------+
bool CConsoleDialog::CreateCanvas() {
// Получаем размеры клиентской области диалогового окна
   int height = ClientAreaHeight();
   int width = ClientAreaWidth();

// Если размеры ненулевые
   if(height > 0 && width > 0) {
      // Если при создании холста возникла ошибка, то выходим
      if(!m_canvas.CreateBitmapLabel("display",
                                     ClientAreaLeft(),
                                     ClientAreaTop(),
                                     ClientAreaWidth(),
                                     ClientAreaHeight(),
                                     COLOR_FORMAT_ARGB_NORMALIZE)) {
         PrintFormat(__FUNCTION__" | ERROR: Creating canvas %d", GetLastError());
         return false;
      }

      UpdateCanvasFont();
   }

   return true;
}

//+------------------------------------------------------------------+
//| Вывод текста на холсте                                           |
//+------------------------------------------------------------------+
void CConsoleDialog::UpdateCanvas() {
// Стираем холст цветом фона
   m_canvas.Erase(m_backgroundColor);

// Для каждой строки, попадающей в видимый диапазон
   for (int i = m_startRow; i < MathMin(m_totalRows, m_startRow + m_visibleRows); i++) {
      // Берём очередную строку текста
      string line = m_lines[i];

      // Если её надо показывать не с первого символа, то
      if (m_startCol > 0) {
         // Вырезаем начальные символы
         line = StringSubstr(line, m_startCol);
      }

      // Выводим строку на холст
      m_canvas.TextOut(5, 5 + (i - m_startRow) * m_fontSymbolHeight, line, m_fontColor, TA_LEFT | TA_TOP);
   }

// Вызываем метод отрисовки холста на экране
   m_canvas.Update(true);
}

//+------------------------------------------------------------------+
//| Изменение шрифта холста                                          |
//+------------------------------------------------------------------+
void CConsoleDialog::UpdateCanvasFont() {
// Установка параметров шрифта для вывода текста на холст
   m_canvas.FontSet(m_fontName, m_fontSize);

// Установка новых размеров одного символа
   m_canvas.TextSize("M", m_fontSymbolWidth, m_fontSymbolHeight);

// Определяем количество видимых строк и символов в строке (столбцов)
   m_visibleRows = ClientAreaHeight() / m_fontSymbolHeight;
   m_visibleCols = ClientAreaWidth() / m_fontSymbolWidth;
}

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


Подключаем компонент

Для того, чтобы выводить текст на графике с использованием нового компонента, откроем файл советника-информера. Первым делом подключим созданный библиотечный файл:

#include "ConsoleDialog.mqh"

Затем, создадим глобальный объект диалога:

CConsoleDialog *dialog;

В методе Init() перед запуском расчёта и отображения добавим команды создания и запуска диалога:

//+------------------------------------------------------------------+
//| Инициализация советника                                          |
//+------------------------------------------------------------------+
int OnInit(void) {
// ...

// Создаём и запускаем диалог для вывода результатов
   dialog = new CConsoleDialog();
   dialog.Create("Symbols Informer");
   dialog.Run();

// Выполняем принудительный перерасчёт
   Calculate(true);

// Показываем результаты
   Show();

   return(INIT_SUCCEEDED);
}

И наконец, в функции Show() заменяем вызов функции Comment() на установку текста с результатами нашему диалогу:

//+------------------------------------------------------------------+
//| Показ результатов                                                |
//+------------------------------------------------------------------+
void Show() {
// Получаем результаты в виде текста
   string text = TextComment();

// Показываем его на графике в диалоговом окне
   dialog.Text(text);
}

Сохраним сделанные изменения в файле SymbolsInformer.mq5 в папке проекта.


Тестирование

Запустим советник-информер с параметрами по умолчанию. Поскольку теперь работает и прокрутка, и изменение размера текста, то можно спокойно подобрать наиболее комфортный размер и нужную видимую область результатов.

Если нас интересуют, например, только данные по среднему размеру свечей для EURUSD M30, то можно сделать такое отображение, увеличив размер шрифта:

Если же мы хотим сразу видеть все значения для GBPUSD и EURGBP, то можно снова уменьшить шрифт и прокрутить текст ниже:

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

Например, в недавней статье Арбитражный трейдинг Forex: Матричная торговая система на возврат к справедливой стоимости с ограничением риска, её автор приводит пример как раз такого советника:

Внеся в его исходный код небольшие изменения, которые описаны в разделе про подключение компонента, получаем такую картину:

В таком виде воспринимать информацию гораздо удобнее и приятнее.


Заключение

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

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

Спасибо за внимание, до встречи!


Важное предупреждение

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


Содержание архива

#
 Имя
Версия  Описание   Последние изменения
  SymbolsInformer   Рабочая папка проекта  
1 SymbolsInformer.mq5 1.01
Советник для вывода информации о длинах серий однонаправленных свечей
Часть 27
2 CConsoleDialog.mqh 1.00   Часть 27
3 AbbyCross.mq5 Пример файла стороннего советника с подключенным классом CConsoleDialog
  SymbolsInformer/Include/Adwizard/Utils
  Вспомогательные утилиты, макросы для сокращения кода
 
4 Macros.mqh
1.07 Полезные макросы для операций с массивами
Часть 26
5 NewBarEvent.mqh  1.00  Класс определения нового бара для конкретного символа  Часть 8
Также исходный код доступен в публичных репозиториях SymbolsInformer и Adwizard.
Прикрепленные файлы |
MQL5.zip (19.76 KB)
Изучаем конформное прогнозирование финансовых временных рядов Изучаем конформное прогнозирование финансовых временных рядов
В этой статье вы познакомитесь с конформными предсказаниями и библиотекой MAPIE, которая их реализует. Данный подход является одним из самых современных в машинном обучении и позволяет сосредоточиться на контроле рисков для уже существующих разнообразных моделей машинного обучения. Конформные предсказания, сами по себе, не являются способом поиска закономерностей в данных. Они лишь определяют степень уверенности существующих моделей в предсказании конкретных примеров и позволяют фильтровать надежные предсказания.
Помощник Connexus (Часть 5): HTTP-методы и коды состояния Помощник Connexus (Часть 5): HTTP-методы и коды состояния
В настоящей статье мы разберемся с методами HTTP и кодами состояния, двумя очень важными элементами взаимодействия между клиентом и сервером в Интернете. Понимание того, что каждый метод действительно дает возможность более точно делать запросы, информируя сервер о том, какое действие надо выполнить, и делая его более эффективным.
Трейдинг с экономическим календарем MQL5 (Часть 1): Освоение функций экономического календаря MQL5 Трейдинг с экономическим календарем MQL5 (Часть 1): Освоение функций экономического календаря MQL5
В этой статье мы рассмотрим, как использовать экономический календарь MQL5 для торговли, сначала разобравшись с его основными функциями. Затем мы реализуем ключевые функции экономического календаря в MQL5 для извлечения необходимых новостей для принятия торговых решений. Наконец, мы посмотрим, как использовать эту информацию для эффективного совершенствования торговых стратегий.
От начального до среднего уровня: Объединение (II) От начального до среднего уровня: Объединение (II)
Сегодня нас ждет очень забавная и довольно интересная статья, причем в нескольких аспектах. В ней мы рассмотрим объединение, чтобы решить проблему, о которой говорилось ранее. Кроме того, мы изучим некоторые необычные ситуации, которые могут возникнуть при использовании объединения в приложениях. Представленные здесь материалы предназначены исключительно для образовательных целей. Ни в коем случае нельзя рассматривать приложение ни с какой иной целью, кроме как для изучения и освоения представленных концепций.