Подскажите как проверить работу кода

[Удален]  
Здравствуйте все! Подскажите пожалуйста как проверить работу кода. На покупке идёт добавление к позиции, трейлинг работает нормально. На продаже добавление также срабатывает, но трейлинг-стоп и тейк-профит слетают. Изначальные показатели ТР и SL одинаковые для обоих типов сделок. Компилятор ошибки и предупреждения не находит. В коде не могу найти логическую ошибку
[Удален]  
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

input  int   ma_periodSlow = 70;
input  int   ma_periodFast = 30;

input  int   whole_array   = 15;
input int    PartialClosePoints = 300;  // столько должна пройти цена для активации частичного закрытия позиции
input double AdditionFactor = 4; // множитель на сколько надо добавить позицию (0,5 = половина позиции)

//+------------------------------------------------------------------+
//| Defines                                                          |
//+------------------------------------------------------------------+
MqlRates bar[];

//+------------------------------------------------------------------+
//| Includes                                                         |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>


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

double last_price = 0;
double eStep      = 0;



MqlTick currentTick;          //текущий тик символа
CTrade trade;                 //объект открытия закрытия позиций


//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
input group "==== General ====";
static input long   InpMagicnumber = 123456789; //магическое число
static input double InpLots        = 1;      //размер лота
input int           InpStopLoss    = 100;      // стоплосс в пунктах (0=выключение)
input int           InpTakeProfit  = 100;      // тэйкпрофит в пунктах (0=выключение)
input ushort        Step           = 20;

 //+------------------------------------------------------------------+
//| Defines                                                          |
//+------------------------------------------------------------------+
MqlRates bar[];

//+------------------------------------------------------------------+
//| Includes                                                         |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>


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

double last_price = 0;
double eStep      = 0;



MqlTick currentTick;          //текущий тик символа
CTrade trade;                 //объект открытия закрытия позиций


//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
input group "==== General ====";
static input long   InpMagicnumber = 123456789; //магическое число
static input double InpLots        = 1;      //размер лота
input int           InpStopLoss    = 100;      // стоплосс в пунктах (0=выключение)
input int           InpTakeProfit  = 100;      // тэйкпрофит в пунктах (0=выключение)
input ushort        Step           = 20;



//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ArraySetAsSeries(bar,true);

//проверка входных данных
   if(!CheckInputs())
     {
      return INIT_PARAMETERS_INCORRECT;
     }

//получение магического числа
   trade.SetExpertMagicNumber(InpMagicnumber);



   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   CopyRates(_Symbol,PERIOD_CURRENT,0,5,bar);

//создаем массив цен
   double priceEMAmassiveSlow[];
   double priceEMAmassiveFast[];


   int  priceEMASlow = iMA(_Symbol,_Period,ma_periodSlow,0,MODE_EMA,PRICE_CLOSE);
   int  priceEMAFast = iMA(_Symbol,_Period,ma_periodFast,0,MODE_EMA,PRICE_CLOSE);


//установим сортировку цен в массиве от текущей свечи
   ArraySetAsSeries(priceEMAmassiveSlow,true);
   ArraySetAsSeries(priceEMAmassiveFast,true);


//Параметры MA - линия - текущая свеча, 3 свечи - сохраним результат
   CopyBuffer(priceEMASlow,0,0,3,priceEMAmassiveSlow);
   CopyBuffer(priceEMAFast,0,0,3,priceEMAmassiveFast);


//определим Ask, Bid
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
//  double posOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
//  double posVolume    = PositionGetDouble(POSITION_VOLUME);
//  ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);


//является ли новый тик тиком открытия нового бара
   if(!IsNewBar())
     {
      return;
     }

//получение тика текущего символа
   if(!SymbolInfoTick(_Symbol,currentTick))
     {
      Print("ошибка получения текущего тика");
      return;
     }

//подсчёт открытых позиций
   int cntBuy, cntSell;
   if(!CountOpenPositions(cntBuy,cntSell))
     {
      Print("ошибка получения подсчёта открытых позиций");
      return;
     }

//проверка для новой позиции на покупку

   if(cntBuy==0 && cntSell==0)
     {
      double Pattern1 = bar[2].open  > bar[2].close && // поглощение
                        bar[1].open  <= bar[2].close &&
                        bar[1].close > bar[2].open &&
                        bar[1].close > priceEMAmassiveFast[0] &&
                        bar[1].open  < priceEMAmassiveFast[0];
      double Pattern2 = bar[3].open  > bar[3].close &&   // три дня изнутри вверх
                        //  bar[3].high  > bar[2].high &&
                        //   bar[2].low   > bar[3].low &&
                        bar[3].open  >= bar[2].close &&   //
                        bar[2].open  >= bar[3].close &&
                        bar[1].close > bar[3].open &&
                        bar[1].close > priceEMAmassiveFast[0] &&
                        bar[1].open  < priceEMAmassiveFast[0];
      double Pattern3 = bar[2].open  > bar[2].close &&  // завеса просвет
                        bar[1].open  < bar[2].close &&
                        bar[2].open  > bar[1].close &&
                        bar[1].close > bar[1].open &&
                        bar[1].close > priceEMAmassiveFast[0] &&
                        bar[1].open  < priceEMAmassiveFast[0];
      double CandlePattern = Pattern1 || Pattern2 || Pattern3;

      if(Ask > priceEMAmassiveFast[0] &&

         priceEMAmassiveFast[0] > priceEMAmassiveSlow[0] &&
         CandlePattern)
        {
         //рассчёт стоплосса и тейкпрофита
         double sl = currentTick.bid - InpStopLoss * _Point;
         double tp = currentTick.bid + InpTakeProfit * _Point;
         if(!NormalizePrice(sl))
           {
            return;
           }
         if(!NormalizePrice(tp))
           {
            return;
           }

         trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,InpLots,currentTick.ask,sl,tp,"свечной паттерн");
        }



     }
//проверка для новой позиции на продажу



   if(cntSell==0 && cntBuy==0)
     {
      double Pattern1 = bar[2].open  < bar[2].close && // поглощение
                        bar[1].open  >= bar[2].close &&
                        bar[1].close < bar[2].open &&
                        bar[1].close < priceEMAmassiveFast[0] &&
                        bar[1].open  > priceEMAmassiveFast[0];
      double Pattern2 = bar[3].open  < bar[3].close && // три дня изнутри вниз
                     // bar[3].high  > bar[2].high &&
                     // bar[2].low   > bar[3].low &&
                        bar[3].open  <= bar[2].close &&  //
                        bar[2].open  <= bar[3].close &&
                        bar[1].close < bar[3].open &&
                        bar[1].close < priceEMAmassiveFast[0] &&
                        bar[1].open  > priceEMAmassiveFast[0];
      double Pattern3 = bar[2].open  < bar[2].close && // завеса просвет
                        bar[1].open  > bar[2].close &&
                        bar[2].open  < bar[1].close &&
                        bar[1].close < bar[1].open &&
                        bar[1].close < priceEMAmassiveFast[0] &&
                        bar[1].open  > priceEMAmassiveFast[0];
      double CandlePattern = Pattern1 || Pattern2 || Pattern3;

      if(Bid < priceEMAmassiveFast[0] &&

         priceEMAmassiveFast[0] < priceEMAmassiveSlow[0] &&
         CandlePattern)
        {
         //рассчёт стоплосса и тейкпрофита
         double sl = currentTick.ask + InpStopLoss * _Point;
         double tp = currentTick.ask - InpTakeProfit * _Point;
         if(!NormalizePrice(sl))
           {
            return;
           }
         if(!NormalizePrice(tp))
           {
            return;
           }

         trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,InpLots,currentTick.bid,sl,tp,"свечной паттерн");
        }
     }


//трейлинг стоп!

   for(int i = PositionsTotal()-1; i >=0; i--)
     {
      ulong posTicket = PositionGetTicket(i);
      if(PositionSelectByTicket(posTicket))
        {
         double posSl = PositionGetDouble(POSITION_SL);
         double posTp = PositionGetDouble(POSITION_TP);

         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
              {
               int shift = iHighest(_Symbol,PERIOD_CURRENT,MODE_HIGH,whole_array,1);
               double high = iHigh(_Symbol,PERIOD_CURRENT,shift);
               high = NormalizeDouble(high,_Digits);

               if(high < posSl)
                 {
                  //модификация стоплосса

                  if(trade.PositionModify(posTicket,high,posTp))
                    {
                     Print(__FUNCTION__," > Pos #",posTicket," was modified...");
                    }
                 }
              }
         else
            
            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
           {
            int shift = iLowest(_Symbol,PERIOD_CURRENT,MODE_LOW,whole_array,1);
            double low = iLow(_Symbol,PERIOD_CURRENT,shift);
            low = NormalizeDouble(low,_Digits);

            if(low > posSl)
              {
               //модификация стоплосса

               if(trade.PositionModify(posTicket,low,posTp))
                 {
                  Print(__FUNCTION__," > Pos #",posTicket," was modified...");
                 }
              }
           }
        }



      double posOpenPrice         = PositionGetDouble(POSITION_PRICE_OPEN);
      double posVolume            = PositionGetDouble(POSITION_VOLUME);
      ENUM_POSITION_TYPE posType  = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

      //частичное закрытие позиции или добавление
      if(posVolume == InpLots)
        {
         double lotsToAddition = posVolume * AdditionFactor;
         lotsToAddition = NormalizeDouble(lotsToAddition,2);
        
         if(posType == POSITION_TYPE_SELL)
           {
            if(Ask < posOpenPrice - PartialClosePoints*_Point)
              {
               trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,lotsToAddition,currentTick.bid,0,0,"добавление");
               return;
              }
           }

         else
            if(posType == POSITION_TYPE_BUY)
              {
               if(Bid > posOpenPrice + PartialClosePoints*_Point)
                 {
                  trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,lotsToAddition,currentTick.ask,0,0,"добавление");
                  return;
                 }
              }
        }
     }
  }








//+------------------------------------------------------------------+
//|  Custom functions                                                |
//+------------------------------------------------------------------+



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CheckInputs()
  {
   if(InpMagicnumber<=0)
     {
      Alert("неправильные вводные: Магическое число <=0");
      return false;
     }
   if(InpLots<=0)
     {
      Alert("неправильные вводные: Лот <=0");
      return false;
     }
   if(InpStopLoss<0)
     {
      Alert("неправильные вводные: StopLoss <0");
      return false;
     }
   if(InpTakeProfit<0)
     {
      Alert("неправильные вводные: TakeProfit <0");
      return false;
     }


   return true;
  }


//проверка если имеем тик бара открытия
bool IsNewBar()
  {
   static datetime previousTime = 0;
   datetime currentTime = iTime(_Symbol,PERIOD_CURRENT,0);
   if(previousTime!=currentTime)
     {
      previousTime=currentTime;
      return true;
     }
   return false;
  }

//подсчёт открытых позиций
bool CountOpenPositions(int &cntBuy, int &cntSell)
  {
   cntBuy  = 0;
   cntSell = 0;
   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket<=0)
        {
         Print("Ошибка получения тикета позиции");
         return false;
        }
      if(!PositionSelectByTicket(ticket))
        {
         Print("ошибка выбора позиции");
         return false;
        }
      long magic;
      if(!PositionGetInteger(POSITION_MAGIC,magic))
        {
         Print("ошибка получения магического номера позиции");
         return false;
        }
      if(magic==InpMagicnumber)
        {
         long type;
         if(!PositionGetInteger(POSITION_TYPE,type))
           {
            Print("ошибка получения типа позиции");
            return false;
           }
         if(type==POSITION_TYPE_BUY)
           {
            cntBuy++;
           }
         if(type==POSITION_TYPE_SELL)
           {
            cntSell++;
           }
        }
     }
   return true;
  }

// нормализация цены
bool NormalizePrice(double &price)
  {
   double tickSize=0;
   if(!SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE,tickSize))
     {
      Print("ошибка получения размера тика");
      return false;
     }
   price = NormalizeDouble(MathRound(price/tickSize)*tickSize,_Digits);
   return true;
  }
//+------------------------------------------------------------------+
z
Discover new MetaTrader 5 opportunities with MQL5 community and services
Discover new MetaTrader 5 opportunities with MQL5 community and services
  • 2025.11.28
  • www.mql5.com
MQL5: language of trade strategies built-in the MetaTrader 5 Trading Platform, allows writing your own trading robots, technical indicators, scripts and libraries of functions
[Удален]  
вырезка из журнала
Файлы:
 
Неизвестно, что у Вас в коде, но так на вскидку если buy, работает корректно, а sell нет, то возможно, у Вас при sell переменная, которая потом сравнивается с текущей ценой инициализируется 0, а должна быть установлена в DBL_MAX
[Удален]  
Aleksei Stepanenko #:
Неизвестно, что у Вас в коде, но так на вскидку если buy, работает корректно, а sell нет, то возможно, у Вас при sell переменная, которая потом сравнивается с текущей ценой инициализируется 0, а должна быть установлена в DBL_MAX

Спасибо за ответ. Мысль вашу понял. Код в комментарии выше.

 
А вот код появился. Кроме проверки, что high ниже стопа, чтобы поменять стоп на этот high, необходимо убедиться, что текущая цена находиться ниже этого high не менее двух спредов. При чем, для buy  сравнивайте с ценой  bid, а для sell с ask. 

[Удален]  
Aleksei Stepanenko #:
А вот код появился. Кроме проверки, что high ниже стопа, чтобы поменять стоп на этот high, необходимо убедиться, что текущая цена находиться ниже этого high не менее двух спредов. 
Просто на покупке, когда лоу выше стопа, то трейлинг меняется. а коды аналогичные. но на продажу не срабатывает.
 
График рисуется по bid, и цена не может быть ниже low, а цена ask запросто может быть больше high. Поэтому у Вас стоп для sell не переносится. 
[Удален]  
Aleksei Stepanenko #:
График рисуется по bid, и цена не может быть ниже low, а цена ask запросто может быть больше high. Поэтому у Вас стоп для sell не переносится. 
как тогда это исправить подскажите пожалуйста
[Удален]  
teleskoper #:
как тогда это исправить подскажите пожалуйста
добавлять спреды?
 
Я сейчас не у компа, готовым кодом не помогу,  сделайте примерно так:
 Получите  ask и bid из структуры MqlTick, дальше сравнивайте if(posSl- high>0 && high-2*ask+bid>0) , что означает что high выше верхней цены  ask не менее, чем на один спред. Тоже самое  нужно сделать для buy позиции.