//+------------------------------------------------------------------+
//|                                                    open_week.mq4 |
//|                                                          |
//|                                                    http://www.ru |
//+------------------------------------------------------------------+
#property copyright "lex"
#property link      "http://www.ru"
#property version   "1.0"
#property strict


#include <stderror.mqh> 
#include <stdlib.mqh>


extern int TP              = 600; 
extern int SL              = 500;
extern int Interval        = 250; 
extern bool SL_Int         = true;// Стоплосс равен двойному интервалу
extern bool OpenDays     = false;//работать от уровня открытия дня
 

extern int MAGIC           = 111;

extern double lot          = 0.01; // начальный лот
extern double lot_exp      = 2; // коэффициент мартина
extern int Slippage        = 40;//Проскальзывание
extern bool CloseFriday    = false;//Закрывать всё в пятницу

// extern double BU = 10;

   int kol_orderov_buy=0;
   int kol_orderov_sell=0;
   int kol_orderov_buystop=0;
   int kol_orderov_sellstop=0;
   double PriceBuy = 0, PriceSell = 0, PriceBuystop = 0, PriceSellstop = 0;   
   int tOpen;
   
   double lot_buy;
   double lot_sell;
   double Interval1, TP1, SL1;
   double PriceOpenWeek;
   int    vspread;
   
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

  tOpen=0;
  lot_buy = lot;
  lot_sell = lot;
  if (SL_Int) SL = Interval * 2;


   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{

   
   if (tOpen==Time[0]) {return;}
   if (IsTradeAllowed() == false)  {return;}
  
// если нет ордеров начинаем проверять условия  
   if (HowOrders() == 0)
   {

//если понедельник, ждем 10 минут и в течении 3 часов ждем пока цена попадет в промежуток между выставляемыми отложками (если цена уже убежала выше/ниже интервала отложек) 
   
    if (OpenDays == false)
    if (DayOfWeek() == 1 && Hour() < 3  && Minute() > 10 && HowOrders() < 2)
    if (iOpen(Symbol(),PERIOD_D1,0)+NormalizeDouble (Interval*Point,Digits) > Bid && iOpen(Symbol(),PERIOD_D1,0)-NormalizeDouble (Interval*Point,Digits) < Ask) 

     {
     
      OpenNewWeek();
   
     }
     
    if (OpenDays == true)
    if (iOpen(Symbol(),PERIOD_D1,0) +NormalizeDouble (Interval*Point,Digits) > Bid && iOpen(Symbol(),PERIOD_D1,0)-NormalizeDouble (Interval*Point,Digits) < Ask) 

     {
     
      OpenNewWeek();
   
     }     
          
   }
   
// считаем каждый ордер по типу   
   HowOrdersType();
   

   
// если осталась только одна отложка селл, а отложка бай сработала и закрылась в плюс, то удаляем отложку селл
   if (kol_orderov_sellstop == 1 && kol_orderov_buystop == 0 && kol_orderov_buy == 0 && isCloseLastPosByStopTrade("",-1,-1) > 0)  {CloseAllOrder(); lot_buy = lot; lot_sell = lot;}

// если осталась только одна отложка бай, а отложка селл сработала и закрылась в плюс, то удаляем отложку бай
   if (kol_orderov_buystop == 1 && kol_orderov_sellstop == 0 && kol_orderov_sell == 0 && isCloseLastPosByStopTrade("",-1,-1) > 0)  {CloseAllOrder(); lot_buy = lot; lot_sell = lot;}
   
   
//если в работе 2 ордера   
   if (HowOrders() == 2)
   {
      
    HowOrdersType();

//в конце пятницы (20:00) закрываем все ордера    
    if (CloseFriday == true && DayOfWeek() == 5 && Hour() > 20 && HowOrders() > 0 ) {CloseAllOrder(); close_order();}

// если отложка на бай сработала, удаляем отложку селл и устанавливаем вместо нее отложку на селл с увеличенным лотом  
    if (HowOrders() == 2 && kol_orderov_buy > 0 && lot_sell == lot)
    {
     CloseAllOrder();
     lot_sell = NormalizeLots(lot_sell * lot_exp,"");
     lot_buy = NormalizeLots(lot_sell,"");
   
     Interval1 = NormalizeDouble (PriceBuy - SL*Point,Digits);
     SL1 = NormalizeDouble(PriceBuy,Digits);
     TP1 = NormalizeDouble(PriceBuy -SL*Point-TP*Point,Digits);     
     OrderSendReliable (Symbol(),OP_SELLSTOP, lot_sell, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrBrown);
    }
   
   HowOrdersType();

// если отложка на селл сработала, удаляем отложку бай и устанавливаем вместо нее отложку на бай с увеличенным лотом   
   if (HowOrders() == 2 && kol_orderov_sell > 0 && lot_buy == lot)
    {
     CloseAllOrder();
     lot_buy = NormalizeLots(lot_buy * lot_exp,"");
     lot_sell = NormalizeLots(lot_buy,"");

     Interval1 = NormalizeDouble (PriceSell + SL*Point,Digits);
     SL1 = NormalizeDouble(PriceSell,Digits);
     TP1 = NormalizeDouble(PriceSell + SL*Point+TP*Point,Digits);    
     OrderSendReliable (Symbol(),OP_BUYSTOP, lot_buy, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrBlue);
    }
  }
   
   HowOrdersType();
   
//если в работе 1 ордер (например из-за спреда не успела сработать отложка, а открытый ордер закрылся по стопу)  
   if (HowOrders() == 1)
   {
   
    if (HowOrders() == 1 && kol_orderov_buy > 0)
     {
      lot_sell = NormalizeLots(lot_sell * lot_exp,"");
      lot_buy = NormalizeLots(lot_sell,"");
   
     Interval1 = NormalizeDouble (PriceBuy - SL*Point,Digits);
     SL1 = NormalizeDouble(PriceBuy,Digits);
     TP1 = NormalizeDouble(PriceBuy -SL*Point-TP*Point,Digits);     
     OrderSendReliable (Symbol(),OP_SELLSTOP, lot_sell, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrBrown);
     }
 
   HowOrdersType();
 
   if (HowOrders() == 1 && kol_orderov_sell > 0)
    {
     lot_buy = NormalizeLots(lot_buy * lot_exp,"");
     lot_sell = NormalizeLots(lot_buy,"");

     Interval1 = NormalizeDouble (PriceSell + SL*Point,Digits);
     SL1 = NormalizeDouble(PriceSell,Digits);
     TP1 = NormalizeDouble(PriceSell + SL*Point+TP*Point,Digits);    
     OrderSendReliable (Symbol(),OP_BUYSTOP, lot_buy, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrBlue);
    } 
   
   HowOrdersType();
   
   if (HowOrders() == 1 && kol_orderov_buystop > 0)
    {
     lot_sell = NormalizeLots(lot_sell * lot_exp,"");
     lot_buy = NormalizeLots(lot_sell,"");
   
     Interval1 = NormalizeDouble (PriceBuystop-SL*Point,Digits);
     SL1 = NormalizeDouble(PriceBuystop,Digits);
     TP1 = NormalizeDouble(PriceBuystop-SL*Point-TP*Point,Digits);    
     OrderSendReliable (Symbol(),OP_SELLSTOP, lot_sell, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrFireBrick);
    }
 
   HowOrdersType();
 
   if (HowOrders() == 1 && kol_orderov_sellstop > 0)
    {
     lot_buy = NormalizeLots(lot_buy * lot_exp,"");;
     lot_sell = NormalizeLots(lot_buy,"");

     Interval1 = NormalizeDouble (PriceSellstop+SL*Point,Digits);
     SL1 = NormalizeDouble(PriceSellstop,Digits);
     TP1 = NormalizeDouble(PriceSellstop+SL*Point+TP*Point,Digits);    
     OrderSendReliable (Symbol(),OP_BUYSTOP, lot_buy, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrMidnightBlue);
    } 

  }
   
return;
}

// рассчитывает количество ордеров по типу 
void HowOrdersType()
{
   kol_orderov_buy=0;
   kol_orderov_sell=0;
   kol_orderov_buystop=0;
   kol_orderov_sellstop=0;
   
   for(int i=0;i<OrdersTotal();i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
      {
         if (OrderSymbol()==Symbol()&&OrderMagicNumber()==MAGIC)
         {
            if(OrderType() == OP_BUY) {kol_orderov_buy=kol_orderov_buy+1; PriceBuy = OrderOpenPrice();}
            if(OrderType() == OP_SELL) {kol_orderov_sell=kol_orderov_sell+1; PriceSell = OrderOpenPrice();}
            if(OrderType() == OP_BUYSTOP) {kol_orderov_buystop=kol_orderov_buystop+1; PriceBuystop = OrderOpenPrice();}
            if(OrderType() == OP_SELLSTOP) {kol_orderov_sellstop=kol_orderov_sellstop+1; PriceSellstop = OrderOpenPrice();}
         }
      }
   }

}
// рассчитывает общее количество ордеров 
int HowOrders()
{
   
   int kol_orderov=0;
   for(int i=0;i<OrdersTotal();i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
      {
         if (OrderSymbol()==Symbol()&&OrderMagicNumber()==MAGIC)
         {
            kol_orderov=kol_orderov+1;
         }
      }
   }
return(kol_orderov);
}   
   
// закрывает все отложки
void CloseAllOrder()
{
for (int i=0; i<OrdersTotal();i++)
{
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
   {
      if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MAGIC)
      {
         if(OrderType()==OP_BUYSTOP)
         {
            if(OrderDelete(OrderTicket(),clrBrown)==false) Alert("ордера не закрываются");
         }
         if(OrderType()==OP_SELLSTOP)
         {
            if(OrderDelete(OrderTicket(),clrBrown)==false) Alert("ордера не закрываются");
         }
      }
   }
}
return;
}

//закрывает все открытые ордера
void close_order()
{
for (int i=0; i<OrdersTotal();i++)
{
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
   {
      if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MAGIC)
      {
         if(OrderType()==OP_BUY)
         {
            if(OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,clrBrown)==false) Alert("ордера не закрываются");
         }
         if(OrderType()==OP_SELL)
         {
            if(OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,clrBrown)==false) Alert("ордера не закрываются");
         }
      }
   }
}
return;
}



//проверяет последний закрывщийся ордер на профит
double isCloseLastPosByStopTrade(string sy="",int op=-1,int mn=-1)
  {
   datetime t;
   int      i,j=-1,k=OrdersHistoryTotal();

   if(sy=="0") sy=Symbol();
   for(i=0; i<k; i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol()==sy || sy=="")
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL)
              {
               if(op<0 || OrderType()==op)
                 {
                  if(mn<0 || OrderMagicNumber()==mn)
                    {
                     if(t<OrderCloseTime())
                       {
                        t=OrderCloseTime();
                        j=i;
                       }
                    }
                 }
              }
           }
        }
     }
   if(OrderSelect(j,SELECT_BY_POS,MODE_HISTORY))
     {
      return(OrderProfit());
     }
  return(0);
  }
  
  
//функция открытия ордера  
  int OrderSendReliable(string symbol, int cmd, double lots, double price, int slippage, double stoploss, double takeprofit, string comment = "", int magic = 0, int expiration = 0, color arrow_color = CLR_NONE) {   
//   Print("OrderSendReliable(" + symbol + "," + cmd + "," + lots + "," + price + "," + slippage + "," + stoploss + "," + takeprofit + "," + comment +
//      "," + magic + "," + expiration + "," + arrow_color + ")");
   while (true) {
      if (IsStopped()) {
       //  Print("OrderSendReliable(): Trading is stopped!");
         return (-1);
      }
      RefreshRates();
      if (cmd == OP_BUY) price = Ask;
      if (cmd == OP_SELL) price = Bid;
      if (!IsTradeContextBusy()) {
         int ticket = OrderSend(symbol, cmd, lots, NormalizeDouble(price, MarketInfo(symbol, MODE_DIGITS)), slippage, NormalizeDouble(stoploss, MarketInfo(symbol,
            MODE_DIGITS)), NormalizeDouble(takeprofit, MarketInfo(symbol, MODE_DIGITS)), comment, magic, expiration, arrow_color);
         if (ticket > 0) {
           // Print("OrderSendReliable(): Success! Ticket: " + ticket);
            return (ticket);
         }
         int error = GetLastError();
         if (IsTemporaryError(error)) 
            Print("OrderSendReliable(): Temporary Error: " + error + " " + ErrorDescription(error) + ". waiting.");
         else {
            Print("OrderSendReliable(): Permanent Error: " + error + " " + ErrorDescription(error) + ". giving up.");
            return (-1);
         }
      } else 
         Print("OrderSendReliable(): Must wait for trade context");
         
      Sleep(MathRand() / 10);
   }
return(0);
}


bool IsTemporaryError(int error) {
   return (error == ERR_NO_ERROR
		|| error == ERR_COMMON_ERROR
		|| error == ERR_SERVER_BUSY
		|| error == ERR_NO_CONNECTION
		|| error == ERR_MARKET_CLOSED
		|| error == ERR_PRICE_CHANGED
		|| error == ERR_INVALID_PRICE
		|| error == ERR_OFF_QUOTES
		|| error == ERR_BROKER_BUSY
		|| error == ERR_REQUOTE
		|| error == ERR_TRADE_TIMEOUT
		|| error == ERR_TRADE_CONTEXT_BUSY
	);
}

void OpenNewWeek()
{
//рассчитывем интервал, стоп и тейк бай отложек    
     Interval1 = NormalizeDouble (iOpen(Symbol(),PERIOD_D1,0)+Interval*Point,Digits);
     SL1 = NormalizeDouble(iOpen(Symbol(),PERIOD_D1,0)+Interval*Point-SL*Point,Digits);
     TP1 = NormalizeDouble(iOpen(Symbol(),PERIOD_D1,0)+Interval*Point+TP*Point,Digits); 

// выставляем отложку бай
     lot = NormalizeLots(lot,"");
     OrderSendReliable (Symbol(),OP_BUYSTOP, lot, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrLime);

//рассчитывем интервал, стоп и тейк селл отложек         
     Interval1 = NormalizeDouble (iOpen(Symbol(),PERIOD_D1,0)-Interval*Point,Digits);
     SL1 = NormalizeDouble(iOpen(Symbol(),PERIOD_D1,0)-Interval*Point+SL*Point,Digits);
     TP1 = NormalizeDouble(iOpen(Symbol(),PERIOD_D1,0)-Interval*Point-TP*Point,Digits); 

// выставляем отложку селл    
     OrderSendReliable (Symbol(),OP_SELLSTOP, lot, Interval1, Slippage,SL1,TP1,NULL,MAGIC,0,clrYellow);
}


double NormalizeLots(double lots, string pair="")
    {
    if (pair == "") pair = Symbol();
    double  lotStep     = MarketInfo(pair, MODE_LOTSTEP),
            minLot      = MarketInfo(pair, MODE_MINLOT);
    lots            = MathRound(lots/lotStep) * lotStep;
    if (lots < minLot) lots = 0;    // or minLot
    return(lots);
    }