Реализация привязки советника к номеру счета и ограничению по времени в MT4/MT5

,

На чтение потребуется

4 минуты
Защита торгового робота в MetaTrader

При разработке коммерческих торговых роботов часто требуется ограничить использование советника только определёнными счетами (привязка к аккаунту) или задать временной лимит работы (например, демо-версия до определённой даты). В этой статье мы разберём, как реализовать такую защиту. Вы узнаете, как работают функции проверки, как интегрировать их в свои проекты для платформ 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 – это повысит их коммерческую ценность и убережёт от несанкционированного доступа.

: 3

Поделись или сохрани ссылку

Автор статьи

Комментарии

Добавить комментарий

0

Вы добавили товары в корзину?

Мы хотим вам предложить 3% скидку за сохранение вашей корзины. Прислать вам купон на скидку? Укажите рабочий email для отправки.

Содержание