Пятница 13-е мая

 

Привет. Вот что произошло. Робот  Ilan_mql5.mq5 нормально до 13 мая 2016. Потом начал совершать сделки без учета выставленных колен, одну за другой. Хорошо, что комп был перед глазами был и я вовремя все остановил. Проверил робота на дэмо- все работает, в реале - глючит. Помогите. Вот он

//+------------------------------------------------------------------+
//|                                                    Ilan_mql5.mq5 |
//|                         Copyright © 2011, Tarakan Software Corp. |
//+------------------------------------------------------------------+

#property copyright "Copyright © 2011, Tarakan Software Corp."
#property version   "1.00"

#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>

//---

input     double  TakeProfit       = 10;          // TakeProfit в пунктах
input     double  PipStep          = 30;          // Размер шага открытия колен
input     double  Lots             = 0.10;        // Начальный объем лота
input     int     LotDecimal       = 2;           // Количество знаков после запятой в объеме лота
input     double  LotExponent      = 1.40;        // Экспонента увеличения объема лота
input     int     MagicNumber      = 70707;       // Магический номер советника
input     int     MaxTrades        = 8;           // Максимальное количество открытых колен
input     int     Slip             = 3;           // Проскальзывание

/*input*/ bool    UseTrailingStop  = false;       // Использовать TrailingStop
/*input*/ int     TrailStart       = 10;          // Прибыль в пунктах, необходимая для старта трала
/*input*/ int     TrailStop        = 10;          // StopLoss в пунктах, выставляемый при трале

/*input*/ bool    UseEquityStop    = false;       // Использовать ограничение на убыток
/*input*/ double  TotalEquityRisk  = 50.0;        // Максимальный убыток в процентах от депозита

/*input*/ bool    UseTimeOut       = false;       // Использовать ограничение на время жизни позиции
/*input*/ double  MaxTradeOpenHours = 48;         // Максимальное время жизни позиции в часах

//+------------------------------------------------------------------+

//double     Spread;

datetime   Expiration;
double     LotSize;
int        TotalOrders;
bool       TradeNow = false, LongTrade = false, ShortTrade = false;
bool       NewOrdersPlaced = false;
double     LastBuyPrice, LastSellPrice;

double     iTakeProfit, iPipStep;
int        iTrailStart, iTrailStop;

bool       Position = false;      // true - есть открытая позиция, false - нет
long       PositionID = 0;        // идентификатор открытой позиции

ulong      LastDealTicket = 0;    // тикет сделки, который мы будем ловить в OnTrade()

bool CanTrade = true;             // запрет торговли до полного исполнения ордера

CTrade Trade;              // класс для совершения торговых операций
CSymbolInfo SymbolInfo;
CPositionInfo PositionInfo;

//+------------------------------------------------------------------+

int OnInit()
  {
   Trade.SetExpertMagicNumber(MagicNumber);
   Trade.SetDeviationInPoints(Slip);
  
   SymbolInfo.Name(_Symbol);
  
   iTakeProfit = TakeProfit;
   iPipStep = PipStep;
   iTrailStart = TrailStart;
   iTrailStop = TrailStop;
   
   // если после запятой пять знаков - коррекция уровней
   if (_Digits == 5 || _Digits == 3)
     {
      iTakeProfit = TakeProfit * 10;
      iPipStep = PipStep * 10;
      iTrailStart = TrailStart * 10;
      iTrailStop = TrailStop * 10;
     }
   
   return(0);
  }
 
//+------------------------------------------------------------------+

void OnDeinit(const int reason)
  {
   return;
  }
 
//+------------------------------------------------------------------+

void OnTick()
  {
   if (!CanTrade) return;
  
   //---------------------------------
  
   // Spread = NormalizeDouble(SymbolInfo.Ask() - SymbolInfo.Bid(), _Digits);
 
   //---------------------------------
 
   // если включен TrailingStop
   
   if (UseTrailingStop)
     TrailPosition(iTrailStart, iTrailStop);
 
   //---------------------------------
   
   // если стоит ограничение на время жизни позиции
  
   if (UseTimeOut && TimeCurrent() >= Expiration)
     {
      Print("Время жизни позиции истекло, принудительное закрытие");
      ClosePosition();  // закрываем позицию
     }
  
   //---------------------------------
   
   // советник работает только по открытиям новых баров
   // если это первый тик на текущем баре значит бар только что открылся
   
   long TickVolume[1];  // массив для тикового объема последнего бара
   
   // получим количество тиков на последнем баре
   if (CopyTickVolume(_Symbol, _Period, 0, 1, TickVolume) != 1)
     {
      Print("Не удалось получить количество тиков на текущем баре");
      return;
     }
   
   // если на текущем баре больше одного тика - выход
   if (TickVolume[0] > 1) return;
   
   //---------------------------------
   
   // если включено ограничение на убыток

   if (UseEquityStop)
     {
      // если потеряно TotalEquityRisk (или больше) процентов депозита - закрываем позицию
      double AccountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
      double AccountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
       
      if (AccountEquity <= AccountBalance * (1 - TotalEquityRisk / 100))
        {
         Print("Потеряно ", TotalEquityRisk, "% депозита, принудительное закрытие позиции");
         ClosePosition();
        }
     }
  
   //---------------------------------
   
   // найдем открытую позицию по текущему финансовому инструменту
   
   if (PositionInfo.Select(_Symbol))
     {
      Position = true;
      PositionID = PositionInfo.Identifier();
     }
   else
     {
      Position = false;
      PositionID = 0;
     }
   
   //---------------------------------
   
   // узнаем направление открытой позиции
   
   if (Position)  // если есть открытая позиция
     {
      if (PositionInfo.PositionType() == POSITION_TYPE_BUY)
        {
         LongTrade = true;
         ShortTrade = false;
        }
      if (PositionInfo.PositionType() == POSITION_TYPE_SELL)
        {
         LongTrade = false;
         ShortTrade = true;
        }
     }
    
   //---------------------------------------
   
   // узнаем количество ордеров в нашей позиции
   
   if (Position) TotalOrders = CountTrades(PositionID);
   else TotalOrders = 0;
   
   //---------------------------------------
   
   // если цена прошла PipStep пунктов против нас - открываем новый ордер
  
   SymbolInfo.RefreshRates();
   
   if (Position && (TotalOrders > 0 && TotalOrders <= MaxTrades))
     {
      // найдем цены открытия последнего ордера Buy и последнего ордера Sell
      LastBuyPrice = FindLastBuyPrice(PositionID);
      LastSellPrice = FindLastSellPrice(PositionID);
       
      if (LongTrade && LastBuyPrice - SymbolInfo.Ask() >= iPipStep * _Point)  // цена ушла вниз
        TradeNow = true;             
             
      if (ShortTrade && SymbolInfo.Bid() - LastSellPrice >= iPipStep * _Point) // цена ушла вверх
         TradeNow = true;
     }  // if (Total > 0 && Total <= MaxTrades)
     
   //---------------------------------------
   
   // если нет открытой позиции - начинаем новую серию
     
   if (!Position)
     {
      ShortTrade = false;
      LongTrade = false;
      TradeNow = true;
     }
     
   //-----------------------------------
   
   // если продолжаем торговую серию
     
   if (Position && TradeNow)
     {
      // размер лота очередного ордера
      LotSize = NormalizeDouble(Lots * MathPow(LotExponent, TotalOrders), LotDecimal);
       
      if (ShortTrade)  // Sell - серия
        {
         if (!Sell(LotSize, SymbolInfo.Bid())) return;  // продаем
         TradeNow = false;
         NewOrdersPlaced = true;  // новый ордер открыт
        }
      else if (LongTrade)  // Buy - серия
        {
         if (!Buy(LotSize, SymbolInfo.Ask())) return;  // покупаем
         TradeNow = false;
         NewOrdersPlaced = true;  // новый ордер открыт
        }
     }  // if (Position && TradeNow)
   
   //-------------------------------
   
   // если начинаем новую торговую серию
    
   if (!Position && TradeNow)  // если нет открытой позиции
     {
      // массив структур для получения информации о ценах последней свечи
      // цвет последней свечи нужен для определения направления открытия первого ордера серии
      MqlRates Rates[1];
       
      // получим цены последней свечи (свечи с индексом 1)
      if (CopyRates(_Symbol, _Period, 1, 1, Rates) != 1)
        {
         Print("Не удалось получить ценовые данные для предпоследней свечи");
         return;
        }
       
      if (!ShortTrade && !LongTrade)
        {
         // размер лота очередного ордера
         LotSize = NormalizeDouble(Lots * MathPow(LotExponent, TotalOrders), LotDecimal);
           
         if (Rates[0].open > Rates[0].close)  // если последняя свеча черная - продаем
           {
            if (!Sell(LotSize, SymbolInfo.Bid())) return;
            NewOrdersPlaced = true;  // новый ордер открыт
           }
         else  // последняя свеча белая - покупаем
           {
            if (!Buy(LotSize, SymbolInfo.Ask())) return;
            NewOrdersPlaced = true;  // новый ордер открыт
           }
        }  // if (!ShortTrade && !LongTrade)
       
      if (NewOrdersPlaced)
        Expiration = (datetime)(TimeCurrent() + PeriodSeconds(PERIOD_H1) * MaxTradeOpenHours);
         
      TradeNow = false;
     }  // if (!Position && TradeNow)
    
   //----------------------------
   
   // установим TakeProfit для нашей позиции
   
   if (NewOrdersPlaced)
     {
      // найдем нашу позицию
      if (!PositionInfo.Select(_Symbol)) return;
       
      double NewTakeProfit = 0;
       
      if (PositionInfo.PositionType() == POSITION_TYPE_BUY)
        {
         if (iTakeProfit > SymbolInfo.StopsLevel())
           NewTakeProfit = PositionInfo.PriceOpen() + iTakeProfit * _Point;
         else
           NewTakeProfit = PositionInfo.PriceOpen() + SymbolInfo.StopsLevel() * _Point;
        }
      else
        {
         if (iTakeProfit > SymbolInfo.StopsLevel())
           NewTakeProfit = PositionInfo.PriceOpen() - iTakeProfit * _Point;
         else
           NewTakeProfit = PositionInfo.PriceOpen() - SymbolInfo.StopsLevel() * _Point;
        }
       
      if (!CompareDouble(PositionInfo.TakeProfit(), NewTakeProfit))
        if (!Modify(0, NewTakeProfit)) return;
       
      NewOrdersPlaced = false;
     }  // if (NewOrdersPlaced)
       
   return;
  }  // --- Exit OnTick() function ---
 
 
//+------------------------------------------------------------------+

// с момента отправки приказа на открытие и до полного совершения сделки торговля запрещена
// здесь мы ловим момент когда сделка состоялась после чего вновь разрешаем советнику торговать

void OnTrade()
  {
   if (LastDealTicket == 0) return;  // небыло приказа на совершение сделки
  
   // получим историю ордеров и сделок за последний час
   datetime EndDate = TimeCurrent();
   datetime StartDate = EndDate - PeriodSeconds(PERIOD_H1);
  
   HistorySelect(StartDate, EndDate);
  
   int Total = HistoryDealsTotal();
   ulong Ticket = HistoryDealGetTicket(Total - 1);  // тикет последней сделки
  
   if (Ticket == LastDealTicket)  // если это наш ордер, значит сделка состоялась
     {
      LastDealTicket = 0;
      CanTrade = true;       // разрешаем торговлю
     }
  }

//+------------------------------------------------------------------+

// возвращает количество сделок позиции, заданной идентификатором id

int CountTrades(long id)
  {
   int   Total;       // количество сделок текущей позиции
   ulong Ticket;      // тикет выбранной сделки из истории
   int   Count = 0;   // количество найденных ордеров
 
   // создадим список ордеров и сделок текущей позиции
   HistorySelectByPosition(id);
   
   // переберем все сделки открытой позиции
   Total = HistoryDealsTotal(); // количество сделок в истории
   
   for (int i = 0; i < Total; i++)
     {
      Ticket = HistoryDealGetTicket(i);  // получим тикет очередной сделки
      if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_IN) // считаем только вход в рынок
        {
         if (HistoryDealGetInteger(Ticket, DEAL_MAGIC) == MagicNumber) Count++;
        }
     }
     
   return(Count);
  }
 
//+------------------------------------------------------------------+

// возвращает суммарный объем ордеров, открытых советником

double CalculateVolume(long id)
  {
   int    Total;         // количество сделок текущей позиции
   ulong  Ticket;        // тикет выбранной сделки из истории
   double Volume = 0;    // суммарный объем ордеров советника
 
   // создадим список ордеров и сделок текущей позиции
   HistorySelectByPosition(id);
   
   // переберем все сделки открытой позиции
   Total = HistoryDealsTotal(); // количество сделок в истории
   
   for (int i = 0; i < Total; i++)
     {
      Ticket = HistoryDealGetTicket(i);  // получим тикет очередной сделки
      if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_IN) // считаем только вход в рынок
        {
         if (HistoryDealGetInteger(Ticket, DEAL_MAGIC) == MagicNumber)
           Volume = Volume + HistoryDealGetDouble(Ticket, DEAL_VOLUME);
        }
     }
     
   return(Volume);
  }

//+------------------------------------------------------------------+

// закрывает все ордеры, открытые советником

bool ClosePosition()
  {
   if (!PositionInfo.Select(_Symbol)) return(false); // нет открытой позиции
  
   SymbolInfo.RefreshRates();
   
   double Volume = NormalizeDouble(CalculateVolume(PositionInfo.Identifier()), LotDecimal);
   ENUM_POSITION_TYPE Type = PositionInfo.PositionType();
  
   if (Type == POSITION_TYPE_BUY)
     {
      if (Trade.Sell(Volume, _Symbol, SymbolInfo.Bid()))
        {
         if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
           {
            CanTrade = false;  // запрещаем торговлю (разрешаем вновь в OnTrade)
            LastDealTicket = Trade.ResultDeal();
            return(true);
           }
        }
     
      Print("Позиция не закрыта, ошибка ", Trade.ResultRetcodeDescription());
      return(false);
     }
   else if (Type == POSITION_TYPE_SELL)
     {
      if (Trade.Buy(Volume, _Symbol, SymbolInfo.Ask()))
        {
         if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
           {
            CanTrade = false;  // запрещаем торговлю (разрешаем вновь в OnTrade)
            LastDealTicket = Trade.ResultDeal();
            return(true);
           }
        }
     
      Print("Позиция не закрыта, ошибка ", Trade.ResultRetcodeDescription());
      return(false);
     }
  
   return(false);
  }
 
//+------------------------------------------------------------------+

// возвращает цену открытия последнего ордера Buy
// для позиции с идентификатором id

double FindLastBuyPrice(long id)
  {
   int  Total;                   // количество сделок в истории
   ulong Ticket;                 // тикет выбранной сделки из истории
   long Entry;                   // направление сделки (IN или OUT)
   long Magic;                   // магический номер сделки
   long Type;                    // тип сделки (BUY или SELL)
   double Price = 0;             // цена сделки
   double LastPrice = 1000000;   // цена сделки, найденн на предыдущей итерации цикла
  
   // создадим список ордеров и сделок текущей позиции
   HistorySelectByPosition(id);
   
   Total = HistoryDealsTotal(); // количество сделок в истории
   
   for (int i = 0; i < Total; i++)
     {
      Ticket = HistoryDealGetTicket(i);  // получим тикет очередной сделки
     
      Entry = HistoryDealGetInteger(Ticket, DEAL_ENTRY);
      Magic = HistoryDealGetInteger(Ticket, DEAL_MAGIC);
      Type  = HistoryDealGetInteger(Ticket, DEAL_TYPE);
      Price = HistoryDealGetDouble(Ticket, DEAL_PRICE);
       
      if (Entry == DEAL_ENTRY_IN && Magic == MagicNumber && Type == DEAL_TYPE_BUY)
        {
         if (Price < LastPrice) LastPrice = Price;
        }
     }
     
   return(LastPrice);
  }
 
//+------------------------------------------------------------------+

// возвращает цену открытия последнего ордера Sell
// для позиции с идентификатором id

double FindLastSellPrice(long id)
  {
   int  Total;                   // количество сделок в истории
   ulong Ticket;                 // тикет выбранной сделки из истории
   long Entry;                   // направление сделки (IN или OUT)
   long Magic;                   // магический номер сделки
   long Type;                    // тип сделки (BUY или SELL)
   double Price = 0;             // цена сделки
   double LastPrice = 0;         // цена сделки, найденн на предыдущей итерации цикла
  
   // создадим список ордеров и сделок текущей позиции
   HistorySelectByPosition(id);
   
   Total = HistoryDealsTotal(); // количество сделок в истории
   
   for (int i = 0; i < Total; i++)
     {
      Ticket = HistoryDealGetTicket(i);  // получим тикет очередной сделки
     
      Entry = HistoryDealGetInteger(Ticket, DEAL_ENTRY);
      Magic = HistoryDealGetInteger(Ticket, DEAL_MAGIC);
      Type  = HistoryDealGetInteger(Ticket, DEAL_TYPE);
      Price = HistoryDealGetDouble(Ticket, DEAL_PRICE);
       
      if (Entry == DEAL_ENTRY_IN && Magic == MagicNumber && Type == DEAL_TYPE_SELL)
        {
         if (Price > LastPrice) LastPrice = Price;
        }
     }
     
   return(LastPrice);
  }

//+------------------------------------------------------------------+

// тралит открытую позицию
// трал включается если прибыль по позиции составляет не меньше trStart пунктов
// StopLoss выставляется на trStop пунктов от текущей цены

void TrailPosition(int trStart, int trStop)
  {
    int CurrentPipsProfit;     // текущая прибыль позиции в пунктах
   
    double OldStopLoss;        // старый уровень StopLoss
    double NewStopLoss;        // новый уровень StopLoss
   
    if (!PositionInfo.Select(_Symbol)) return; // нет открытой позиции
   
    double PositionOpenPrice = PositionInfo.PriceOpen();      // цена открытия позиции
    double PositionTakeProfit = PositionInfo.TakeProfit();    // уровень TakeProfit позиции
   
    SymbolInfo.RefreshRates();
   
    if (PositionInfo.PositionType() == POSITION_TYPE_BUY)  // позиция Buy
      {
        // вычислим прибыль позиции в пунктах
        CurrentPipsProfit = (int)((SymbolInfo.Bid() - PositionOpenPrice) / _Point);
        if (CurrentPipsProfit < trStart) return;
       
        OldStopLoss = PositionInfo.StopLoss();             // текущий StopLoss позиции
        NewStopLoss = SymbolInfo.Bid() - trStop * _Point;  // новый StopLoss позиции
       
        // установим новый уровень StopLoss
        if (OldStopLoss == 0 || (OldStopLoss != 0 && NewStopLoss > OldStopLoss))
          {
           if (!Modify(NewStopLoss, 0)) return;
          }
      }
   
    if (PositionInfo.PositionType() == POSITION_TYPE_SELL)  // позиция Sell
      {
        // прибыль позиции в пунктах
        CurrentPipsProfit = (int)((PositionOpenPrice - SymbolInfo.Ask()) / _Point);
        if (CurrentPipsProfit < trStart) return;
       
        OldStopLoss = PositionInfo.StopLoss();             // текущий StopLoss позиции
        NewStopLoss = SymbolInfo.Ask() + trStop * _Point;  // новый StopLoss позиции
       
        // установим новый уровень StopLoss
        if (OldStopLoss == 0 || (OldStopLoss != 0 && NewStopLoss < OldStopLoss))
          {
           if (!Modify(NewStopLoss, 0)) return;
          }
      }
  }
 
//+------------------------------------------------------------------+

// возвращает нормализованное значение цены

double ND(double price)
  {
   return(NormalizeDouble(price, _Digits));
  }

//-------------------------------------------------------------------+

// открывает ордер Buy

bool Buy(double OrderLotSize, double OrderPrice)
  {
   if (Trade.Buy(OrderLotSize, _Symbol, OrderPrice))
     {
      if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
        {
         CanTrade = false;  // запрещаем торговлю (разрешаем вновь в OnTrade)
         LastDealTicket = Trade.ResultDeal();
         return(true);
        }
     }
  
   Print("Ордер Buy не открыт, ошибка ", Trade.ResultRetcodeDescription());
   return(false);
  }

//+------------------------------------------------------------------+

// открывает ордер Sell

bool Sell(double OrderLotSize, double OrderPrice)
  {
   if (Trade.Sell(OrderLotSize, _Symbol, OrderPrice))
     {
      if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
        {
         CanTrade = false;  // запрещаем торговлю (разрешаем вновь в OnTrade)
         LastDealTicket = Trade.ResultDeal();
         return(true);
        }
     }
     
   Print("Ордер Sell не открыт, ошибка ", Trade.ResultRetcodeDescription());
   return(false);
  }

//+------------------------------------------------------------------+

// устанавливает уровень TakeProfit

bool Modify(double NewStopLoss, double NewTakeProfit)
  {
   if (CompareDouble(NewStopLoss, 0.0)) NewStopLoss = PositionInfo.StopLoss();
   if (CompareDouble(NewTakeProfit, 0.0)) NewTakeProfit = PositionInfo.TakeProfit(); 
  
   if (Trade.PositionModify(_Symbol, NewStopLoss, NewTakeProfit))
     {
      if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
        {
         // CanTrade = false;
         return(true);
        }
     }
  
   Print("TakeProfit не установлен, ошибка ", Trade.ResultRetcodeDescription());
   return(false);
  }

//+------------------------------------------------------------------+

// сравнивает два вещественных числа
// возвращает true если числа равны, false если числа не равны

bool CompareDouble(double a, double b)
  {
   if (NormalizeDouble(a - b, 8) == 0) return(true);
   else return(false);
  }

//+------------------------------------------------------------------+

 
etl.t:

Привет. Вот что произошло. Робот  Ilan_mql5.mq5 нормально до 13 мая 2016. Потом начал совершать сделки без учета выставленных колен, одну за другой. Хорошо, что комп был перед глазами был и я вовремя все остановил. Проверил робота на дэмо- все работает, в реале - глючит. Помогите. Вот он

Нет там явно проверки на такую дату. 

Код оформите, а то модератор заругает - в редакторе есть кнопка SRC.

 

  Copyright © 2011, Tarakan Software Corp.

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