Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 2738

 
Sergey Gridnev #:
Потому что,  если целое разделить на целое, то получается целое без остатка. 
40 / 100 = 0
После этого результат записывается в переменную с типом double,  при этом происходит неявное преобразование  0 -> 0.0

Но если целое делить на double, то сначала происходит преобразование целого в double,  а только потом - деление. 
40 -> 40.0
40.0 /  100.0 = 0.4
Большое спасибо. Теперь это буду учитывать.
 
Добрый день!
Не могу создать условие для закрытия........
Как вместе с закрытием позиций по Тейк Профиту с магиком - например 123, закрыть остальные позиции с другим магиком например - 321, на которых нет Тейк Профита
 
Sprut 185 #:
Добрый день!
Не могу создать условие для закрытия........
Как вместе с закрытием позиций по Тейк Профиту с магиком - например 123, закрыть остальные позиции с другим магиком например - 321, на которых нет Тейк Профита

В чём? В мт4 или мт5?

если в мт5, то попробуй это

//+------------------------------------------------------------------+
//|                                               CloseByMagicTP.mq5 |
//|                        Закрывает позиции без TP при срабатывании |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026"
#property link      ""
#property version   "1.00"

//--- Входные параметры: магики, которые нужно связать между собой
input int MagicToTrigger = 123; // Магик позиции, чей TP запускает процесс
input int MagicToClose   = 321; // Магик позиций, которые нужно закрыть принудительно

//--- Переменные для предотвращения рекурсии (чтобы закрытие позиций само не вызывало новые проверки)
bool IsClosingPositions = false;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("Эксперт запущен. Ожидание закрытия позиции #", MagicToTrigger, " по TP...");
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
   // Выходим, если уже идет процесс закрытия других позиций, чтобы избежать зацикливания
   if(IsClosingPositions) return;
   
   // Нас интересует только добавление новой сделки (исполнение ордера)
   if(trans.type!=TRADE_TRANSACTION_DEAL_ADD) return;
   
   // Получаем тикет сделки
   ulong deal_ticket=trans.deal;
   
   // Выбираем сделку по тикету для получения её свойств
   if(HistoryDealSelect(deal_ticket)==false) 
     {
      Print("Ошибка выбора сделки ", deal_ticket, ": ", GetLastError());
      return;
     }
      
   // Фильтруем сделки на выход (закрытие/частичное закрытие)
   long entry_type = HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
   if(entry_type != DEAL_ENTRY_OUT) return;

   // Проверяем причину закрытия (должен быть Take Profit)
   long reason = HistoryDealGetInteger(deal_ticket, DEAL_REASON);
   if(reason != DEAL_REASON_TP) return;

   // Проверяем магик закрытой позиции
   long closed_magic = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
   if(closed_magic != MagicToTrigger) return;

   // --- Все условия выполнены: позиция с нужным магиком закрыта по TP ---
   PrintFormat("Обнаружено закрытие позиции #%lld (M:%d) по TP. Запускаю проверку позиций M:%d.", 
               HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID), 
               MagicToTrigger, MagicToClose);
               
   ProcessForcedClosure();
  }

//+------------------------------------------------------------------+
//| Функция принудительного закрытия позиций                         |
//+------------------------------------------------------------------+
void ProcessForcedClosure()
  {
   IsClosingPositions = true; // Блокируем повторный вход до завершения цикла
   
   int total = PositionsTotal();
   for(int i = total - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0) continue;
      
      // Выбираем позицию для работы со свойствами
      if(PositionSelectByTicket(ticket) == false) continue;
      
      // Фильтр по символу (если торгуете несколькими инструментами)
      if(PositionGetString(POSITION_SYMBOL) != Symbol()) continue;
      
      // Фильтр по нужному магику
      if((long)PositionGetInteger(POSITION_MAGIC) != MagicToClose) continue;
      
      // Главный фильтр: закрываем только те, у кого НЕТ Тейк Профита
      double tp_price = PositionGetDouble(POSITION_TP);
      if(tp_price > 0) continue; 
      
      ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
      string comment = "[Closed by EA]";
      
      bool success = false;
      
      if(type == POSITION_TYPE_BUY)
        {
         // Расчет цены Stop Loss минимально допустимой (на уровне Bid), чтобы приказ точно прошел
         double sl_price = SymbolInfoDouble(Symbol(), SYMBOL_BID) - SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) * Point();
         
         // Пытаемся изменить SL перед закрытием (опционально, иногда помогает обойти фильтры брокера)
         trade.PositionModify(ticket, sl_price, 0); 
         Sleep(100); // Небольшая пауза
         
         // Закрываем позицию по рынку
         success = trade.PositionClose(ticket);
        }
      else if(type == POSITION_TYPE_SELL)
        {
         double sl_price = SymbolInfoDouble(Symbol(), SYMBOL_ASK) + SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) * Point();
         trade.PositionModify(ticket, sl_price, 0);
         Sleep(100);
         success = trade.PositionClose(ticket);
        }
        
      if(!success)
        {
         Print("Не удалось закрыть позицию ", ticket, ". Код ошибки: ", GetLastError(), ". Текст: ", ResultRetcodeDescription(GetLastError()));
        }
      else
        {
         Print("Позиция ", ticket, " успешно закрыта.");
        }
        
      // Важно: небольшая задержка, чтобы сервер успел обработать запрос и не отклонил следующие из-за высокой частоты
      Sleep(500); 
     }
     
   IsClosingPositions = false; // Снимаем блокировку
  }

//+------------------------------------------------------------------+
//| Вспомогательная функция для описания ошибок                      |
//+------------------------------------------------------------------+
string ResultRetcodeDescription(uint retcode)
  {
   switch(retcode)
     {
      case 10004: return "Торговля выполнена полностью";
      case 10006: return "Запрос отклонен";
      case 10007: return "Запрос отменен трейдером";
      case 10008: return "Ордер размещен";
      case 10009: return "Запрос обработан";
      case 10010: return "Цена изменилась";
      case 10011: return "Отсутствуют котировки для обработки запроса";
      case 10012: return "Автоматический торговый бот запрещен";
      case 10013: return "Неправильный объем";
      case 10014: return "Неверная цена";
      case 10015: return "Неверные стопы";
      case 10016: return "Неправильная дата истечения";
      case 10017: return "Торговый поток занят";
      case 10018: return "Рынок закрыт";
      case 10019: return "Торговые ограничения";
      case 10020: return "Недостаточно средств";
      case 10021: return "Цены изменились слишком сильно";
      case 10022: return "Уровень стопов изменился";
      case 10023: return "Объем увеличился";
      case 10024: return "Некоторое время ничего не запрашивалось";
      case 10025: return "Активирован контроль активации";
      case 10026: return "Подключение к торговому серверу было разорвано";
      case 10027: return "Слишком частые запросы";
      case 10028: return "В торговой политике счета запрещена работа с помощью торговых роботов";
      default:    return "Код ошибки: "+IntegerToString(retcode);
     }
  }

//+------------------------------------------------------------------+
 
Igor Nagorniuk #:

В чём? В мт4 или мт5?

если в мт5, то попробуй это

Добрый день!
Это в МТ5, но не совсем, то что надо..........
Есть две функции:
Одна где закрываются позиции по ТП с магиком - MagikMrtn
 и другая, которая закрывает все остальные позиции с магиками -  Magik и MagikPrmd.
При каких условиях должно это отработать - я не могу сформулировать, просто какой то стопор.
Помогите пожалуйста разобраться.

void PosClos(ENUM_POSITION_TYPE PosTp) // функция с магиками Magik и MagikPrmd
  {
   for(int ic = PositionsTotal()-1; ic >= 0; ic --) // определяем количество текущих позиций
     {
      if(PositionGetSymbol(ic) == _Symbol && PositionGetInteger(POSITION_TYPE) == PosTp && PositionGetInteger(POSITION_MAGIC) == Magik && PositionGetInteger(POSITION_MAGIC) == MagikPrmd) // выбираем позицию для дальнейшего доступа к ее свойствам
         c_trade.PositionClose(c_posit.Ticket()); // и закрываем позиции
     }
  } 
void MartSym() // функция с магиком MagikMrtn
  {
   double Mart_B = 0.0; // создаем переменную Mart_B с нулевым значением для общего профита и свопа - в Buy
   double Mart_S = 0.0; // создаем переменную Mart_S с нулевым значением для общего профита и свопа - в Sell
     {
      for(int ip = PositionsTotal() -1; ip >= 0; ip--) // колличесво циклов (ордеров), условие выполнения цыкла, счетчик циклов
        {
         if(PositionGetSymbol(ip) == _Symbol && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC) == MagikMrtn) // выбираем позицию для дальнейшего доступа к ее свойствам
            Mart_B += c_posit.Profit() + c_posit.Swap(); // прибавляем к Mart_BS общий профит плюс общий своп
         //---
         if(PositionGetSymbol(ip) == _Symbol && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC) == MagikMrtn) // выбираем позицию для дальнейшего доступа к ее свойствам
            Mart_S += c_posit.Profit() + c_posit.Swap(); // прибавляем к Mart_BS общий профит и общий своп
        }
     }
   if(Total_ByMn > 1) // если кол-во позиций в Buy по Мартину - больше одной
      LinePrib_By_Sl(Mart, 33); // то исполняем функцию построения Tейк Профита в Buy
//---
   if(Total_SlMn > 1) // если кол-во позиций в Sell по Мартину - больше одной
      LinePrib_By_Sl(Mart, 44); // то исполняем функцию построения Tейк Профита в Sell
//----------------------------------------------------------------------------------------------------------------------------------------------//
  // if(Total_ByMn > 0 && Mart_B >= Mart)  // если кол-во позиций в Buy больше нуля и общий ппрофит больше, или ровно закрытию по Мартину (НЕ МОГУ ОПРЕДЕЛИТЬСЯ С УСЛОВИЕМ ДЛЯ ЗАКРЫТИЯ)
      PosClos(POSITION_TYPE_BUY); // то используем функцию для закрытия позиций
//---
 //  if(Total_SlMn > 0 && Mart_S >= Mart)  // если кол-во позиций в Sell больше нуля и общий ппрофит больше, или ровно закрытию по Мартину (НЕ МОГУ ОПРЕДЕЛИТЬСЯ С УСЛОВИЕМ ДЛЯ ЗАКРЫТИЯ)
      PosClos(POSITION_TYPE_SELL); // то используем функцию для закрытия позиций
  }
 
Sprut 185 #:
for(int ic = PositionsTotal()-1; ic >= 0; ic --) // определяем количество текущих позиций      {       if(PositionGetSymbol(ic) == _Symbol && PositionGetInteger(POSITION_TYPE) == PosTp && PositionGetInteger(POSITION_MAGIC) == Magik && PositionGetInteger(POSITION_MAGIC) == MagikPrmd) // выбираем позицию для дальнейшего доступа к ее свойствам          c_trade.PositionClose(c_posit.Ticket()); // и закрываем позиции      }
for(int ic = PositionsTotal()-1; ic >= 0; ic --) // определяем количество текущих позиций
     {
      if(PositionGetSymbol(ic) == _Symbol && PositionGetInteger(POSITION_TYPE) == PosTp && (PositionGetInteger(POSITION_MAGIC) == Magik || PositionGetInteger(POSITION_MAGIC) == MagikPrmd)) // выбираем позицию для дальнейшего доступа к ее свойствам
         c_trade.PositionClose(c_posit.Ticket()); // и закрываем позиции
     }
 
Sprut 185 #:

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

Ошибки в функции PosClos

В этой строке кода содержится фундаментальная ошибка: ...PositionGetInteger(POSITION_MAGIC) == Magik && PositionGetInteger(POSITION_MAGIC) == MagikPrmd)

Позиция не может иметь два разных магических числа одновременно. Это условие никогда не выполнится (оно всегда будет ложным). Чтобы закрыть позиции с любым из этих магиков, нужно использовать оператор "ИЛИ" ( || ) или проверять принадлежность к массиву/списку.

Также вы используете переменную c_posit.Ticket() , но нигде внутри цикла она не инициализируется через PositionGetTicket(ic) .

Косяк вот в чём, в логике условий закрытия 

Вы хотите реализовать следующую схему: когда сетка ордеров по Мартину (магик MagikMrtn ) закрывается по суммарному профиту, нужно принудительно «подчистить» график от остальных зависших ордеров (магики Magik и MagikPrmd ), у которых нет Тейк Профита.

Условия должны быть такими:

  1. Считаем общий финансовый результат (Прибыль + Своп) только для позиций с магиком MagikMrtn .
  2. Если этот результат достигает целевого значения ( Mart ), мы запускаем функцию очистки графика.
  3. Функция очистки должна проходить по всем позициям на символе _Symbol и закрывать те, где магическое число совпадает со списком [Magik, MagikPrmd] . При этом фильтр типа позиции ( BUY или SELL ) лучше убрать, чтобы гарантированно закрыть всё сразу одной функцией, либо вызывать её дважды — отдельно для Buy и Sell.

  4. Вот, думаю, так правильней будет.


    // Предполагаемые глобальные входные параметры
    input int    Magik       = 100;
    input int    MagikPrmd   = 200; 
    input int    MagikMrtn   = 300;
    input double Mart        = 50.0; // Целевая прибыль для сетки мартина
    
    
    //+------------------------------------------------------------------+
    //| Универсальная функция закрытия позиций по списку магиков         |
    //+------------------------------------------------------------------+
    void ClosePositionsByMagic(ENUM_POSITION_TYPE PosTp, const long &magic_list[], int magic_count)
    {
       for(int ic = PositionsTotal() - 1; ic >= 0; ic--)
         {
          ulong ticket = PositionGetTicket(i);
          if(ticket == 0) continue;
          
          // Выбираем позицию для доступа к свойствам
          if(PositionSelectByTicket(ticket) == false) continue;
    
          // Проверка символа и типа позиции
          if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
          if(PositionGetInteger(POSITION_TYPE) != PosTp) continue;
          
          // Получаем магик текущей позиции
          long pos_magic = PositionGetInteger(POSITION_MAGIC);
          
          // Ищем совпадение магика в нашем списке
          bool is_target_magic = false;
          for(int m = 0; m < magic_count; m++)
            {
             if(pos_magic == magic_list[m])
               {
                is_target_magic = true;
                break;
               }
            }
            
          // Если нашли нужный магик — закрываем
          if(is_target_magic)
            {
             c_trade.PositionClose(ticket); 
            }
         }
    }
    
    //+------------------------------------------------------------------+
    //| Основная логика контроля мартингейла                             |
    //+------------------------------------------------------------------+
    void MartSym()
    {
       double total_profit_martin = 0.0;
       
       // Массив магиков, которые нужно закрыть при достижении цели мартином
       long other_magics[2];
       other_magics[0] = Magik;
       other_magics[1] = MagikPrmd;
    
       // --- Шаг 1: Подсчет общего профита именно по сетке Мартина ---
       for(int ip = PositionsTotal() - 1; ip >= 0; ip--)
         {
          ulong ticket = PositionGetTicket(ip);
          if(ticket == 0) continue;
          
          if(PositionSelectByTicket(ticket) == false) continue;
          
          if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
          if(PositionGetInteger(POSITION_MAGIC) != MagikMrtn) continue;
          
          // Суммируем фин. результат всех сделок мартина
          total_profit_martin += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
         }
    
       // --- Шаг 2: Условия срабатывания ---
       // Здесь Total_ByMn и Total_SlMn — это ваши счетчики количества позиций с магиком MagikMrtn
       // (их тоже нужно считать циклом перед этим блоком или внутри него)
    
       // Закрытие BUY направлений
       if(Total_ByMn > 0 && total_profit_martin >= Mart)
         {
          Print("Цель мартина достигнута. Закрываем сетку MRTN и зачищаем другие позиции BUY.");
          // Сначала закрываем саму сетку мартина
          ClosePositionsByMagic(POSITION_TYPE_BUY, &MagikMrtn, 1); 
          // Затем зачищаем остальные магики без учета TP (просто все подряд этого типа)
          ClosePositionsByMagic(POSITION_TYPE_BUY, other_magics, 2);
         }
    
       // Закрытие SELL направлений
       if(Total_SlMn > 0 && total_profit_martin >= Mart)
         {
          Print("Цель мартина достигнута. Закрываем сетку MRTN и зачищаем другие позиции SELL.");
          ClosePositionsByMagic(POSITION_TYPE_SELL, &MagikMrtn, 1);
          ClosePositionsByMagic(POSITION_TYPE_SELL, other_magics, 2);
         }
    }
 

Всем доброго времени суток. Вопрос по тестеру МТ5
Есть в тестере  2 советника. у обоих одинаковый период тестирования. У обоих код со вчерашнего дня не менялся. Вчера оба советника тестировались нормально. Сегодня один советник тестируется нормально. А второй советник не запускается на тестирование. Компилятор говорит НЕТ ИСТОРИИ КОТИРОВОК. Как такое может быть, если другой советник успешно тестируется на той же истории?
Что нужно сделать что бы и второй советник начал запускать тест? Тем более в документации говориться что тестер перед тестирование загружает все котировки автоматически. Всем спасибо за помощь


 
Андрей Кондрашов #:
Всем доброго времени суток. Вопрос по тестеру МТ5
Есть в тестере  2 советника. у обоих одинаковый период тестирования. У обоих код со вчерашнего дня не менялся. Сегодня один советник тестируется нормально. А второй советник не запускается на тестирование. Компилятор говорит НЕТ ИСТОРИИ КОТИРОВОК. Как такое может быть, если другой советник успешно тестируется на той же истории?
Что нужно сделать что бы и второй советник начал запускать тест? Тем более в документации говориться что тестер перед тестирование загружает все котировки автоматически. Всем спасибо за помощь

Нет соединения с сервером брокера. В правом нижнем углу терминала выберите другой сервер.


 
Aleksandr Slavskii #:

Нет соединения с сервером брокера. В правом нижнем углу терминала выберите другой сервер.


Спасибо. Действительно помогло. Я и сам хотел это сделать. Но меня остановило то обстоятельство что второй советник работает нормально. Разве оба советника обращаются не к одному серверу?
 
Андрей Кондрашов #:
Спасибо. Действительно помогло. Я и сам хотел это сделать. Но меня остановило то обстоятельство что второй советник работает нормально. Разве оба советника обращаются не к одному серверу?
Просто так совпало. На тесте первого советника была связь, а потом, когда поставили тестировать второй пропала.