English Deutsch 日本語
preview
Использование Экономического календаря MQL5 для фильтрации новостей (Часть 2): Временное удаление и восстановление стоп-уровней во время выхода новостей

Использование Экономического календаря MQL5 для фильтрации новостей (Часть 2): Временное удаление и восстановление стоп-уровней во время выхода новостей

MetaTrader 5 — Трейдинг |
88 2
Solomon Anietie Sunday
Solomon Anietie Sunday

Введение

В части 1 был представлен новостной фильтр, блокирующий открытие новых сделок во время событий высокой важности. Этот механизм снижает риск входа в рынок в условиях аномальной волатильности, но не решает оставшуюся проблему: сделки, открытые до начала новостного окна, по-прежнему подвержены расширению спредов, кратковременным всплескам и искажениям, что может преждевременно активировать SL и TP. Закрытие всех позиций перед каждым новостным событием часто неприемлемо: оно нарушает структуру сделки, искажает статистику и противоречит долгосрочной логике.

В статье рассматривается конкретная техническая задача: как добавить слой управления стоп-уровнями с возможностью обратного восстановления, который временно снимает SL и TP для уже открытых позиций на время ограниченного новостного окна, а затем детерминированно восстанавливает их. Критерии успеха четко заданы: действия должны выполняться один раз за каждое новостное окно без повторных модификаций; исходные значения SL и TP должны сохраняться и восстанавливаться, когда это технически возможно; должны соблюдаться правила брокера о минимальной дистанции до стоп-уровня; механизм должен позволять отбирать сделки по магическому числу советника и иметь четко определенную область действия, включая документированное поведение для одного символа. Цель — снижение риска преждевременного срабатывания стопов, а не прогнозирование направления рынка.


Решение, цель и принципы

Цель части 2 четко определена: убрать уровни стоп-лосса и тейк-профита на время ограниченного новостного окна и безопасно восстановить их после его окончания.

Этот подход не пытается интерпретировать направление реакции рынка на новости. Он лишь снижает риск преждевременного срабатывания стопов, вызванного аномальными рыночными условиями.

Принципы восстановления стоп-уровней

Логика восстановления детерминирована:

  • если цена не пересекла сохраненный исходный уровень стоп-лосса или тейк-профита, соответствующий уровень восстанавливается точно на исходном значении;
  • если цена уже пересекла исходный уровень стоп-лосса, стоп-лосс восстанавливается на ближайшем допустимом уровне непосредственно перед текущей ценой.

Та же логика применяется к уровням тейк-профита. Это обеспечивает:

  • отсутствие некорректной установки стоп-уровней;
  • отсутствие отказов брокера из-за того, что цена уже прошла соответствующие уровни;
  • отсутствие восстановления логически невозможных значений;
  • сохранение исходной структуры сделки во всех технически возможных случаях.

Механизм по-прежнему работает по четко заданным правилам.

Инженерные требования

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

  • несколько открытых сделок, потенциально по разным символам;
  • ограничения брокера по минимальной дистанции до стоп-уровня;
  • цена, уже пересекшая исходный стоп-уровень или целевой уровень на момент восстановления.

Для стабильной работы система должна:

  • безопасно сохранять исходные значения SL и TP перед их удалением;
  • отслеживать сделки, находящиеся в состоянии приостановки (когда стопы временно удалены);
  • избегать повторных или ненужных попыток модификации;
  • восстанавливать стоп-уровни только один раз за цикл события.

Поэтому сохранение состояния стратегии и логика контролируемой модификации являются ключевыми компонентами этой части.

Обзор решения и рамки статьи

Решение, представленное в статье, добавляет слой управления стоп-уровнями, активируемый только во время ограниченного новостного окна.

Рабочий процесс включает следующие этапы:

  1. обнаружить активное новостное окно, как описано в части 1;
  2. сохранить исходные значения SL и TP;
  3. временно удалить уровни SL и TP;
  4. отслеживать состояние приостановки;
  5. определить окончание новостного окна;
  6. детерминированно восстановить SL и TP;
  7. безопасно сбросить состояние.

Такая структура позволяет торговой стратегии немедленно восстановить полный контроль после окончания новостного окна, не изменяя на постоянной основе исходную структуру сделки.

Ограничения подхода с временным удалением стоп-уровней

Несмотря на свою эффективность, этот подход имеет ограничения.

  1. Риск открытой позиции без жесткой защиты: во время новостного окна с ограничениями сделки временно не имеют защиты стоп-лоссом. Резкие или продолжительные направленные движения могут увеличить плавающую просадку. Рекомендуется устанавливать короткое новостное окно с ограничениями, например продолжительностью 3-10 минут.
  2. Риск гэпа: если в период приостановки возникает значительный ценовой разрыв, восстановление может произойти на менее выгодном уровне.
  3. Это не система прогнозирования волатильности: данный механизм не прогнозирует реакцию рынка или направление движения. Он лишь снижает риск преждевременного срабатывания стопов, вызванного аномальными спредами или кратковременными ценовыми всплесками.
  4. Ограничения исполнения у брокера: восстановление стоп-уровней должно соответствовать правилам брокера о минимальной дистанции и ограничениям конкретного символа.
  5. Совместимость со стратегией: этот подход может не подходить для ультракраткосрочных скальпинговых систем, в которых обязательно постоянное наличие стоп-лосса.

Цель этого слоя — не устранение риска, а устранение конкретной структурной слабости автоматической торговли во время событий высокой важности.


Реализация

Прежде чем приступить к реализации, необходимо определить структуру рабочего процесса.

Структура рабочего процесса

Этап обнаружения:

  • выявить предстоящие новостные события — этот вопрос уже рассмотрен в части 1 и используется в части 2;
  • проверить, попадает ли текущее время в новостное окно.

Этап приостановки:

  • пройти по открытым позициям;
  • сохранить исходные значения SL и TP в массиве в памяти;
  • удалить SL и TP;
  • пометить сделку как приостановленную.

Этап мониторинга:

  • предотвращать повторные модификации;
  • поддерживать состояние приостановки до момента восстановления.

Этап восстановления:

  • для каждой приостановленной сделки — если цена не пересекла исходные SL и TP, восстановить точные значения; если цена пересекла исходные уровни, восстановить их на ближайшем допустимом уровне перед текущей ценой;
  • очистить состояние приостановки.

Схема архитектуры рабочего процесса

Наглядная схема

Шаг 1. Проектирование структуры состояния стоп-уровней

Прежде чем удалять или сохранять что-либо, необходимо ответить на простой вопрос: где будут храниться исходные значения SL и TP после их удаления?

Если удалить стоп-уровни без надежного сохранения, их восстановление станет невозможным.

Почему необходима структура отслеживания

К началу новостного окна уже может быть открыто несколько сделок с разными тикетами, уровнями стоп-лосса и уровнями тейк-профита. Для каждой сделки необходимо сохранить исходную конфигурацию. Поэтому вводится структура состояния, которая будет:

  • хранить номер тикета;
  • хранить исходный стоп-лосс;
  • хранить исходный тейк-профит.

Это обеспечивает точное, а не приблизительное восстановление для каждой сделки.

Структура состояния стоп-уровней

Определяется структура, служащая контейнером для каждой приостановленной сделки.

Необходимый код:

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+

//--- Structure to store removed stop information
struct SavedStops
  {
  ulong             ticket;       // Trade ticket number
  double            sl;           // Original stop loss
  double            tp;           // Original take profit
  };

Массив хранения

Поскольку может быть открыто несколько сделок, используется массив следующей структуры:

SavedStops savedStops[];     // Each element of this array represents one suspended trade

Флаг состояния приостановки

Помимо хранения значений стоп-уровней, необходимо отслеживать, находится ли система в состоянии приостановки. Это предотвращает:

  • повторное удаление стоп-уровней,
  • повторные попытки восстановления;
  • ненужную модификацию позиции.

Вводится логический флаг состояния:

bool     newsSuspended = false;        // When true stops are currently removed, when false stops are active

Почему это решение важно

Эта основа обеспечивает детерминированное восстановление, отслеживание по каждому тикету, отсутствие путаницы между сделками и разделение логики обнаружения и модификации.

На данном этапе пока ничего не снимается. Пока лишь создается система памяти, на которую будет опираться советник.

Все глобальные переменные следует разместить перед определением функции OnInit(), как показано ниже:

//+------------------------------------------------------------------+
//|                                       News integration part2.mq5 |
//|                                                    soloharbinger |
//|                      https://www.mql5.com/ru/users/soloharbinger |
//+------------------------------------------------------------------+
#property copyright "soloharbinger"
#property link      "https://www.mql5.com/ru/users/soloharbinger"
#property version   "1.00"

#include <Trade/Trade.mqh>

//+------------------------------------------------------------------+
//| GLOBAL VARIABLES                                                 |
//+------------------------------------------------------------------+
CTrade trade;

//--- Structure to store removed stop information
struct SavedStops
  {
  ulong ticket;        // Trade ticket number
  double sl;           // Original stop loss
  double tp;           // Original take profit
  };

SavedStops savedStops[];

bool newsSuspended = false;         // when true stops are currently removed, and when false stops are active


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  return(INIT_SUCCEEDED);
  }

Шаг 2. Фаза приостановки — удаление стоп-уровней во время новостей

Теперь, когда создана структура для хранения данных о стоп-уровнях, можно реализовать фазу их удаления.

Когда новостное окно становится активным, нужно:

  • пройти по открытым позициям;
  • сохранить исходные значения SL и TP;
  • удалить уровни SL и TP на стороне брокера;
  • пометить систему как приостановленную.

Защита от повторной приостановки

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

Используется следующее условие:

//--- Already in the desired state, prevent duplicate execution
if (newsSuspended)
  {
  return;
  }

Функция SuspendStops()

//+------------------------------------------------------------------+
//| Suspend Stops During News                                        |
//+------------------------------------------------------------------+
void SuspendStops(bool suspend)
{
    if (suspend == newsSuspended)
      return;
    newsSuspended = suspend;

    if(suspend)
    {
        ArrayResize(savedStops, 0); // Clear previous list
        for(int i = PositionsTotal() - 1; i >= 0; i--)
        {
            ulong ticket = PositionGetTicket(i);
            
            //--- If needed, filter by magic number here
            if(PositionSelectByTicket(ticket)) 
            {
                // Save current SL/TP
                int idx = ArraySize(savedStops);
                ArrayResize(savedStops, idx + 1);
                savedStops[idx].ticket = ticket;
                savedStops[idx].sl = PositionGetDouble(POSITION_SL);
                savedStops[idx].tp = PositionGetDouble(POSITION_TP);


                // Remove stops from broker side
                if(trade.PositionModify(ticket, 0.0, 0.0))
                {
                    PrintFormat("Frozen trade #%I64u: SL/TP removed for news.", ticket);
                }
            }
        }
    }
    else // Unsuspended using the RestoreStops() function then reset array
    {
        for(int k = 0; k < ArraySize(savedStops); k++)
        {
            RestoreStops(savedStops[k].ticket,
                         savedStops[k].sl,
                         savedStops[k].tp);
        }
        ArrayResize(savedStops, 0); 
    }
}

На данном этапе сделки остаются открытыми, а стоп-уровни не активны. Исходные уровни хранятся в памяти.

Шаг 3. Фаза восстановления — детерминированное восстановление стоп-уровней

После завершения новостного окна необходимо безопасно восстановить стоп-уровни. Однако восстановление — это не просто

trade.PositionModify(ticket, originalSL, originalTP);

поскольку цена могла измениться.

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

Принципы восстановления

Для каждой сделки с приостановленными стоп-уровнями нужно:

  1. выбрать позицию по тикету;
  2. получить текущую рыночную цену;
  3. сравнить цену с сохраненными уровнями SL и TP;
  4. если исходный уровень по-прежнему допустим, точно восстановить его;
  5. если уровень уже пересечен, восстановить его на ближайшем допустимом уровне с соответствующей стороны от текущей цены;
  6. соблюдать правила брокера о минимальной дистанции до стоп-уровня.

Функция восстановления RestoreStops()

//+------------------------------------------------------------------+
//| Restore Stops After News                                         |
//+------------------------------------------------------------------+
bool RestoreStops(ulong ticket, double sl, double tp)
{
    if (!PositionSelectByTicket(ticket))
      return(false);
    
    ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
    double price = (type == POSITION_TYPE_BUY) ?
        SymbolInfoDouble(_Symbol, SYMBOL_BID) :
        SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        
    double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    
    double minStopDist = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;

    // Safety check: If price has moved past the saved SL/TP, adjust to a valid level
    if(type == POSITION_TYPE_BUY)
    {
        if(sl != 0 && price <= sl)
            sl = price - minStopDist;
        if(tp != 0 && price >= tp)
            tp = price + minStopDist;
    }
    else // SELL
    {
        if(sl != 0 && price >= sl)
            sl = price + minStopDist;
        if(tp != 0 && price <= tp)
            tp = price - minStopDist;
    }

    // Full restore of stops 
    if(trade.PositionModify(ticket, sl, tp))
    {
        PrintFormat("Restored SL/TP for #%I64u | SL=%.5f, TP=%.5f", ticket, sl, tp);
        return true;
    }
    else
    {
        PrintFormat("Failed to restore SL/TP for #%I64u | Error=%d", ticket, GetLastError());
        return false;
    }
}

Что делает эта функция

Для каждой сделки с приостановленными стоп-уровнями:

  • восстанавливает исходные SL и TP, если они по-прежнему допустимы;
  • корректирует до ближайшего уровня, если цена уже пересекла исходный уровень;
  • соблюдает установленную брокером минимальную дистанцию до стоп-уровня.


Раздел интеграции — добавление части 2 к части 1

Мы выполним следующее:

  1. добавим входные параметры приостановки;
  2. добавим переменные состояния;
  3. добавим функции SuspendStops() и RestoreStops();
  4. интегрируем их в OnTick() с использованием логики переходов состояния.

В качестве ориентира будем использовать код из части 1.

Добавим новый входной параметр приостановки к существующим параметрам:

input bool   SuspendStopsDuringNews = false;         // Temporarily remove and later restore SL/TP during the news window
//EXISTING INPUTS

input bool   EnableNewsFilter = false;                           // Enable Economic News Filter
input int    NewsMinutesBefore = 5;                              // Minutes before news to restrict
input int    NewsMinutesAfter = 5;                               // Minutes after news to restrict 
input bool   RestrictNewTradesDuringNews = true;                 // Block new trades during news window
input bool   CloseOpenTradesBeforeHighImpactNews = false;        // Close all trades before news
input string SymbolCurrencyOverride = "";                        // Manual currency override e.g. "USD,JPY"
enum ENUM_NEWS_IMPORTANCE_MODE
  {
   NEWS_HIGH_ONLY = 0,
   NEWS_MODERATE_ONLY,
   NEWS_HIGH_AND_MODERATE
  };
input ENUM_NEWS_IMPORTANCE_MODE NewsImportanceMode = NEWS_HIGH_ONLY; // Which importance levels to consider
// Cache reload interval
input int CacheReloadHours = 6;                                      // How often to reload calendar cache (hours)

Добавим ранее приведенную структуру и глобальные переменные:

// EXISTING GLOBALS
MqlCalendarValue TodayEvents[];    // Calendar cache
datetime lastCalendarLoad = 0;
CTrade  trade;                     // CTrade instance for order management

// NEWLY ADDED [part 2]
// Structure to store removed stop information
struct SavedStops
{
   ulong ticket;        // Trade ticket number
   double sl;           // Original stop loss
   double tp;           // Original take profit
};
SavedStops savedStops[];

bool     newsSuspended = false;

Добавим ранее описанные функции приостановки и восстановления.

Разместим ранее описанные функции приостановки и восстановления ниже функций части 1.

4. Интеграция в OnTick

Почему необходимо реструктурировать OnTick

В части 1 сейчас используются флаг bool isNews, переменная-защелка закрытия сделок и сброс по окончании новостей. Для сценария с закрытием сделок этого достаточно, но во второй части вводится более сложный механизм: необходимо точно определять начало и окончание новостного окна. Это необходимо, поскольку удаление стоп-уровней должно выполняться один раз при начале новостного окна, а восстановление — один раз после его окончания.

Вводятся две переменные:

currentNewsState — состояние, которое система видит в данный момент;

lastNewsState — состояние, которое система видела на предыдущем тике.

Если эти два значения различаются, произошел переход состояния. Переход означает, что новостное окно либо только что началось, либо только что завершилось.

Итоговая функция OnTick

Ниже приведен интегрированный код, заменяющий новостной блок из части 1. Благодаря этому части 1 и 2 остаются объединенными.

//+------------------------------------------------------------------+
//| OnTick                                                           |
//+------------------------------------------------------------------+
void OnTick()
  {
// Main News Logic
   if(EnableNewsFilter)
     {
      // Track previous state of the news window
      static bool lastNewsState = false;

      bool currentNewsState = (EnableNewsFilter && IsNewsTime(_Symbol));

      // Detect state transition
      if(currentNewsState != lastNewsState)
        {
         if(currentNewsState) // News window has just started
           {
            Print("--- NEWS WINDOW STARTED ---");

            // Part 1 Feature: Close trades if enabled
            if(CloseOpenTradesBeforeHighImpactNews)
              {
               Print("Closing all trades due to high impact news setting.");
               CloseAllTradesForSymbol(_Symbol);
              }

            // Part 2 Feature: Suspend SL/TP if enabled
            if(SuspendStopsDuringNews)
              {
               Print("Freezing trade management (SL/TP).");
               SuspendStops(true);
              }
           }
         else // News window has just ended
           {
            Print("--- NEWS WINDOW ENDED ---");

            // Part 2 Feature: Restore SL/TP
            if(SuspendStopsDuringNews)
              {
               Print("Restoring normal trade management.");
               SuspendStops(false);
              }
           }

         // Update last state after handling transition
         lastNewsState = currentNewsState;
        }
     }
  }

Переменная-защелка tradesClosedForThisNewsWindow удалена, проверка закрытия на каждом тике исключена, а вместо нее используется модель переходов состояния: одно выполнение при начале или окончании каждого окна.

Новое поведение системы

При начале новостного окна система при необходимости закрывает сделки и удаляет SL и TP. После окончания новостного окна SL и TP восстанавливаются.

Ниже приведено изображение с настройками новостного фильтра.

Настройка модификации стопов

Настройки новостного фильтра

Print statements during a news window

Пример сообщений Print в период действия новостного окна

Важное замечание

  • В начале логики открытия сделок или логики обработки сделок вызовите:

if(!CanOpenNewTrade(_Symbol))
    return;

  • Создайте магическое число, чтобы все модификации затрагивали только сделки, совершенные этим советником.

input int magicNumber = 12345;

//--- in SuspendStops and CloseAllTradesForSymbol, filter by magic:

if (PositionSelectByTicket(ticket) &&
   PositionGetInteger(POSITION_MAGIC) == magicNumber)
  • Эта реализация предназначена для односимвольных советников. Она не будет корректно работать для мультисимвольных советников, торгующих несколькими символами одновременно, поскольку восстановление стоп-уровней зависит от текущего символа графика.


Заключение

Мы устранили технический разрыв между блокировкой открытия новых сделок и безопасным управлением существующими позициями во время новостей. Предложенное решение детерминировано и готово к интеграции: структура SavedStops для каждого тикета сохраняет исходные SL и TP в памяти; флаг приостановки и модель переходов состояния обеспечивают однократное выполнение при начале и окончании новостного окна; SuspendStops() однократно удаляет SL и TP, а RestoreStops() восстанавливает стоп-уровни с учетом текущей цены и минимальной дистанции, заданной брокером. Этот механизм сохраняет исходную структуру сделки, когда это возможно. Если цена пересекла сохраненный уровень, используется предсказуемый запасной сценарий — устанавливается ближайший допустимый уровень.

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

Ниже приведено изображение с выводом операторов Print() во время работы новостного окна.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/21446

Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (2)
Retail Trading Realities LTD
Philip Kym Sang Nelson | 7 апр. 2026 в 15:16

Как я планирую использовать эти функции:

Я планирую использовать часть 1 статьи — «Предотвращение открытия новых сделок или закрытия открытых позиций в период ограничения торговли из-за новостей» — во всех своих советниках, запущенных на счетах проп-фирм.

Однако части 2 и 3 — удаление SL/TP, а затем их восстановление до и после периода ограничений на торговлю из-за новостей — я планирую использовать в отдельном советнике. Поскольку этот код проходит по всем открытым позициям на счетах, у меня может быть открыто более одного графика, и мне не нужно запускать его больше раз, чем необходимо. Я вручную перенастрою выбор символов на «USD, GBP, EUR», так как это единственные новости из «красной папки», которые, как я знаю по опыту, мне уже приходится фильтровать (у вас это будет по-другому).

Поэтому внес однострочное изменение в функцию RestoreStops().

Функция SuspendStops() не требовала изменений.

Судя по всему, мне не придется ничего менять в Части 3, так как мне нужны только: номер тикета, SL и TP.

Большое спасибо @Solomon Anietie Sunday

Я протестирую это в реальном режиме на демо-счете!

// I won't need this if statement, in the 2nd EA, as the 2nd EA only modifies trades, 
// only need this is statement in the first EA (that opens trades)

if(!CanOpenNewTrade(_Symbol))
    return;
 
//+------------------------------------------------------------------+
//| Восстановление остановок после новостей (редактированная версия статьи для оригинала)      |
//+------------------------------------------------------------------+
bool RestoreStops(ulong ticket, double sl, double tp)
{
    if (!PositionSelectByTicket(ticket))
      return(false);
    string   symbol= PositionGetString(POSITION_SYMBOL);  // заменили исходную переменную «_Symbol» на «symbol»
    ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
    double price = (type == POSITION_TYPE_BUY) ?
        SymbolInfoDouble(symbol, SYMBOL_BID) :  //например, «_Symbol» теперь называется symbol
        SymbolInfoDouble(symbol, SYMBOL_ASK);
        
    double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
    
    double minStopDist = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;

    // Проверка безопасности: если цена пробила сохраненные уровни SL/TP, скорректируйте их до допустимых значений
    if(type == POSITION_TYPE_BUY)
    {
        if(sl != 0 && price <= sl)
            sl = price - minStopDist;
        if(tp != 0 && price >= tp)
            tp = price + minStopDist;
    }
    else // ПРОДАЖА
    {
        if(sl != 0 && price >= sl)
            sl = price + minStopDist;
        if(tp != 0 && price <= tp)
            tp = price - minStopDist;
    }

    // Полное восстановление остановок 
    if(trade.PositionModify(ticket, sl, tp))
    {
        PrintFormat("Restored SL/TP for #%I64u | SL=%.5f, TP=%.5f", ticket, sl, tp);
        return true;
    }
    else
    {
        PrintFormat("Failed to restore SL/TP for #%I64u | Error=%d", ticket, GetLastError());
        return false;
    }
}
Solomon Anietie Sunday
Solomon Anietie Sunday | 19 апр. 2026 в 21:27
Да! Это очень эффективный подход. Вы также можете использовать «магическое число» для блокировки определённых советников. Однако сосредоточение внимания на трёх основных инструментах, которыми вы торгуете, особенно на тех, что характеризуются наибольшей волатильностью, может стать надёжным способом защиты вашего портфеля в целом.
Решение, описанное в этой серии статей, при правильном внедрении может стать очень гибким и настраиваемым.
Тестирование можно проводить на исторических данных (бэктест), но это непросто и требует определённых усилий. Я постараюсь предоставить соответствующую информацию в следующей статье для тех, кто хочет проводить бэктестирование с учётом новостных событий.

Не за что, Филип. Я всегда готов обсудить с вами любые вопросы, связанные с алгоритмической торговлей.

Отвечаю с небольшим опозданием, иногда бываю занят... извините.
Освоение массивов премии и дисконта: Оптимизация торговли по дисбалансам в PD-массивах Освоение массивов премии и дисконта: Оптимизация торговли по дисбалансам в PD-массивах
В этой статье рассматривается специализированный трендовый советник, а также подробно объясняется, как формировать и использовать торговые сетапы, возникающие на основе дисбалансов, обнаруженных в PD-массивах. В этой статье будет подробно рассмотрен советник, специально разработанный для трейдеров, которые стремятся оптимизировать и использовать PD-массивы и дисбалансы в качестве критериев входа в сделки и принятия торговых решений. Кроме того, в статье будет рассмотрено, как правильно размечать и оценивать премиальные и дисконтные массивы, как подтверждать их валидность и использовать каждый из них в соответствующих рыночных условиях, чтобы по максимуму использовать возникающие в таких сценариях возможности.
Свинговые экстремумы и откаты в MQL5 (Часть 2): Автоматизация стратегии с помощью советника Свинговые экстремумы и откаты в MQL5 (Часть 2): Автоматизация стратегии с помощью советника
Индикатор свинговых экстремумов и откатов (Swing Extremes and Pullbacks) основан на рыночной структуре младшего таймфрейма и затем согласовывается со старшим таймфреймом. Он выявляет свинговые экстремумы, в которых цена становится статистически уязвимой к развороту. Он визуализирует зоны перерастяжения и отката, позволяя заранее оценить поведение цены при возврате к среднему.
Единый пайплайн валидации для защиты от переобучения бэктеста Единый пайплайн валидации для защиты от переобучения бэктеста
В статье объясняется, почему стандартный метод пошагового тестирования (walk-forward) и k-блочная кросс-валидация завышают результаты на финансовых данных, а затем показано, как это исправить. Валидация внутри валидации (V-in-V) обеспечивает строгое разбиение данных и пошаговое тестирование с фиксированным началом (anchored) между окнами. Комбинаторно очищенная кросс-валидация (CPCV) устраняет утечки данных с помощью очистки и эмбарго, одновременно агрегируя результативность на уровне траекторий бэктеста. Комбинаторно симметричная кросс-валидация (CSCV) измеряет вероятность переобучения бэктеста (PBO). Практикующие специалисты получают целостную систему для оценки устойчивости к рыночным режимам и надежности отбора кандидатов.
Вероятностный метод главных компонент на MQL5 Вероятностный метод главных компонент на MQL5
Рассмотрены классический PCA и его вероятностная формулировка (PPCA). Представлен универсальный класс CPPCA для MQL5 с тремя алгоритмами обучения (EIG, SVD, EM). Выполнено сопоставление результатов со scikit-learn и разобраны подходы к выбору числа главных компонент (Scree Plot, AIC/BIC, кросс-валидация). Показано применение метрики Score (средний логарифм правдоподобия) для обнаружения смены распределения данных.