//+------------------------------------------------------------------+
//|                                                 PuppetShadow.mq4 |
//|                                                            Dirst |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+

extern int take_profit = 10;
extern int stop_loss = 21;
extern double lot = 0.01;
extern int period_length = 20;
extern int level_offset = 30;


#property copyright "Dirst"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

struct round_levels{
  double high;
  double low;
};  
  
class PuppetShadow {
  public: round_levels levels;
  
  public: void PuppetShadow() {
    this.levels.high = -1;
    this.levels.low  = -1;
  }
  
  public: void redrawLevels() {   
    //вычислить коридор за период
      int indexH = iHighest( 
          Symbol(),          // символ 
          Period(),       // период 
          MODE_HIGH,            // идентификатор таймсерии 
          period_length,           // число элементов 
          0            // индекс 
        );
      
        int indexL = iLowest( 
          Symbol(),          // символ 
          Period(),       // период 
          MODE_LOW,            // идентификатор таймсерии 
          period_length,           // число элементов 
          0            // индекс 
        );
  
     OrderSelect(0, SELECT_BY_POS);
     
     int hundreeds = iHigh(Symbol(), Period(), indexH)*100;
     hundreeds *= 100;
     
     if(!OrdersTotal() || OrderType() != OP_SELLLIMIT) {
       this.levels.high = (hundreeds+100);
       this.levels.high /= 10000;
     }
     hundreeds = iLow(Symbol(), Period(), indexL)*100;
     hundreeds *= 100;
     
     
     if(!OrdersTotal() || OrderType() != OP_BUYLIMIT) {
       this.levels.low = hundreeds;
       this.levels.low /= 10000;
     }
     
     // удалить старые уровни
     ObjectDelete(ChartID(), "High Level");
     ObjectDelete(ChartID(), "Low Level");
   
     // нарисовать уровни
     ObjectCreate("High Level", OBJ_HLINE, 0, Time[0], this.levels.high, 0, 0); 
     ObjectCreate("Low Level", OBJ_HLINE, 0, Time[0], this.levels.low, 0, 0); 
  }
  
  public: void set_orders() {
    double sell_limit = level_offset * Point() + this.levels.high;
    double buy_limit  = this.levels.low - level_offset * Point();
  
    if(Ask < sell_limit && Ask > this.levels.high) //цена пересекла уровень вверх 
      OrderSend(Symbol(), OP_SELLLIMIT, lot, sell_limit, 1, stop_loss * Point() + sell_limit, sell_limit - take_profit*Point()); //отложка на продажу
  
    if(Ask > buy_limit && Ask < this.levels.low) //цена пересекла уровень вниз
      OrderSend(Symbol(), OP_BUYLIMIT, lot, buy_limit, 1, buy_limit - stop_loss * Point(), buy_limit + take_profit*Point()); //отложка на покупку 
  }
  
  public: void delete_limit_order(){
    if(OrdersTotal()) {
    
      OrderSelect(0, SELECT_BY_POS);
      if(OrderType() == OP_BUYLIMIT && Ask > this.levels.high || OrderType() == OP_SELLLIMIT && Ask < this.levels.low)
        OrderDelete(OrderTicket());
      else
        if(OrderType() == OP_BUY || OrderType() == OP_SELL)
          this.redrawLevels();
           
    }
  }
};  

static PuppetShadow obj();
int OnInit() {
   level_offset *= 10;
   stop_loss    *= 10;
   take_profit  *= 10;
   obj.redrawLevels();
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   
}


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){
  
  datetime date = TimeGMT();
  int h = TimeHour( date );
  int m = TimeMinute( date );
  
  Print(h + " " + " " + m);
  
  if((h == 20 || h == 23 || h == 8) && m == 0 && OrdersTotal()){
    OrderSelect(0, SELECT_BY_POS);
    OrderClose(OrderTicket(), OrderLots(), Ask, 1, clrGreen);
  }
  
  if(h >= 20 && h <= 23) //не торгуем в этом промежутке
   return;
  
  //если цена вышла за границы удалить предыдущий отложенный ордер отложенный 
  obj.delete_limit_order();
  
  if(is_new_bar())
    obj.redrawLevels();  
    
  if((obj.levels.high < Ask || Ask < obj.levels.low) && !OrdersTotal()) { //если нет ордеров и уровни не выставлены
    obj.set_orders();
  }  
  
  /*
  if(!OrdersTotal() && is_new_bar()){
     if(!(obj.levels.high < Ask || Ask < obj.levels.low))
       
  }
  */
  /*   
  if(obj.levels.high > Ask && Ask > obj.levels.low) {
    if(OrdersTotal()) {
      OrderSelect(0, SELECT_BY_POS);
      OrderDelete(OrderTicket());
    }
  }*/
  
}



/**
 * Set orders
 
void set_orders() {
  
  Print(levels.high);
  // если открыт хоть один не отложенный ордер не устанавливать дополнительных
  if(OrdersTotal()){ 
    OrderSelect(0, SELECT_BY_POS);
    if(OrderType() == OP_BUY || OrderType() == OP_SELL)
      return;
    else
      if(OrderType() == OP_BUYLIMIT && Ask > levels.low || OrderType() == OP_SELLLIMIT && Ask < levels.high){
        OrderDelete(OrderTicket()); //удаляем отложенный ордер
        levels.high = -1;
      }
    return; // выходим не поставиви новых ордеров так как уже есть
  }
  
  levels = get_prev_levels();
  
  double sell_limit = level_offset * Point() + levels.high;
  double buy_limit  = levels.low - level_offset * Point();
  
  if(Ask < sell_limit && Ask > levels.high) //цена пересекла уровень вверх 
    OrderSend(Symbol(), OP_SELLLIMIT, lot, sell_limit, 1, stop_loss * Point() + sell_limit, sell_limit - take_profit*Point()); //отложка на продажу
  
  if(Ask > buy_limit && Ask < levels.low) //цена пересекла уровень вниз
    OrderSend(Symbol(), OP_BUYLIMIT, lot, buy_limit, 1, buy_limit - stop_loss * Point(), buy_limit + take_profit*Point()); //отложка на покупку 
    
  levels = !OrdersTotal() ? get_round_levels() : levels; //получать новые уровни только если нет ордеров
    
}

round_levels get_prev_levels() {
  if(levels.high < 0)
    return get_round_levels();
  else 
    return levels;   
}

round_levels get_round_levels() {

  round_levels lvl;
  
  int hundreeds = Ask*100;
  
  hundreeds *= 100;
  
  lvl.high = (hundreeds+100);
  lvl.high /= 10000;
  
  lvl.low = hundreeds;
  lvl.low /= 10000;
  
  // удалить старые уровни
  ObjectDelete(ChartID(), "High Level");
  ObjectDelete(ChartID(), "Low Level");

  // нарисовать уровни
  ObjectCreate("High Level", OBJ_HLINE, 0, Time[0], lvl.high, 0, 0); 
  ObjectCreate("Low Level", OBJ_HLINE, 0, Time[0], lvl.low, 0, 0); 

  return lvl;
}
*/
bool is_new_bar() {
  if(Volume[0] == 1)
    return true;
  else 
    return false; 
}