MQL5: Скрипт для массового закрытия убыточных позиций по Magic Number

MQL5: Скрипт для массового закрытия убыточных позиций по Magic Number MQL4 / MQL5 (MetaTrader)
Подробная инструкция и MQL5 скрипт для автоматического массового закрытия всех убыточных торговых позиций в MetaTrader 5, фильтруя их по магическому номеру.
Суть: Представленный MQL5 скрипт позволяет быстро и эффективно закрыть все убыточные торговые позиции в MetaTrader 5, которые соответствуют заданному магическому номеру. Это мощный инструмент для управления рисками и оперативного реагирования на нежелательные рыночные ситуации.

Исходный код

Ниже представлен полный исходный код MQL5 скрипта. Он предназначен для запуска на любом графике в MetaTrader 5 и выполняет итерацию по всем открытым позициям. Для каждой позиции скрипт проверяет ее магический номер и текущую прибыльность. Если позиция убыточна и соответствует заданному магическому номеру (или если магический номер не указан, то всем убыточным позициям), она будет закрыта.

Этот скрипт является отличным дополнением к вашему арсеналу инструментов для управления рисками, особенно если вы используете несколько торговых стратегий или экспертов, каждый из которых имеет свой уникальный Magic Number. Например, для более продвинутых методов управления объемом, таких как автоматическое выравнивание объемов ордеров по Келли, или для сложных стратегий, требующих точного контроля над позициями, подобных тем, что используются при расчете маржинальных требований для Straddle, такой скрипт может быть незаменим.


//+------------------------------------------------------------------+
//|                                     CloseLosingPositionsByMagic.mq5|
//|                                                 FinFluct.com     |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "FinFluct.com"
#property link      "https://finfluct.com"
#property version   "1.00"
#property description "Скрипт для массового закрытия всех убыточных позиций по заданному магическому номеру."
#property script_show_inputs

#include 

//--- Входные параметры
input long   MagicNumberToClose = 0;    // Магический номер позиций для закрытия (0 - все)
input bool   ConfirmClosure     = false; // Подтвердить закрытие (true - закрыть, false - только лог)
input int    Slippage           = 5;     // Максимальное проскальзывание в пунктах

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
    CTrade trade;
    trade.SetExpertMagicNumber(MagicNumberToClose); // Устанавливаем магический номер для торговых операций (хотя для закрытия это не критично, но хорошая практика)
    trade.SetDeviationInPoints(Slippage);

    int closedPositions = 0;
    int totalPositions  = PositionsTotal();

    PrintFormat("Начинаем проверку %d открытых позиций...", totalPositions);

    // Итерируем в обратном порядке, так как закрытие позиций меняет их индексы
    for (int i = totalPositions - 1; i >= 0; i--)
    {
        ulong positionTicket = PositionGetTicket(i);
        if (positionTicket == 0)
        {
            PrintFormat("Ошибка получения тикета позиции по индексу %d. Пропускаем.", i);
            continue;
        }

        if (!PositionSelectByTicket(positionTicket))
        {
            PrintFormat("Ошибка выбора позиции с тикетом %llu. Пропускаем.", positionTicket);
            continue;
        }

        long currentMagic = PositionGetInteger(POSITION_MAGIC);
        double currentProfit = PositionGetDouble(POSITION_PROFIT);
        string symbol = PositionGetString(POSITION_SYMBOL);
        ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
        double volume = PositionGetDouble(POSITION_VOLUME);

        // Проверяем магический номер (если MagicNumberToClose = 0, то закрываем все убыточные)
        bool magicMatch = (MagicNumberToClose == 0 || currentMagic == MagicNumberToClose);

        if (magicMatch && currentProfit < 0)
        {
            PrintFormat("Позиция #%llu (%s %s %.2f лотов, Magic: %d) - Убыточная (%.2f).",
                        positionTicket,
                        symbol,
                        (type == POSITION_TYPE_BUY ? "BUY" : "SELL"),
                        volume,
                        currentMagic,
                        currentProfit);

            if (ConfirmClosure)
            {
                PrintFormat("Попытка закрыть позицию #%llu...", positionTicket);
                if (trade.PositionClose(positionTicket))
                {
                    PrintFormat("Позиция #%llu успешно отправлена на закрытие.", positionTicket);
                    closedPositions++;
                }
                else
                {
                    PrintFormat("Ошибка при попытке закрыть позицию #%llu. Код ошибки: %d", positionTicket, GetLastError());
                }
            }
            else
            {
                PrintFormat("Закрытие позиции #%llu пропущено (ConfirmClosure = false).", positionTicket);
            }
        }
        else if (magicMatch && currentProfit >= 0)
        {
            PrintFormat("Позиция #%llu (%s %s %.2f лотов, Magic: %d) - Прибыльная (%.2f). Пропускаем.",
                        positionTicket,
                        symbol,
                        (type == POSITION_TYPE_BUY ? "BUY" : "SELL"),
                        volume,
                        currentMagic,
                        currentProfit);
        }
        else
        {
            PrintFormat("Позиция #%llu (%s %s %.2f лотов, Magic: %d) - Не соответствует магическому номеру %d. Пропускаем.",
                        positionTicket,
                        symbol,
                        (type == POSITION_TYPE_BUY ? "BUY" : "SELL"),
                        volume,
                        currentMagic,
                        MagicNumberToClose);
        }
    }

    if (ConfirmClosure)
    {
        PrintFormat("Завершено. Отправлено на закрытие %d убыточных позиций.", closedPositions);
    }
    else
    {
        PrintFormat("Завершено. Обнаружено %d убыточных позиций, но закрытие не выполнено (ConfirmClosure = false).", closedPositions);
    }
}

Разбор параметров

  • MagicNumberToClose:

    Этот параметр определяет магический номер (Magic Number) позиций, которые скрипт будет рассматривать для закрытия. Если вы установите значение 0, скрипт будет проверять и потенциально закрывать убыточные позиции независимо от их магического номера. Это полезно, если вы хотите закрыть все убыточные позиции на счете.

  • ConfirmClosure:

    Булевый (логический) параметр, который служит мерой предосторожности. Если установлено в false, скрипт будет только логировать (выводить в журнал) информацию об убыточных позициях, которые он нашел, но не будет отправлять запросы на их закрытие. Установите его в true, чтобы разрешить скрипту фактически закрывать позиции. Всегда рекомендуется сначала запустить скрипт с ConfirmClosure = false для «сухого прогона».

  • Slippage:

    Максимально допустимое проскальзывание в пунктах при закрытии позиций. Проскальзывание — это разница между ожидаемой ценой исполнения ордера и фактической ценой. Установка более высокого значения может увеличить вероятность исполнения ордера, но по менее выгодной цене.

Как запустить

Для использования скрипта выполните следующие шаги:

  1. Откройте MetaEditor: В MetaTrader 5 нажмите F4 или выберите Сервис -> Редактор MetaQuotes Language.

  2. Создайте новый скрипт: В MetaEditor выберите Файл -> Создать -> Скрипт. Дайте ему имя, например, CloseLosingPositionsByMagic.

  3. Вставьте код: Скопируйте предоставленный выше MQL5 код и вставьте его в окно нового скрипта, заменив стандартный шаблон.

  4. Скомпилируйте скрипт: Нажмите кнопку Компилировать (или F7). Убедитесь, что нет ошибок компиляции. Скрипт появится в навигаторе MetaTrader 5 в разделе Скрипты.

  5. Запустите скрипт: Перетащите скрипт CloseLosingPositionsByMagic из окна Навигатор на любой график в MetaTrader 5. Появится окно с параметрами.

  6. Настройте параметры:

    • Установите желаемое значение для MagicNumberToClose. Если вы хотите закрыть все убыточные позиции, оставьте 0.

    • Сначала установите ConfirmClosure в false и нажмите ОК. Проверьте вкладку Эксперты в окне Терминал, чтобы увидеть, какие позиции были бы закрыты. Это ваш «сухой прогон».

    • Если результаты «сухого прогона» вас устраивают, снова перетащите скрипт на график, установите ConfirmClosure в true и нажмите ОК для фактического закрытия позиций.

  7. Мониторинг: Следите за вкладкой Эксперты в окне Терминал для получения информации о ходе выполнения скрипта и результатах закрытия позиций. В случае возникновения ошибок, их коды будут отображены там же.

Помните, что торговля на финансовых рынках сопряжена с рисками. Всегда тщательно проверяйте скрипты перед использованием на реальном счете. Для более сложных сценариев управления ордерами, например, при обходе ограничений на количество ордеров, вы можете ознакомиться с такими решениями, как MT4 Max Orders Bypass.

Оцените статью
FinFluct