Исходный код
Представленный ниже код демонстрирует полноценный MQL5 советник, который создает на графике интерактивную панель управления. Панель включает две кнопки — ‘Buy’ и ‘Sell’ — а также поле ввода для указания объема лота. При нажатии на соответствующую кнопку советник считывает значение лота из поля, выполняет базовую валидацию и отправляет торговый ордер на исполнение. Это позволяет трейдеру вручную контролировать открытие позиций, используя логику и параметры советника.
#property copyright "FinFluct"
#property link "https://finfluct.com"
#property version "1.00"
#property description "Панель управления для советника с кнопками Buy/Sell и полем ввода лота."
#property description "Демонстрирует создание GUI элементов и обработку торговых операций."
#include
#include
#include
#include
//--- Входные параметры
input long MagicNumber = 12345; // Магический номер для ордеров
input int Deviation = 5; // Максимальное отклонение цены в пунктах
input double DefaultLot = 0.1; // Лот по умолчанию
//--- Объекты GUI
CButton* g_buyButton = NULL;
CButton* g_sellButton = NULL;
CEdit* g_lotEdit = NULL;
CLabel* g_lotLabel = NULL;
CLabel* g_statusLabel = NULL;
//--- Торговый объект
CTrade g_trade;
//--- Идентификаторы объектов GUI
enum ENUM_GUI_OBJECT_ID
{
GUI_ID_BUY_BUTTON = 1001,
GUI_ID_SELL_BUTTON,
GUI_ID_LOT_EDIT,
GUI_ID_LOT_LABEL,
GUI_ID_STATUS_LABEL
};
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Устанавливаем режим торговли
g_trade.SetAsyncMode(false); // Синхронный режим для простоты
g_trade.SetExpertMagicNumber(MagicNumber);
//--- Создаем метку для поля лота
g_lotLabel = new CLabel();
if(g_lotLabel == NULL) { Print("Failed to create g_lotLabel"); return INIT_FAILED; }
g_lotLabel.Create(0, "Лот:", 10, 10, 50, 20);
g_lotLabel.Color(clrWhite);
g_lotLabel.Font("Arial");
g_lotLabel.FontSize(9);
g_lotLabel.BringToTop();
g_lotLabel.Show();
//--- Создаем поле ввода лота
g_lotEdit = new CEdit();
if(g_lotEdit == NULL) { Print("Failed to create g_lotEdit"); return INIT_FAILED; }
g_lotEdit.Create(0, GUI_ID_LOT_EDIT, 60, 10, 80, 20);
g_lotEdit.Text(DoubleToString(DefaultLot, 2)); // Устанавливаем лот по умолчанию с 2 знаками после запятой
g_lotEdit.Color(clrWhite);
g_lotEdit.BackColor(clrBlack);
g_lotEdit.Font("Arial");
g_lotEdit.FontSize(9);
g_lotEdit.BringToTop();
g_lotEdit.Show();
//--- Создаем кнопку Buy
g_buyButton = new CButton();
if(g_buyButton == NULL) { Print("Failed to create g_buyButton"); return INIT_FAILED; }
g_buyButton.Create(0, GUI_ID_BUY_BUTTON, 10, 40, 60, 25);
g_buyButton.Text("Buy");
g_buyButton.Color(clrWhite);
g_buyButton.BackColor(clrGreen);
g_buyButton.Font("Arial");
g_buyButton.FontSize(10);
g_buyButton.BringToTop();
g_buyButton.Show();
//--- Создаем кнопку Sell
g_sellButton = new CButton();
if(g_sellButton == NULL) { Print("Failed to create g_sellButton"); return INIT_FAILED; }
g_sellButton.Create(0, GUI_ID_SELL_BUTTON, 80, 40, 60, 25);
g_sellButton.Text("Sell");
g_sellButton.Color(clrWhite);
g_sellButton.BackColor(clrRed);
g_sellButton.Font("Arial");
g_sellButton.FontSize(10);
g_sellButton.BringToTop();
g_sellButton.Show();
//--- Создаем метку для статуса
g_statusLabel = new CLabel();
if(g_statusLabel == NULL) { Print("Failed to create g_statusLabel"); return INIT_FAILED; }
g_statusLabel.Create(0, "Статус: Готов", 10, 75, 130, 20);
g_statusLabel.Color(clrWhite);
g_statusLabel.Font("Arial");
g_statusLabel.FontSize(8);
g_statusLabel.BringToTop();
g_statusLabel.Show();
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Удаляем объекты GUI
if(g_buyButton != NULL) { delete g_buyButton; g_buyButton = NULL; }
if(g_sellButton != NULL) { delete g_sellButton; g_sellButton = NULL; }
if(g_lotEdit != NULL) { delete g_lotEdit; g_lotEdit = NULL; }
if(g_lotLabel != NULL) { delete g_lotLabel; g_lotLabel = NULL; }
if(g_statusLabel != NULL) { delete g_statusLabel; g_statusLabel = NULL; }
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- Обработка кликов по кнопкам
if(id == CHARTEVENT_CLICK)
{
if(lparam == GUI_ID_BUY_BUTTON)
{
ProcessTrade(ORDER_TYPE_BUY);
}
else if(lparam == GUI_ID_SELL_BUTTON)
{
ProcessTrade(ORDER_TYPE_SELL);
}
}
}
//+------------------------------------------------------------------+
//| Функция обработки торговых операций |
//+------------------------------------------------------------------+
void ProcessTrade(ENUM_ORDER_TYPE orderType)
{
if(g_lotEdit == NULL || g_statusLabel == NULL) return;
//--- Получаем лот из поля ввода
double lot = StringToDouble(g_lotEdit.Text());
//--- Валидация лота
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick))
{
g_statusLabel.Text("Ошибка: не удалось получить тиковые данные.");
return;
}
double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double step_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
int lot_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_VOLUME_DECIMAL_DIGITS);
if(lot < min_lot)
{
g_statusLabel.Text("Ошибка: лот меньше минимального (" + DoubleToString(min_lot, lot_digits) + ").");
return;
}
if(lot > max_lot)
{
g_statusLabel.Text("Ошибка: лот больше максимального (" + DoubleToString(max_lot, lot_digits) + ").");
return;
}
// Проверяем кратность шагу с учетом точности double
if(fmod(lot, step_lot) > DBL_EPSILON * 1000) // Увеличиваем точность сравнения для fmod
{
g_statusLabel.Text("Ошибка: лот не кратен шагу (" + DoubleToString(step_lot, lot_digits) + ").");
return;
}
// Нормализуем лот до нужной точности
lot = NormalizeDouble(lot, lot_digits);
//--- Отправка ордера
string action = (orderType == ORDER_TYPE_BUY) ? "Покупка" : "Продажа";
double price = (orderType == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
g_statusLabel.Text("Отправка ордера " + action + " " + DoubleToString(lot, lot_digits) + " лот...");
if(orderType == ORDER_TYPE_BUY)
{
if(!g_trade.Buy(lot, _Symbol, price, Deviation, 0, 0, NULL, MagicNumber, 0, "Buy from GUI Panel"))
{
g_statusLabel.Text("Ошибка Buy: " + g_trade.ResultRetcodeDescription());
Print("Ошибка Buy: ", g_trade.ResultRetcode(), " - ", g_trade.ResultRetcodeDescription());
}
else
{
g_statusLabel.Text("Ордер Buy отправлен. Результат: " + g_trade.ResultRetcodeDescription());
Print("Ордер Buy отправлен. Результат: ", g_trade.ResultRetcode(), " - ", g_trade.ResultRetcodeDescription());
}
}
else // ORDER_TYPE_SELL
{
if(!g_trade.Sell(lot, _Symbol, price, Deviation, 0, 0, NULL, MagicNumber, 0, "Sell from GUI Panel"))
{
g_statusLabel.Text("Ошибка Sell: " + g_trade.ResultRetcodeDescription());
Print("Ошибка Sell: ", g_trade.ResultRetcode(), " - ", g_trade.ResultRetcodeDescription());
}
else
{
g_statusLabel.Text("Ордер Sell отправлен. Результат: " + g_trade.ResultRetcodeDescription());
Print("Ордер Sell отправлен. Результат: ", g_trade.ResultRetcode(), " - ", g_trade.ResultRetcodeDescription());
}
}
}
Разбор параметров
MagicNumber: Уникальный магический номер для идентификации ордеров, открытых данным советником. Это позволяет отличать ордера, открытые этим советником, от ордеров, открытых другими советниками или вручную.Deviation: Максимально допустимое отклонение цены в пунктах при отправке ордера. Если запрашиваемая цена изменится более чем на это значение к моменту исполнения, ордер может быть отклонен.DefaultLot: Начальное значение лота, которое будет отображаться в поле ввода при запуске советника. Пользователь может изменить его в любой момент.
Как запустить
Для запуска и использования данной панели управления выполните следующие шаги:
1. Сохраните код: Скопируйте весь представленный MQL5 код в новый файл с расширением .mq5 в папке MQL5/Experts/ вашего терминала MetaTrader 5. Например, назовите файл GUIPanelEA.mq5.
2. Скомпилируйте: Откройте файл в MetaEditor и нажмите кнопку ‘Компилировать’ (или F7). Убедитесь, что нет ошибок компиляции.
3. Прикрепите к графику: Перетащите скомпилированный советник GUIPanelEA.ex5 из окна ‘Навигатор’ терминала MetaTrader 5 на любой график.
4. Настройте: В окне настроек советника (вкладка ‘Входные параметры’) можете изменить MagicNumber, Deviation и DefaultLot. Убедитесь, что разрешена ‘Автоматическая торговля’ на вкладке ‘Общие’.
5. Используйте: После прикрепления на графике появится панель с кнопками ‘Buy’, ‘Sell’ и полем ввода лота. Введите желаемый лот и нажмите соответствующую кнопку для открытия позиции.
6. Мониторинг: Следите за сообщениями в журнале экспертов и на вкладке ‘Торговля’ для подтверждения открытия ордеров.
Эта панель предоставляет удобный способ ручного управления торговлей, используя при этом инфраструктуру советника. Вы можете расширить ее функционал, добавив, например, кнопки для закрытия позиций или отображения текущей прибыли, а также интегрировать с более сложными системами, как описано в статье MQL5: Реализация сетки ордеров (Grid) с мартингейлом и проверкой маржи, или добавить уведомления, используя подходы из MT5 и Pushover: Критические PUSH-уведомления через WebRequest. Для более глубокого анализа рынка вы можете рассмотреть использование инструментов, подобных Индикатору профиля рынка (Market Profile) на MQL5: гистограмма TPO, чтобы принимать более обоснованные торговые решения.




