//+------------------------------------------------------------------+
//|                                            News hunter v.1.4.mq4 |
//|                                                         AriusKis |
//|                                             https://www.mql5.com |
//| Сделки теперь открываются независимо от наличия открытых ордеров |
//+------------------------------------------------------------------+
#property copyright "AriusKis"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
enum dayOfWeek
  {
   M =1,    // Понедельник
   T =2,    // Вторник
   W =3,    // Среда
   Th=4,    // Четверг
   Fr=5,    // Пятница
   S =6,    // Не торговать
  };
extern string MainSettings="параметры   =========================";   //==============================  Общие
extern int    Magic          = 942;
extern int    Slippage       = 4;
//если здесь будут нули, то данные берутся локальные из торговых точек
extern int    MainTakeProfit = 10;                                        //Тейк-профит в пунктах
extern int    MainStopLoss   = 10;                                        //Стоп-лосс в пунктах
extern double MainRisk       = 1;                                         //Риск от депозита, %
extern int    MaintCloseTime = 20;                                        //Закрытие ордеров, мин.
input  bool   DeleteOrderFlag =true;                                      //Удалить ордер, если открылся только один
                                                                          //ниже, если будет день недели воскресенье - то торговли по этим точкам не будет
extern string Settings1      = "точка   =============================";   //===================== Первая торговая
extern dayOfWeek swapday_1   = S;                                         //День недели
extern int    Tradehour_1    = 0;                                        //Часы торговой точки
extern int    Trademinutes_1 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_1   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_1     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_1=0;                                         //Риск от депозита, %
extern double Spread_1=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_1    = 0;                                        //Закрытие ордеров, мин.
                                                                         //Если в параметрах CloseTime и OpenTime стоит 0, значит ордера не закрываются и новые не открываются (только один раз)
extern string Settings2      = "точка   =============================";   //===================== Вторая торговая
extern dayOfWeek swapday_2   = S;                                         //День недели
extern int    Tradehour_2    = 0;                                        //Часы торговой точки
extern int    Trademinutes_2 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_2   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_2     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_2=0;                                         //Риск от депозита, %
extern double Spread_2=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_2    = 0;                                        //Закрытие ордеров, мин.

extern string Settings3      = "точка   =============================";   //===================== Третья торговая
extern dayOfWeek swapday_3   = S;                                         //День недели
extern int    Tradehour_3    = 0;                                        //Часы торговой точки
extern int    Trademinutes_3 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_3   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_3     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_3=0;                                         //Риск от депозита, %
extern double Spread_3=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_3    = 0;                                        //Закрытие ордеров, мин.

extern string Settings4      = "точка   =============================";   //================== Четвертая торговая
extern dayOfWeek swapday_4   = S;                                         //День недели
extern int    Tradehour_4    = 0;                                        //Часы торговой точки
extern int    Trademinutes_4 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_4   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_4     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_4=0;                                         //Риск от депозита, %
extern double Spread_4=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_4    = 0;                                        //Закрытие ордеров, мин.

extern string Settings5      = "точка   =============================";   //====================== Пятая торговая
extern dayOfWeek swapday_5   = S;                                         //День недели
extern int    Tradehour_5    = 0;                                        //Часы торговой точки
extern int    Trademinutes_5 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_5   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_5     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_5=0;                                         //Риск от депозита, %
extern double Spread_5=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_5    = 0;                                        //Закрытие ордеров, мин.

extern string Settings6      = "точка   =============================";   //===================== Шестая торговая
extern dayOfWeek swapday_6   = S;                                         //День недели
extern int    Tradehour_6    = 0;                                        //Часы торговой точки
extern int    Trademinutes_6 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_6   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_6     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_6=0;                                         //Риск от депозита, %
extern double Spread_6=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_6    = 0;                                        //Закрытие ордеров, мин.

extern string Settings7      = "точка   =============================";   //==================== Седьмая торговая
extern dayOfWeek swapday_7   = S;                                         //День недели
extern int    Tradehour_7    = 0;                                        //Часы торговой точки
extern int    Trademinutes_7 = 0;                                        //Минуты торговой точки
extern int    TakeProfit_7   = 0;                                        //Тейк-профит в пунктах
extern int    StopLoss_7     = 0;                                        //Стоп-лосс в пунктах
extern double Risk_7=0;                                         //Риск от депозита, %
extern double Spread_7=3.0;   //Максимально приемлемый спред, п.
extern int    CloseTime_7    = 0;                                        //Закрытие ордеров, мин.

int takeprofit,stoploss,definepoint;
double risk,Spreadnow;
bool check,CloseFlag=true;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(Digits()==3 || Digits()==5)
     {
      Slippage       *= 10;
      MainTakeProfit *= 10;
      MainStopLoss   *= 10;
      TakeProfit_1   *= 10;
      TakeProfit_2   *= 10;
      TakeProfit_3   *= 10;
      TakeProfit_4   *= 10;
      TakeProfit_5   *= 10;
      TakeProfit_6   *= 10;
      TakeProfit_7   *= 10;
      StopLoss_1     *= 10;
      StopLoss_2     *= 10;
      StopLoss_3     *= 10;
      StopLoss_4     *= 10;
      StopLoss_5     *= 10;
      StopLoss_6     *= 10;
      StopLoss_7     *= 10;
      Spread_1       *=10;
      Spread_2       *=10;
      Spread_3       *=10;
      Spread_4       *=10;
      Spread_5       *=10;
      Spread_6       *=10;
      Spread_7       *=10;
     }
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
      if(DayOfWeek()==swapday_1 && Hour()==Tradehour_1 && Minute()==Trademinutes_1 && CountPointOrders(1)==0)
        {
         takeprofit = TakeProfit_1;
         stoploss   = StopLoss_1;
         risk       = Risk_1;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_1)
            OpenOppositeOrders(takeprofit,stoploss,risk,1);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=1;
        }
      if(DayOfWeek()==swapday_2 && Hour()==Tradehour_2 && Minute()==Trademinutes_2 && CountPointOrders(2)==0)
        {
         takeprofit = TakeProfit_2;
         stoploss   = StopLoss_2;
         risk       = Risk_2;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_2)
            OpenOppositeOrders(takeprofit,stoploss,risk,2);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=2;
        }
      if(DayOfWeek()==swapday_3 && Hour()==Tradehour_3 && Minute()==Trademinutes_3 && CountPointOrders(3)==0)
        {
         takeprofit = TakeProfit_3;
         stoploss   = StopLoss_3;
         risk       = Risk_3;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_3)
            OpenOppositeOrders(takeprofit,stoploss,risk,3);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=3;
        }
      if(DayOfWeek()==swapday_4 && Hour()==Tradehour_4 && Minute()==Trademinutes_4 && CountPointOrders(4)==0)
        {
         takeprofit = TakeProfit_4;
         stoploss   = StopLoss_4;
         risk       = Risk_4;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_4)
            OpenOppositeOrders(takeprofit,stoploss,risk,4);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=4;
        }
      if(DayOfWeek()==swapday_5 && Hour()==Tradehour_5 && Minute()==Trademinutes_5 && CountPointOrders(5)==0)
        {
         takeprofit = TakeProfit_5;
         stoploss   = StopLoss_5;
         risk       = Risk_5;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_5)
            OpenOppositeOrders(takeprofit,stoploss,risk,5);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=5;
        }
      if(DayOfWeek()==swapday_6 && Hour()==Tradehour_6 && Minute()==Trademinutes_6 && CountPointOrders(6)==0)
        {
         takeprofit = TakeProfit_6;
         stoploss   = StopLoss_6;
         risk       = Risk_6;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_6)
            OpenOppositeOrders(takeprofit,stoploss,risk,6);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=6;
        }
      if(DayOfWeek()==swapday_7 && Hour()==Tradehour_7 && Minute()==Trademinutes_7 && CountPointOrders(7)==0)
        {
         takeprofit = TakeProfit_7;
         stoploss   = StopLoss_7;
         risk       = Risk_7;
         CloseFlag=true;
         if(takeprofit==0)
            takeprofit=MainTakeProfit;
         if(stoploss==0)
            stoploss=MainStopLoss;
         if(risk==0)
            risk=MainRisk;
         Spreadnow=MarketInfo(Symbol(),MODE_SPREAD);
         if(Spreadnow<Spread_7)
            OpenOppositeOrders(takeprofit,stoploss,risk,7);
         else Print("Ордера не открыты в заданное время в связи с большим спредом!! Spread = ",NormalizeDouble(Spreadnow,0),".");
         definepoint=7;
        }
   if(CountOpenOrders()>0 && CloseFlag==true) //Этот флаг станет false, если у нас не указано время закрытия ордеров
      MonitorPosition();
  }
//+------------------------------------------------------------------+
//| Функция открытия противоположных ордеров                         |
//+------------------------------------------------------------------+
int CountPointOrders(int nextpoint)
  {
     int count= 0;
     for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic+nextpoint)
            count++;
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//| Функция открытия противоположных ордеров                         |
//+------------------------------------------------------------------+
void OpenOppositeOrders(int take,int stop,double Risk,int nextpoint)
  {
   double lot,sl_buy,tp_buy,sl_sell,tp_sell;
   int ticketbuy,ticketsell;
   lot=DealVolume(Risk,stop);
   sl_buy  = NormalizeDouble(Ask-stop*Point(), Digits());
   sl_sell = NormalizeDouble(Bid+stop*Point(), Digits());
   tp_buy  = NormalizeDouble(Ask+take*Point(), Digits());
   tp_sell = NormalizeDouble(Bid-take*Point(), Digits());
   ticketbuy=OrderSendx(Symbol(),OP_BUY,lot,Ask,Slippage,0,0,"news hunter",Magic+nextpoint,0,clrNONE);
   if(ticketbuy>0 && OrderSelect(ticketbuy,SELECT_BY_TICKET,MODE_TRADES))
      check=OrderModifyx(ticketbuy,OrderOpenPrice(),sl_buy,tp_buy,0,clrNONE);                      //для ecn счетов
   ticketsell=OrderSend(Symbol(),OP_SELL,lot,Bid,Slippage,0,0,"news hunter",Magic+nextpoint,0,clrNONE);
   if(ticketsell>0 && OrderSelect(ticketsell,SELECT_BY_TICKET,MODE_TRADES))
      check=OrderModifyx(ticketsell,OrderOpenPrice(),sl_sell,tp_sell,0,clrNONE);
   if(DeleteOrderFlag==true)
     {
      if(ticketbuy<=0 && ticketsell>0)
        {
         if(OrderSelect(ticketsell,SELECT_BY_TICKET,MODE_TRADES))
            OrderClosex(OP_SELL,ticketsell,OrderLots(),Ask,Slippage,clrNONE);
        }
      if(ticketbuy>0 && ticketsell<=0)
        {
         if(OrderSelect(ticketbuy,SELECT_BY_TICKET,MODE_TRADES))
            OrderClosex(OP_BUY,ticketbuy,OrderLots(),Bid,Slippage,clrNONE);
        }
     }

  }
//+------------------------------------------------------------------+
//| Функция подсчета количества открытых ордеров                     |
//+------------------------------------------------------------------+
int CountOpenOrders()
  {
   int count= 0;
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()>=Magic && OrderMagicNumber()<=Magic+7)
            count++;
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//| Функция вычисления объема сделки                                 |
//+------------------------------------------------------------------+
double DealVolume(double riskcount,double sl)
  {
   double lot_min  = MarketInfo(Symbol(), MODE_MINLOT);
   double lot_max  = MarketInfo(Symbol(), MODE_MAXLOT);
   double lot_step = MarketInfo(Symbol(), MODE_LOTSTEP);
   double lotcost  = MarketInfo(Symbol(), MODE_TICKVALUE);

   double lot=0;
   double UsdPerPip=0;
   
   lot = MathMin(AccountBalance(), AccountEquity())*riskcount/100;
   
   UsdPerPip=lot/sl;

   lot=UsdPerPip/lotcost;

   lot = MathFloor(lot/lot_step)*lot_step;
   
   if(lot<lot_min) lot = lot_min;
   if(lot>lot_max) lot = lot_max;
   
   return(lot);
  }
//+------------------------------------------------------------------+
//| Функция слежения за сделкой                                      |
//+------------------------------------------------------------------+
void MonitorPosition()
  {
   int closetime=0;
   int magicnumber;
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()>=Magic && OrderMagicNumber()<=Magic+7)
           {
            magicnumber=OrderMagicNumber()-Magic;
            switch(magicnumber)
              {
               case 1: closetime=CloseTime_1; break;
               case 2: closetime=CloseTime_2; break;
               case 3: closetime=CloseTime_3; break;
               case 4: closetime=CloseTime_4; break;
               case 5: closetime=CloseTime_5; break;
               case 6: closetime=CloseTime_6; break;
               case 7: closetime=CloseTime_7; break;
              }
            if(closetime==0)
               closetime=MaintCloseTime;
            if(closetime==0)
              {
               CloseFlag=false;
               return;
              }
            if(TimeCurrent()-OrderOpenTime()>closetime*60)
              {
               if(OrderType()==OP_BUY)
                  check=OrderClosex(OP_BUY,OrderTicket(),OrderLots(),Bid,Slippage,clrNONE);
               if(OrderType()==OP_SELL)
                  check=OrderClosex(OP_SELL,OrderTicket(),OrderLots(),Ask,Slippage,clrNONE);
              }

           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Функция-обработчик ошибок при открытии ордеров                   |
//+------------------------------------------------------------------+
int OrderSendx(string symbolx,int cmdx,double volumex,double pricex,int slippagex,double stoplossx,double takeprofitx,
               string commentx,int magicx,datetime expirationx,color arrow_colorx)
  {
   int err=0;
   bool exit_loop=false;
   int ticketx=-1;
   int Retry = 15;
   int cnt   = 0;

   while(!exit_loop)
     {
      ticketx=OrderSend(symbolx,cmdx,volumex,pricex,slippagex,stoplossx,takeprofitx,commentx,magicx,expirationx,arrow_colorx);
      err=GetLastError();

      switch(err)
        {
         case ERR_NO_ERROR:
            exit_loop=true;
            return(ticketx);
         case ERR_SERVER_BUSY:
         case ERR_NO_CONNECTION:
         case ERR_INVALID_PRICE:
         case ERR_TRADE_TIMEOUT:
         case ERR_OFF_QUOTES:
         case ERR_BROKER_BUSY:
         case ERR_TRADE_CONTEXT_BUSY:
            cnt++;
            break;
         case ERR_PRICE_CHANGED:
         case ERR_REQUOTE:
            RefreshRates();
            cnt++;
            continue;
         default:
            exit_loop=true;
            break;
        }
      if(cnt>Retry)
        {
         exit_loop=true;
         Print("Ошибка открытия ордера после ",cnt," попыток");
        }
      if(err!=ERR_NO_ERROR)
         Print("Ошибка открытия ордера! Ошибка №: ",err);
      if(!exit_loop)
        {
         Sleep(5000);
         RefreshRates();
         if(cmdx==OP_BUY)
            pricex=Ask;
         if(cmdx==OP_SELL)
            pricex=Bid;
        }

     }
   if(err!=ERR_NO_ERROR)
      SendMail("Советник News hunter. ","Ошибка открытия ордера на валютной паре "+Symbol()+"! Номер ошибки: "+IntegerToString(err,0));
   return(ticketx);
  }
//+------------------------------------------------------------------+
//| Функция-обработчик ошибок при модификации ордеров                |
//+------------------------------------------------------------------+
bool OrderModifyx(int ticketx,double pricex,double stoplossx,double takeprofitx,datetime expirationx,color arrow_colorx)
  {
   int err=0;
   bool exit_loop=false;
   bool answer=false;
   int Retry = 10;
   int cnt   = 0;

   while(!exit_loop)
     {
      answer=OrderModify(ticketx,pricex,stoplossx,takeprofitx,expirationx,arrow_colorx);
      err=GetLastError();

      switch(err)
        {
         case ERR_NO_ERROR:
            exit_loop=true;
            return(answer);
         case ERR_SERVER_BUSY:
         case ERR_NO_CONNECTION:
         case ERR_INVALID_PRICE:
         case ERR_TRADE_TIMEOUT:
         case ERR_OFF_QUOTES:
         case ERR_BROKER_BUSY:
         case ERR_TRADE_CONTEXT_BUSY:
            cnt++;
            break;
         default:
            exit_loop=true;
            break;
        }
      if(cnt>Retry)
        {
         exit_loop=true;
         Print("Ошибка модификации ордера после ",cnt," попыток");
        }
      if(err!=ERR_NO_ERROR)
         Print("Ошибка модификации ордера! Ошибка №: ",err);
      if(!exit_loop)
        {
         Sleep(5000);
         RefreshRates();
        }

     }
   if(err!=ERR_NO_ERROR)
      SendMail("Советник News hunter. ","Ошибка модификации ордера на валютной паре "+Symbol()+"! Номер ошибки: "+IntegerToString(err,0));
   return(answer);
  }
//+------------------------------------------------------------------+
//| Функция-обработчик ошибок при закрытии ордеров                   |
//+------------------------------------------------------------------+
bool OrderClosex(int cmdx,int ticketx,double lotsx,double pricex,int slippagex,color arrow_colorx)
  {
   int err=0;
   bool exit_loop=false;
   bool answer=false;
   int Retry = 15;
   int cnt   = 0;

   while(!exit_loop)
     {
      answer=OrderClose(ticketx,lotsx,pricex,slippagex,arrow_colorx);
      err=GetLastError();

      switch(err)
        {
         case ERR_NO_ERROR:
            exit_loop=true;
            return(answer);
         case ERR_SERVER_BUSY:
         case ERR_NO_CONNECTION:
         case ERR_INVALID_PRICE:
         case ERR_TRADE_TIMEOUT:
         case ERR_OFF_QUOTES:
         case ERR_BROKER_BUSY:
         case ERR_TRADE_CONTEXT_BUSY:
            cnt++;
            break;
         case ERR_PRICE_CHANGED:
         case ERR_REQUOTE:
            RefreshRates();
            cnt++;
            continue;
         default:
            exit_loop=true;
            break;
        }
      if(cnt>Retry)
        {
         exit_loop=true;
         Print("Ошибка закрытия ордера после ",cnt," попыток");
        }
      if(err!=ERR_NO_ERROR)
         Print("Ошибка закрытия ордера! Ошибка №: ",err);
      if(!exit_loop)
        {
         Sleep(5000);
         RefreshRates();
         if(cmdx==OP_SELL)
            pricex=Ask;
         if(cmdx==OP_BUY)
            pricex=Bid;
        }

     }
   if(err!=ERR_NO_ERROR)
      SendMail("Советник News hunter. ","Ошибка закрытия ордера на валютной паре "+Symbol()+"! Номер ошибки: "+IntegerToString(err,0));
   return(answer);
  }
//+------------------------------------------------------------------+