Система аудита счета в MQL5 (Часть 1): Проектирование пользовательского интерфейса
Введение
Трейдеры и разработчики на MQL5 регулярно проводят «аудит» счёта: вручную просматривают историю сделок, подсчитывают количество прибыльных и убыточных сделок и оценивают результаты за неделю или месяц. При этом зачастую отсутствует единое постоянное представление данных, которое всегда присутствует прямо на графике. Попытки вывести такие показатели на график нередко приводят к двум практическим проблемам: интерфейс получается статичным и навязчивым, а также может мешать работе функций терминала, например торговле в один клик, нарушая привычный рабочий процесс трейдера.
В этой статье мы сузим рамки задачи и рассмотрим её с инженерной точки зрения: создадим слой пользовательского интерфейса системы аудита счёта в виде пользовательского индикатора MQL5. На данном этапе мы не будем реализовывать расчеты аудита или хранение данных. Наша цель — создать компактную панель на графике, которая отображает основные поля аудита (начальный и конечный баланс, чистую прибыль, количество сделок, прибыльные и убыточные сделки, процент прибыльных сделок, выведенные средства и оценку эффективности) и которую пользователь может отображать и скрывать без побочных эффектов и нарушения работы терминала. Индикатор проектируется с учетом удобства сопровождения: используются именованные константы, отдельная структура данных для показателей, модульные вспомогательные функции интерфейса и событийный механизм отображения и скрытия панели. Благодаря этому панель корректно интегрируется с терминалом и не мешает работе режима торговли в один клик.
Такой целенаправленный подход позволяет заранее проверить представление данных, модель взаимодействия и работу с объектами графика. Созданный интерфейс станет готовой к подключению интерфейсной основой для механизма аудита, слоя хранения данных и подсистемы уведомлений, которые будут разработаны в следующих частях.
Обзор проекта
Прежде чем переходить к реализации, важно наглядно представить, что именно мы собираемся создать.
Система рассчитана на регулярный цикл оценки и автоматически формирует структурированные отчёты аудита еженедельно или ежемесячно — в зависимости от настроек пользователя. Вместо ручной проверки система непрерывно анализирует последний оцениваемый интервал, обеспечивая последовательную и объективную оценку результатов счёта во времени.
Результаты аудита выводятся непосредственно на график в аккуратном и структурированном интерфейсе. В результате трейдер получает компактную панель аудита непосредственно рядом с ценовым движением на графике и может отслеживать эффективность торговли в реальном времени, не переключаясь на другие окна. Задача заключается не только в отображении чисел, но и в преобразовании сырых торговых данных в понятную, легко читаемую аналитику для принятия решений.
Ниже показано, как будет выглядеть окончательный интерфейс аудита после его размещения на графике: 
Определив визуальный ориентир, рассмотрим подход к созданию удобного пользовательского интерфейса. Вместо немедленного перехода к коду сначала разобьем процесс на основные компоненты, чтобы до начала реализации понять структуру системы и потоки данных.
На приведенной ниже схеме рабочего процесса кратко представлен этот подход и показано, какую роль каждый компонент играет в создании понятного и отзывчивого интерфейса аудита счёта.

Теперь, когда подход определён, можно перейти к описанию основных показателей аудита, необходимых системе.
Определение показателей аудита
После определения архитектуры системы зададим основные показатели, на которых строится процесс аудита. Они образуют количественную основу механизма аудита и преобразуют исходные торговые данные в содержательную оценку результатов. Каждый показатель выбран так, чтобы отвечать на конкретный вопрос о поведении счёта, эффективности торговли и уровне риска.
- Начальный баланс: Баланс счёта на начало периода аудита. Он учитывает только реализованный капитал и не включает плавающую прибыль или убыток, благодаря чему расчеты эффективности остаются стабильными и воспроизводимыми.
- Конечный баланс: Баланс счёта на конец расчетного периода. В сочетании с начальным балансом он позволяет сразу оценить, вырос ли счёт, остался без существенных изменений или уменьшился за указанный период.
- Чистая прибыль: Арифметическая разница между конечным и начальным балансом с учётом пополнений и вывода средств, если это необходимо.
- Всего сделок: Отражает общую торговую активность за период аудита и позволяет правильно интерпретировать другие показатели, прежде всего процент прибыльных сделок и прибыль.
- Прибыльные и убыточные сделки: Разделяет общее количество сделок на прибыльные и убыточные. Такая двоичная классификация необходима для анализа распределения результатов и служит основой для расчета более сложных коэффициентов.
- Процент прибыльных сделок: Отражает вероятность успешного результата отдельной сделки. Сам по себе этот показатель нередко переоценивают, однако в сочетании с чистой прибылью он становится весьма информативным и показывает, обусловлена ли прибыльность частотой успешных сделок или размером прибыли по отдельным сделкам.
- Выведенные средства: Учитывает все средства, выведенные со счёта за период аудита. Этот показатель крайне важен, поскольку предотвращает ошибочную оценку результатов: счёт может выглядеть неизменным или убыточным, хотя на самом деле прибыль регулярно выводилась.
- Оценка эффективности: Составной показатель, объединяющий несколько характеристик — прибыльность, стабильность, уровень риска и эффективность торговли — в единую итоговую оценку. Он служит не только для описания результатов, но и для их интерпретации, позволяя с первого взгляда оценить общее качество торговли на счёте.
В совокупности эти показатели формируют структурированное и всестороннее представление о результатах торговли. Система не только сообщает, что произошло, но и помогает понять причины полученного результата, создавая основу для информативного интерфейса, ориентированного на принятие решений.
Разработка пользовательского интерфейса
После определения аналитической основы необходимо воплотить систему аудита в визуальном и интерактивном интерфейсе, преобразовав исходные показатели в наглядный интерактивный инструмент для трейдера.
В данной реализации используется пользовательский индикатор MQL5. Это осознанное архитектурное решение. В отличие от скриптов и советников, пользовательский индикатор естественным образом размещается на графике и предоставляет постоянно доступную, динамически обновляемую область для вывода данных аудита в реальном времени. Благодаря этому показатели эффективности отображаются непосредственно там, где принимаются торговые решения и где они наиболее полезны.
Директивы препроцессора
Начнем с директив препроцессора, определяющих параметры компиляции и метаданные программы MQL5. Затем объявим основные константы, которые будут использоваться во всей реализации и обеспечат ее единообразие и удобство сопровождения.
//+------------------------------------------------------------------+ #property copyright "© 2026, ChukwuBuikem" #property link "https://www.mql5.com/en/users/bikeen" #property version "1.00" #property indicator_chart_window #property indicator_plots 0 #property strict #include <ChartObjects\ChartObjectsTxtControls.mqh> #define PROG_NAME "Account Audit System" #define OUTER_PANEL PROG_NAME + "_OuterPanel" #define INNER_PANEL PROG_NAME + "_InnerPanel" #define MAIN_HEADER PROG_NAME + "_Header" #define START_BALANCE_LABEL PROG_NAME + "_StartBal" #define END_BALANCE_LABEL PROG_NAME + "_EndBal" #define NET_PROFIT_LABEL PROG_NAME + "_NetProfit" #define LINE_SEPARATOR PROG_NAME + "_Separator" #define TRADES_LABEL PROG_NAME + "_Trades" #define WINS_LABEL PROG_NAME + "_Wins" #define LOSSES_LABEL PROG_NAME + "_Losses" #define WINRATE_LABEL PROG_NAME + "_WinRate" #define WITHDRAWAL_LABEL PROG_NAME + "_Withdrawal" #define PERFORMANCE_LABEL PROG_NAME + "_Performance" #define RATING_LABEL PROG_NAME + "_Star" #define CLR_CHARCOAL C'30,30,30' #define CHART_ID ChartID()
- #property: объявляет метаданные программы, включая версию, сведения об авторе и директивы компилятора, которые определяют обработку и отображение программы MQL5 в терминале.
- #include: Подключает к программе заголовочные файлы и предоставляет доступ к готовым классам, например ChartObjectsTxtControls, расширяя функциональность и обеспечивая повторное использование готовых классов и элементов управления интерфейсом.
- #define: Задает макросы, выполняющие роль многократно используемых псевдонимов и повышающие читаемость и удобство сопровождения кода.
Пользовательская структура данных
Далее создадим пользовательскую структуру данных, которая служит основным контейнером для всех рассчитанных показателей счёта. Она представляет центральное состояние системы аудита и обеспечивает упорядоченное хранение, доступность и согласованное управление данными об эффективности.
//-Data structure struct acc_Audit { //--Variables : Defined audit metrics double startBal, endBal; double deposit, withdrawn, netProfit; int winRate, totalTrades, wins; int losses, stars; //-Constructor acc_Audit() { startBal = 0; endBal = 0; withdrawn = 0; netProfit = 0; winRate = 0; totalTrades = 0; wins = 0; losses = 0; stars = 1; } };
- Переменные: Представляют заранее определенные показатели эффективности: начальный и конечный баланс, оценку эффективности в звёздах и другие данные аудита.
- Конструктор: Инициализирует переменные структуры стандартными значениями. Это обеспечивает предсказуемое поведение при первом запуске до того, как управление перейдет к подсистеме хранения данных, которая начнет восстанавливать или обновлять сохраненные значения.
Глобальные переменные
После создания основной структуры данных перейдем к определению глобальных переменных программы. Это общие экземпляры, существующие на протяжении всего жизненного цикла программы и обеспечивающие согласованный доступ к данным и компонентам интерфейса.
//-Global variables
acc_Audit accountAudit;
CChartObjectRectLabel rectLabel;
CChartObjectLabel label; - accountAudit: Экземпляр пользовательской структуры данных, предназначенный для хранения всех рассчитанных показателей счёта и управления ими.
- rectLabel: Экземпляр CChartObjectRectLabel, упрощающий создание прямоугольных элементов интерфейса на графике и управление ими.
- label: Экземпляр CChartObjectLabel, предоставляющий удобный интерфейс для вывода и обновления текстовых компонентов.
Обработчики жизненного цикла
Теперь рассмотрим основные обработчики жизненного цикла программы, в которых определяется логика инициализации, выполнения и очистки. К ним относятся OnInit(), OnCalculate() и OnDeinit(), каждый из которых выполняет отдельную роль в процессе работы индикатора.
На данном этапе основное внимание уделяется настройке пользовательского интерфейса, поэтому логика OnInit() и OnDeinit() будет реализована полностью. Функцию OnCalculate() пока намеренно оставим пустой. Ее реализация будет рассмотрена в одной из следующих частей серии при создании вычислительного механизма аудита.
//+------------------------------------------------------------------+ //| Initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- showDashboard(accountAudit); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int32_t reason) { //--- ObjectsDeleteAll(0, PROG_NAME);//Clear chart ChartSetInteger(CHART_ID, CHART_SHOW_ONE_CLICK, true); ChartRedraw(); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int32_t &spread[]) { //-Empty for now return(rates_total); }
- OnInit(): Формирует начальное состояние: инициализирует переменные и создает информационную панель.
- OnDeinit(): Обеспечивает корректное завершение работы и очистку графика при удалении программы. Кроме того, функция восстанавливает измененные настройки графика, например повторно включает торговлю в один клик.
- OnCalculate(): Обрабатывает обновления ценовых данных и выполняет необходимые вычисления при каждом обновлении тиковых данных или появлении нового бара.
Вспомогательные функции
Далее создадим набор вспомогательных функций — модульных компонентов, инкапсулирующих повторно используемую логику. Они позволяют сделать основную реализацию компактной, упорядоченной и удобной для сопровождения.
//+------------------------------------------------------------------+ //| Function to create rectangle labels | //+-----------------------------------------------------------------+ bool createRectLabel(const string objName, const int xDistance, const int yDistance, const int xSize, const int ySize, const color clr, int borderWidth, const color borderColor = clrNONE, const ENUM_BORDER_TYPE borderType = BORDER_FLAT, const ENUM_LINE_STYLE borderStyle = STYLE_SOLID) { //--- if(rectLabel.Create(CHART_ID, objName, 0, 0, 0, 0, 0)) { rectLabel.X_Distance(xDistance); rectLabel.Y_Distance(yDistance); rectLabel.X_Size(xSize); rectLabel.Y_Size(ySize); rectLabel.BackColor(clr); rectLabel.SetInteger(OBJPROP_BORDER_COLOR, borderColor); rectLabel.BorderType(borderType); rectLabel.Style(borderStyle); rectLabel.Corner(CORNER_LEFT_UPPER); rectLabel.Tooltip("\n"); rectLabel.SetInteger(OBJPROP_HIDDEN, true); return true; } return false; } //+------------------------------------------------------------------+ //| Function to create labels | //+------------------------------------------------------------------+ bool createLabel(const string objName, const int xDistance, const int yDistance, const color clr, const string display, const int fontSize = 15, const string font = "Arial Bold", const string tooltip = "\n") { //--- if(label.Create(CHART_ID, objName, 0, 0, 0)) { label.X_Distance(xDistance); label.Y_Distance(yDistance); label.Color(clr); label.Tooltip(tooltip); label.SetString(OBJPROP_TEXT, display); label.FontSize(fontSize); label.Font(font); label.SetInteger(OBJPROP_HIDDEN, true); return true; } return false; } //+------------------------------------------------------------------+ //| Function to star shapes for rating, using labels | //+------------------------------------------------------------------+ void createStars(const int earnedStar) { //--- int xDistance = 215; for(int w = 1; w <= 5; w++) { string name = RATING_LABEL + IntegerToString(w); createLabel(name, (w == 1) ? xDistance : xDistance += 35, 513, (w <= earnedStar) ? clrGold : clrGray, "★", 30, "Arial Bold", "Overall Rating"); } } //+------------------------------------------------------------------+ //| Function to assemble Dashboard | //+------------------------------------------------------------------+ void showDashboard(acc_Audit & audit) { //--- createRectLabel(OUTER_PANEL, 30, 50, 400, 530, CLR_CHARCOAL, 1, clrDarkBlue, BORDER_FLAT, STYLE_SOLID); createRectLabel(INNER_PANEL, 55, 120, 350, 450, CLR_CHARCOAL, 1, clrDarkBlue, BORDER_FLAT, STYLE_DASHDOTDOT); createLabel(MAIN_HEADER, 70, 70, clrGold, "Account Audit", 25); createLabel(START_BALANCE_LABEL, 75, 135, clrWhiteSmoke, "Start Balance :", 15); createLabel(START_BALANCE_LABEL + "Value", 250, 135, clrWheat, DoubleToString(audit.startBal, 2), 15); createLabel(END_BALANCE_LABEL, 75, 175, clrWhiteSmoke, "End Balance :", 15); createLabel(END_BALANCE_LABEL + "Value", 250, 175, clrWheat, DoubleToString(audit.endBal, 2), 15); createLabel(NET_PROFIT_LABEL, 75, 215, clrWhiteSmoke, "Net Profit :", 15); createLabel(NET_PROFIT_LABEL + "Value", 250, 215, clrWheat, DoubleToString(audit.netProfit, 2), 15); createLabel(LINE_SEPARATOR + "0", 75, 250, clrGray, "___________________________________", 11); createLabel(TRADES_LABEL, 75, 290, clrWhiteSmoke, "Trades :", 15); createLabel(TRADES_LABEL + "Value", 250, 290, clrWheat, IntegerToString(audit.totalTrades), 15); createLabel(WINS_LABEL, 75, 330, clrWhiteSmoke, "Wins :", 15); createLabel(WINS_LABEL + "Value", 250, 330, clrLime, IntegerToString(audit.wins), 15); createLabel(LOSSES_LABEL, 75, 370, clrWhiteSmoke, "Losses :", 15); createLabel(LOSSES_LABEL + "Value", 250, 370, clrCrimson, IntegerToString(audit.losses), 15); createLabel(WINRATE_LABEL, 75, 410, clrWhiteSmoke, "Win Rate :", 15); createLabel(WINRATE_LABEL + "Value", 250, 410, clrWheat, IntegerToString(audit.winRate) + "%", 15); createLabel(LINE_SEPARATOR + "1", 75, 450, clrGray, "___________________________________", 11); createLabel(WITHDRAWAL_LABEL, 75, 490, clrWhiteSmoke, "Withdrawn :", 15); createLabel(WITHDRAWAL_LABEL + "Value", 250, 490, clrWheat, "- " + DoubleToString(audit.withdrawn, 2), 15); createLabel(PERFORMANCE_LABEL, 75, 530, clrWhiteSmoke, "Performance :", 15); createStars(audit.stars); ChartSetInteger(CHART_ID, CHART_SHOW_ONE_CLICK, false); ChartRedraw(); } //+------------------------------------------------------------------+
- createRectLabel(): Использует экземпляр CChartObjectRectLabel для создания прямоугольных элементов, формирующих структуру панели.
- createLabel(): Использует экземпляр CChartObjectLabel для создания текстовых компонентов, отображающих показатели.
- createStars(): Динамически формирует оценку эффективности в виде звёзд с помощью объектов-меток.
- showDashboard(): Управляет сборкой пользовательского интерфейса, объединяя все компоненты в единую панель, и одновременно отключает торговлю в один клик для предотвращения конфликтов взаимодействия.
После компиляции и запуска программы на графике интерфейс должен выглядеть следующим образом:

Теперь у нас есть аккуратная и структурированная панель с основными показателями. Однако возникает серьезная проблема удобства использования: система постоянно отключает панель торговли в один клик, а сама панель аудита остается статичной, ограничивает взаимодействие с графиком и мешает просмотру истории движения цены.
Возникает важный вопрос: как повысить удобство работы, сохранив всю функциональность?
Повышение удобства использования (UX)
Для дальнейшего повышения удобства можно рассмотреть несколько подходов. В этой реализации выбрано простое и практичное решение: кнопка-переключатель, позволяющая отображать или скрывать панель по команде пользователя. Пользователь получает больше контроля над пространством графика: панель остается доступной при необходимости и не мешает наблюдать за движением цены, когда она не используется.
Перейдем к реализации этой функциональности на MQL5.
Перед созданием кнопки определим константы имен, которые будут использоваться в этом процессе. Также создадим экземпляр CChartObjectButton, чтобы упростить создание кнопки и управление ею.
. . . . . . #define CLR_CHARCOAL C'30,30,30' #define CHART_ID ChartID() #define BUTTON_MENU PROG_NAME + "_ButtonMenu" #define BUTTON_RESET PROG_NAME + "_ButtonReset" //-Global variables . . . CChartObjectRectLabel rectLabel; CChartObjectLabel label; CChartObjectButton button;
Затем изменим функцию инициализации так, чтобы при запуске она создавала только кнопку меню с надписью «Show» («Показать»), а не загружала всю панель.
//+------------------------------------------------------------------+ //| Initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- createButton(BUTTON_MENU, 780, 40, 55, 50, clrBlue, clrBlack, "Show", 13, "Menu Button"); ChartRedraw(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
После изменения процесса инициализации создадим отдельную функцию создания кнопок на основе экземпляра CChartObjectButton. Затем добавим функцию переключения кнопки меню, которая обновляет её состояние, текст и цвет в зависимости от режима отображения или скрытия панели: «Show» («Показать») и «Hide» («Скрыть»).
//+------------------------------------------------------------------+ //| Function to create clickable button | //+------------------------------------------------------------------+ bool createButton(const string objName, const int xDistance, const int yDistance, const int xSize, const int ySize, const color backColor, const color borderColor, const string display, const int fontSize, const string toolTip) { //--- if(button.Create(CHART_ID, objName, 0, 0, 0, 0, 0)) { button.X_Distance(xDistance); button.Y_Distance(yDistance); button.X_Size(xSize); button.Y_Size(ySize); button.BackColor(backColor); button.SetString(OBJPROP_TEXT, display); button.Color(clrWhite); button.BorderColor(borderColor); button.State(false); button.Selectable(false); button.FontSize(fontSize); button.Tooltip(toolTip); button.SetInteger(OBJPROP_HIDDEN, true); return true; } return false; } //+------------------------------------------------------------------+ //| Function to toggle menu button | //+------------------------------------------------------------------+ bool toggleMenuButton() { //--- static bool isShow = false; isShow = !isShow; if(button.Attach(CHART_ID, BUTTON_MENU, 0, 1)) { if(isShow) { button.State(false); button.BackColor(clrRed); button.SetString(OBJPROP_TEXT, "Hide"); button.Tooltip("Hide Button"); } else { button.State(false); button.BackColor(clrBlue); button.SetString(OBJPROP_TEXT, "Show"); button.Tooltip("Show Button"); } button.Detach(); } return isShow; } //+------------------------------------------------------------------+
После внесения этих изменений функцию сборки панели потребуется изменить лишь незначительно.
//+------------------------------------------------------------------+ //| Function to assemble Dashboard | //+------------------------------------------------------------------+ void showDashboard(acc_Audit & audit) { //--- ChartSetInteger(CHART_ID, CHART_SHOW_ONE_CLICK, false);//-Should be executed before others createRectLabel(OUTER_PANEL, 30, 50, 400, 530, CLR_CHARCOAL, 1, clrDarkBlue, BORDER_FLAT, STYLE_SOLID); . . . . . . . . . createLabel(PERFORMANCE_LABEL, 75, 530, clrWhiteSmoke, "Performance :", 15); createStars(audit.stars); createButton(BUTTON_RESET, 335, 70, 55, 35, clrCrimson, clrWhiteSmoke, "Reset", 13, "Reset Button");//-Reset button ChartRedraw(); } //+------------------------------------------------------------------+
Далее создадим функцию, которая по запросу пользователя скрывает панель и одновременно восстанавливает торговлю в один клик.
//+------------------------------------------------------------------+ //| Function to hide dashboard and re-enable one-click trading | //+------------------------------------------------------------------+ void hideDashboard() { //--- ObjectDelete(CHART_ID, OUTER_PANEL); ObjectDelete(CHART_ID, INNER_PANEL); ObjectDelete(CHART_ID, MAIN_HEADER); ObjectDelete(CHART_ID, BUTTON_RESET); ObjectsDeleteAll(CHART_ID, START_BALANCE_LABEL); ObjectsDeleteAll(CHART_ID, END_BALANCE_LABEL); ObjectsDeleteAll(CHART_ID, NET_PROFIT_LABEL); ObjectsDeleteAll(CHART_ID, TRADES_LABEL); ObjectsDeleteAll(CHART_ID, LINE_SEPARATOR); ObjectsDeleteAll(CHART_ID, TRADES_LABEL); ObjectsDeleteAll(CHART_ID, WINS_LABEL); ObjectsDeleteAll(CHART_ID, LOSSES_LABEL); ObjectsDeleteAll(CHART_ID, WINRATE_LABEL); ObjectsDeleteAll(CHART_ID, WITHDRAWAL_LABEL); ObjectDelete(CHART_ID, PERFORMANCE_LABEL); ObjectsDeleteAll(CHART_ID, RATING_LABEL); ChartSetInteger(CHART_ID, CHART_SHOW_ONE_CLICK, true); ChartRedraw(); } //+------------------------------------------------------------------+
Теперь перейдем к основному элементу, обеспечивающему удобство работы, — обработчику OnChartEvent. В нем настроим реакцию кнопки меню на щелчки пользователя, переключая видимость панели аудита.
//+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int32_t id, const long & lparam, const double & dparam, const string & sparam) { //--- if(StringFind(sparam, PROG_NAME) == -1) return; if(sparam == BUTTON_MENU) { if(toggleMenuButton()) { showDashboard(accountAudit); ChartRedraw(); } else { hideDashboard(); ChartRedraw(); } } if(sparam == BUTTON_RESET) { //-Audit engine logic } } //+------------------------------------------------------------------+
После внесения этих улучшений и компиляции программы при ее запуске на графике должна отображаться более удобная панель аудита: 
Удобная панель аудита
Заключение
В этой части мы реализовали и проверили слой пользовательского интерфейса системы аудита счёта. В результате создан индикатор для графика, который:
- Формирует структурированную панель аудита на основе центральной структуры показателей.
- Предоставляет кнопку меню для отображения и скрытия панели без потери удобства работы с графиком.
- Восстанавливает торговлю в один клик при скрытии панели.
- Обрабатывает щелчки пользователя с помощью OnChartEvent и содержит кнопку «Reset» («Сброс»), пока используемую как заготовку для будущих действий.
Важно отметить, что вычислительное ядро OnCalculate намеренно остается пустым: отображаемые значения показателей считываются из структуры данных индикатора и ожидают подключения к механизму аудита. В следующих статьях система будет дополнена обработкой сделок с фильтрацией по времени, расчетом показателей, сохранением состояния между перезапусками и слоем уведомлений, включая отправку push-уведомлений на мобильные устройства. Благодаря чётко определённым интерфейсам и именованным константам пользовательский интерфейс можно расширять и без переработки слоя представления подключать к этим модулям.
Откройте прилагаемый файл с исходным кодом в MetaEditor, запустите индикатор на графике, чтобы оценить работу панели и модель взаимодействия. В следующих частях к интерфейсу будут подключены механизм аудита и подсистема хранения данных.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/22032
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Можно ли запустить DOOM в MetaTrader 5: DLL, рендеринг и ввод через MQL5?
Возможности Мастера MQL5, которые вам нужно знать (Часть 78): Стратегии на основе осцилляторов Gator и A/D для повышения устойчивости на рынке
Возможности Мастера MQL5, которые вам нужно знать (Часть 79): Использование осцилляторов Gator и A/D в обучении с учителем
Ручное тестирование на исторических данных в тестере стратегий MetaTrader 5 с кнопками Buy/Sell на графике
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования