При разработке коммерческих торговых роботов часто требуется ограничить использование советника только определёнными счетами (привязка к аккаунту) или задать временной лимит работы (например, демо-версия до определённой даты). В этой статье мы разберём, как реализовать такую защиту. Вы узнаете, как работают функции проверки, как интегрировать их в свои проекты для платформ MetaTrader 4 и MetaTrader 5.
1. Основные компоненты защиты
Типовая система лицензирования включает:
- Список разрешённых номеров счетов – массив целых чисел (для MT5 –
ulong, для MT4 –int). - Флаг временного ограничения – включает/отключает проверку срока действия.
- Дата окончания лицензии – после этой даты советник перестаёт работать.
- Функция проверки – сравнивает текущий счёт и текущую дату с разрешёнными значениями.
2. Реализация на MQL5 (пример из кода)
В исходном коде используются следующие глобальные определения:
#define TIME_LIMIT true
datetime TimeLimit = D'2027.01.01';
ulong accounts[] = {
30022,
// другие номера
};
bool PROTECT_STATUS() {
datetime timeCurrent = TimeCurrent();
ulong currentAcc = AccountNumber();
for(int i = 0; i < ArraySize(accounts); i++) {
ulong acc = accounts[i];
if(acc > 0 && acc == currentAcc) {
if(!TIME_LIMIT || (TIME_LIMIT && timeCurrent < TimeLimit))
return true;
}
}
return false;
} Пояснение работы
AccountNumber()– встроенная функция по аналогии как в MQL4, возвращающая номер текущего счёта. У меня сделана на основе функцииlong AccountInfoInteger(ACCOUNT_LOGIN), можно использовать сразу её.TimeCurrent()– текущее серверное время.- Цикл проходит по массиву
accounts. Если текущий счёт найден и (временное ограничение отключено ИЛИ текущее время меньшеTimeLimit), функция возвращаетtrue– доступ разрешён. - Иначе возвращает
false.
3. Адаптация для MetaTrader 4
В MT4 код будет почти идентичным, но с учётом отличий:
AccountNumber()в MT4 возвращаетint.- Массив счетов следует объявить как
int accounts[]. - Функция
TimeCurrent()работает одинаково.
Пример для MT4:
#define TIME_LIMIT true
datetime TimeLimit = D'2027.01.01';
int accounts[] = {
30022,
};
bool ProtectStatus() {
datetime now = TimeCurrent();
int acc = AccountNumber();
for(int i = 0; i < ArraySize(accounts); i++) {
if(accounts[i] == acc) {
if(!TIME_LIMIT || now < TimeLimit)
return true;
}
}
return false;
} 4. Интеграция в советник
4.1. Проверка при инициализации
В функции OnInit() вызываем проверку и, если она не пройдена, возвращаем INIT_FAILED или выводим предупреждение и продолжаем работу без торговли (как в примере – просто печатаем сообщение и в OnTick ничего не делаем).
int OnInit() {
if(!ProtectStatus()) {
Print("Данный счёт не разрешён для торговли. Обратитесь к продавцу.");
return INIT_FAILED; // советник не запустится
// или можно вернуть INIT_SUCCEEDED, но в OnTick проверять снова
}
// остальная инициализация
return INIT_SUCCEEDED;
} 4.2. Проверка в торговых функциях
Даже если при инициализации проверка пройдена, рекомендуется дублировать её в OnTick() и OnTimer() – на случай, если пользователь изменит счёт через терминал во время работы советника.
void OnTick() {
if(!ProtectStatus()) return;
// основной код
} 4.3. Сокрытие списка счетов и даты
Чтобы злоумышленник не мог легко изменить массив счетов или дату в декомпилированном коде, применяют следующие методы:
- Хранение в зашифрованном виде – например, с помощью простого XOR или более сложных алгоритмов.
- Разнесение данных по разным модулям – вынести список в отдельный include-файл и компилировать его в бинарном виде.
- Использование серверной проверки – советник обращается к удалённому серверу за подтверждением.
- Обфускация кода – запутывание логики (но полностью защитить от декомпиляции невозможно).
Самый простой способ – применить MQL5 Cloud Protector (или аналоги для MQL4), который шифрует строки и усложняет анализ.
Пример примитивного XOR-шифрования для массива:
void DecryptAccounts(ulong &out[], uchar &encrypted[], uchar key) {
int size = ArraySize(encrypted) / sizeof(ulong);
ArrayResize(out, size);
for(int i = 0; i < size; i++) {
ulong val;
for(int j = 0; j < sizeof(ulong); j++) {
((uchar*)&val)[j] = encrypted[i * sizeof(ulong) + j] ^ key;
}
out[i] = val;
}
} 5. Расширенные возможности
5.1. Проверка по имени счета или типу счёта
Помимо номера счёта можно проверять:
AccountName()– имя владельца.AccountServer()– сервер.AccountCompany()– компания.
5.2. Ограничение по времени с точностью до часа
Вместо даты можно задать точное время: datetime expire = D'2025.12.31 23:59:59'.
5.3. Механизм «килл-свитч»
При нарушении лицензии советник может не только прекратить торговлю, но и удалить все ордера, графические объекты или даже самоуничтожиться (через ExpertRemove()).
6. Полный пример для копирования
Ниже приведён готовый шаблон, который можно вставить в любой советник (MQL4/MQL5). Для MT4 замените ulong на int.
//+------------------------------------------------------------------+
//| License verification module |
//+------------------------------------------------------------------+
#define LICENSE_TIME_LIMIT true // true – ограничение по времени включено
datetime LicenseExpiration = D'2026.12.31 23:59:59'; // дата окончания
ulong LicensedAccounts[] = {
30022,
41005,
// добавьте другие счета
};
bool IsLicenseValid() {
datetime now = TimeCurrent();
ulong acc = AccountNumber();
for(int i = 0; i < ArraySize(LicensedAccounts); i++) {
if(LicensedAccounts[i] == acc) {
if(!LICENSE_TIME_LIMIT || now < LicenseExpiration)
return true;
}
}
return false;
} Использование:
int OnInit() {
if(!IsLicenseValid()) {
Alert("Лицензия недействительна! Советник остановлен.");
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
void OnTick() {
if(!IsLicenseValid()) return;
// ... торговый код
} 7. Важные замечания
- Никогда не полагайтесь только на проверку в
OnInit()– пользователь может перекомпилировать советник или изменить счёт после запуска. - Не храните чувствительные данные в открытом виде – хотя MQL-код сложно декомпилировать, полностью обезопасить его невозможно. Используйте дополнительные инструменты защиты.
- Для MT5 учтите, что номер счёта может быть очень большим (до 2^63-1), поэтому используйте тип
longилиulong. - Тестирование в стратегическом тестере – в тестере
AccountNumber()возвращает 0, поэтому для тестирования лицензионных ограничений придётся временно закомментировать проверку или добавить специальный режим.
Заключение
Привязка советника к номеру счёта и временное ограничение – это базовый, но эффективный способ защитить свою разработку от нелегального использования. Приведённый в статье код уже применяется в реальном коммерческом эксперте и может быть легко адаптирован под ваши нужды. Для повышения надёжности комбинируйте эту проверку с обфускацией, шифрованием строк и, по возможности, серверной валидацией.
Теперь вы можете внедрить лицензионную защиту в свои проекты на MT4 и MT5 – это повысит их коммерческую ценность и убережёт от несанкционированного доступа.


Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.