Магический номер (Magic Number) — это уникальный числовой идентификатор, который присваивается каждому торговому ордеру или позиции советником (Экспертом) для их последующей идентификации․ Это фундаментальный механизм, позволяющий автоматизированным торговым системам (Советникам) отличать свои сделки от сделок других советников, ручной торговли или других экземпляров того же советника на одном счете․
Зачем нужен Magic Number? Основные сценарии использования
Без магического номера советник не может надежно управлять своими ордерами в реальной торговой среде․ Вот ключевые причины его использования:
- Работа нескольких советников на одном счете и символе: Если на счете запущено несколько Экспертов (например, один торгует по тренду, другой — по флэту), они не должны закрывать или модифицировать чужие ордера․ Magic Number — единственный способ их различить․
- Несколько экземпляров одного советника на разных таймфреймах: Даже если это один и тот же файл
․ex4/․ex5, запущенный на M15 и H1 у EURUSD, они должны иметь разные Magic Numbers, чтобы не путать свои позиции․ - Разделение ручной и автоматической торговли: Ордера, открытые вручную трейдером, имеют Magic Number 0․ Советник должен игнорировать их (если не задано иное) и обрабатывать только ордера со своим Magic Number․
- Идентификация в истории и отчетах: При анализе истории сделок (Backtest или реальный счет) Magic Number позволяет отфильтровать статистику по конкретной стратегии․
Как верно замечено на форуме MQL4: «Несколько советников на один счет MagicNumber нужен что бы он отличал свои ордера от других на одном счете»․
Реализация в MQL4
Объявление входного параметра
Стандартная практика — выносить Magic Number во входные параметры (input или extern в старых версиях), чтобы трейдер мог изменить его без перекомпиляции кода․
input int InpMagicNumber = 123456; // Магический номер ордеров Пример из классического шаблона урока по MQL:
extern double Lots = 0․1; // объём сделки в лотах
extern int StopLoss = 40; // ограничение убытка в пунктах
extern int TakeProfit= 70; // профит в пунктах
extern int Magic = 123; // магический номер ордеров
extern int Slippage = 5; // проскальзывание в пунктах
extern string comment = "Мой первый советник"; Отправка ордера (OrderSend)
При открытии ордера Magic Number передается в функцию OrderSend:
int ticket = OrderSend(_Symbol, OP_BUY, Lots, Ask, Slippage,
Bid ‒ StopLoss * _Point,
Ask + TakeProfit * _Point,
"My EA Comment",
InpMagicNumber, // <--- Передаем Magic Number
0, clrBlue); Поиск и фильтрация своих ордеров
Это самая критичная часть․ При переборе ордеров (через OrdersTotal и OrderSelect) обязательно проверяйте Magic Number и символ․
for(int i = OrdersTotal ─ 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{ // Проверяем символ И магический номер
if(OrderSymbol == _Symbol && OrderMagicNumber == InpMagicNumber)
{
// Это НАШ ордер․ Можно модифицировать, закрывать, трейлить стоп․
// OrderModify(․․․); OrderClose(․․․);
}
}
} Реализация в MQL5
В MQL5 архитектура изменилась: вместо ордеров (Orders) мы оперируем позициями (Positions) и заявками (Orders)․ У позиций и заявок есть свойство MAGIC (ENUM_POSITION_PROPERTY_INTEGER / ENUM_ORDER_PROPERTY_INTEGER)․
Установка Magic Number при торговле
Используется структура MqlTradeRequest:
MqlTradeRequest request = {0};
MqlTradeResult result = {0};
request․action = TRADE_ACTION_DEAL;
request․symbol = _Symbol;
request․volume = InpLots;
request․type = ORDER_TYPE_BUY;
request․price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request․sl = request․price ─ InpStopLoss * _Point;
request․tp = request․price + InpTakeProfit * _Point;
request․magic = InpMagicNumber; // <--- Установка Magic Number
request․comment = "MQL5 Expert";
request․type_filling = ORDER_FILLING_FOK;
if(!OrderSend(request, result))
Print("OrderSend error: ", GetLastError); Получение Magic Number у позиции/заявки
// Для позиций
for(int i = PositionsTotal ‒ 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{ long magic = PositionGetInteger(POSITION_MAGIC);
if(magic == InpMagicNumber && PositionGetString(POSITION_SYMBOL) == _Symbol)
{
// Наша позиция
}
}
}
// Для истории сделок (Deals) ‒ у сделок тоже есть MAGIC (DEAL_MAGIC) Документация MQL5 подтверждает: "В MQL5 имеется возможность задавать магический номер выставляемому ордеру, чтобы затем использовать эту информацию для идентификации ордера"․
Продвинутые техики: Маскирование Magic Number (Bitwise Operations)
В профессиональной разработке (например, в Стандартной библиотеке MQL5 или коммерческих фреймворках) Magic Number часто используют как составное число, кодирующее несколько параметров: ID стратегии, ID символа, ID таймфрейма, номер экземпляра․ Это делается через побитовые операции․
Структура составного Magic Number
Типичная маска (пример из статей по MQL5): 0xFFF0FFFF
- Низшие 16 бит (0x0000FFFF): Пользовательский Magic Number (задается в настройках)․
- Следующие 12 бит (0x0FFF0000): Идентификатор символа/стратегии/экземпляра (генерируется программно)․
- Старшие 4 бита (0xF0000000): Резерв или флаги типа ордера․
Пример кода для генерации и проверки
// Генерация уникального Magic для экземпляра
// Допустим, базовый магик пользователя = 123
// Хэш символа и таймфрейма = 0xABC
#define MAGIC_MASK_USER 0x0000FFFF
#define MAGIC_MASK_INTERNAL 0x0FFF0000
int GetInstanceMagic(int userMagic, long symbolHash)
{
return (userMagic & MAGIC_MASK_USER) | ((int)(symbolHash << 16) & MAGIC_MASK_INTERNAL);
}
// Проверка: "Является ли этот ордер моим?" (с учетом маски)
bool IsMyOrder(long orderMagic, int myUserMagic)
{
// Сравниваем только пользовательскую часть (младшие 16 бит)
return (orderMagic & MAGIC_MASK_USER) == myUserMagic;
} Это позволяет запускать один советник на разных символах/ТФ с одинаковым входным параметром Magic, но реальные ордера будут иметь уникальные номера, исключая коллизии․
Лучшие практики и частые ошибки
✅ Делайте так:
- Всегда используйте input-параметр․ Не хардкодьте число в коде (
OrderSend(․․․, 123, ․․․))․ - Проверяйте и Symbol, и MagicNumber․ На счете может быть ордер по GBPUSD с таким же Magic, что и ваш ордер по EURUSD․
- Используйте уникальные диапазоны․ Не ставьте "1", "2", "3"․ Используйте большие случайные числа (например,
1234567,987654321) или генераторы GUID, преобразованные в int․ - Сохраняйте Magic Number в глобальных переменных / файлах при сложной логике (мартингейл, сетки), чтобы восстановить контроль после перезапуска терминала/ВПС․
❌ Не делайте так:
- Игнорируете проверку MagicNumber в цикле перебора․ Это приведет к закрытию чужих ордеров (ручных или других ботов)․
- Меняете Magic Number "на лету" у открытых позиций․ В MQL4/MQL5 Magic Number ордера/позиции нельзя изменить после открытия․ Можно только закрыть и открыть новый․
- Используете 0 (ноль) как Magic для советника․ Ноль зарезервирован за ручной торговлей (в MQL4) или системными операциями․ Это вызовет хаос․
- Путаница между OrderMagicNumber (MQL4) и POSITION_MAGIC / ORDER_MAGIC (MQL5)․ В MQL5 у позиции и у заявки, её открывшей, может быть разный Magic (если меняли при модификации, хотя стандартно они совпадают)․
Magic Number и глобальные переменные / хранение состояния
При разработке сложных систем (например, панелей управления, копировщиков сделок, мульти-валютных советников) Magic Number становится ключом для хранения данных․
"Один эксперт может работать на разных символах, значит к имени глобальной переменной добавляем название символа (_Symbol), также․․․ используется магический номер, значит к имени глобальной переменной добавляем магический номер"․
Пример формирования уникального ключа GlobalVariable:
string GetGVName(string baseName)
{
// Формат: "MyEA_EURUSD_M15_Magic12345_ParamName"
return StringFormat("%s_%s_%s_M%d_%s",
MQLInfoString(MQL_PROGRAM_NAME),
_Symbol,
EnumToString((ENUM_TIMEFRAMES)_Period),
InpMagicNumber,
baseName);
}
// Использование
GlobalVariableSet(GetGVName("LastTradeTime"), TimeCurrent); Ответы на частые вопросы (FAQ)
В: Как узнать Magic Number уже открытых ордеров/позиций?
О: В терминале MetaTrader 4/5: вкладка "Торговля" -> Правый клик -> "Столбцы" -> поставить галочку "Magic Number" (в MT5) или смотреть комментарий/свойства ордера в MT4․ Программно — через OrderMagicNumber (MQL4) или PositionGetInteger(POSITION_MAGIC) (MQL5)․
В: Можно ли изменить Magic Number у открытой позиции?
О: Нет․ Это неизменяемое свойство ордера/позиции на протяжении всей его жизни․ Если нужно "перепривязать" — закрывайте и открывайте заново с новым Magic․
В: Какой максимальный размер Magic Number?
О: Тип данных int (32-битное знаковое целое)․ Диапазон: -2 147 483 648 ․․․ 2 147 483 647․ Рекомендуется использовать только положительные значения․
В: Зачем нужен Magic Number, если я торгую только одним советником на одном графике?
О: Даже в этом случае он нужен для:
- Исключения ручных ордеров (Magic=0) из управления․
- Корректной работы после перезапуска терминала (советник найдет свои ордера после рестарта)․
- Возможности в будущем добавить второй экземпляр или другой советник без переписывания кода․
В: Что означает фраза "магик номер эксперта является идентификатором записи в журнале"?
О: Это немного неточное выражение с форума․ Точнее: Magic Number — это идентификатор торговой записи (ордера/позиции/сделки) в истории и текущем состоянии счета, а не самого эксперта в журнале логов (у эксперта есть свой Handle/Path)․ Но суть верная: это "номер сделки" для программной идентификации․
Магический номер (Magic Number) — это "паспорт" вашей сделки в мире алгоритмической торговли․ Пренебрежение им — самая частая причина критических ошибок: закрытие чужих позиций, накопление "мусорных" ордеров, невозможность тестировать несколько стратегий на одном счете․
Главные правила профессионала:
- Объявляйте
input int MagicNumber․ - Передавайте его в каждый
OrderSend/OrderSend(request)․ - Фильтруйте каждый перебор ордеров/позиций:
if(OrderMagicNumber == MyMagic && OrderSymbol == _Symbol)․ - Используйте уникальные большие числа или битовые маски для мульти-экземплярных систем․
Следуя этим правилам, вы обеспечите надежность, масштабируемость и безопасность своих торговых роботов на платформах MetaTrader 4 и MetaTrader 5․