//+------------------------------------------------------------------+
//|                                          Custom_Box_Breakout.mq4 |
//|                                                              RBI |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "RBI"
#property link      ""
//IDEAS

   // BOX VARIABLES
   extern string  StartTime= "6:15";
   extern string  EndTime= "9:15";
   extern string  orderExpireTime= "12:00";
   extern bool    DrawBox=  true;
   extern color   BoxColor=  White;
   //ORDER VARIABLES
   extern double  TradeSize1=  0.1;
   extern double  TradeSize2=  0.0;
   extern int     TP1= 100;
   extern int     TP2= 15;
   extern int     SL1= 20;
   extern int     Slip= 3;
   extern int     MagicNumber= 162616;
   extern int     MaxTrades= 3;
   extern bool    One_Trade_Bar=true;
   extern double  Max_Dev_ReOpen= 5.0; //Max number of pips away from signals for re-open
   extern double  SignalBufferLong= 5.0;
   extern double  SignalBufferShort= 5.0;
   // EXTERNAL VARIABLES
   extern bool    Use_BE= true;
   extern int     BE_Stop= 15;
   // TRAIL STOP VARIABLES
   extern bool    UseTrail = true;
   extern int     Target_Increment= 15;
   extern int     Stop_Increment= 15;
   extern int     Initial_Jump= 50;
   // INDICATOR VARIABLES
   extern bool    Use_MAFilter= true;
   extern bool    Stop_Inside_Box= true; //Filters all trades if MA is inside Box
   extern int     MA_TF= 0;
   extern int     MA_Period= 90;
   
   // GLOBAL VARIABLES
   //TRADE GLOBALS
   int   ticket, tck2;
   int   tradeBar;
   //TRADE LIMIT GLOBALS
   int   trade_num;
   // TRADE MANAGEMENT GLOBALS
   int timerLCb;
   double PriceReached;
   double trailTarget;
   double nSL;
   double BE_Target;
   double beSL;
   
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----

   //---INITIAL VARIABLES---//
   int tradeDirection;
   datetime ordExpire= StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + " " + orderExpireTime);
   datetime boxEnd= StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + " " + EndTime); 
   
   //---BOX DEFINITION---//
   double buySignal= BoxDefinition(Symbol(), StartTime, EndTime, "high", DrawBox, BoxColor);
   double sellSignal= BoxDefinition(Symbol(), StartTime, EndTime, "low", false, BoxColor);
   double boxHeight= BoxDefinition(Symbol(), StartTime, EndTime, "height", false, BoxColor);
      
   //---INDICATORS---//
   double EMA = iMA(NULL,MA_TF,MA_Period,0,MODE_EMA,PRICE_CLOSE,0);
   
   //---ORDER INFORMATION---//
   bool tckOrder = OrderSelect(ticket,SELECT_BY_TICKET);
   if(tckOrder){ 
      double lastResult = OrderProfit();
      double ordrOpenP = OrderOpenPrice();
      int lastCloseT = OrderCloseTime();
   }
   
   //---CONDITIONS---//
   //TRADE DIRECTION
   if(boxHeight>0){
      if(Ask-SignalBufferLong*(Point*10)>=buySignal){//Activate BUY
         if(Ask<=buySignal+SignalBufferLong*(Point*10)+Max_Dev_ReOpen*(Point*10)){ 
            tradeDirection = 1;
         }
      }
      else if(Bid+SignalBufferShort*(Point*10)<=sellSignal){//Activate SELL
         if(Bid>=sellSignal-SignalBufferShort*(Point*10)-Max_Dev_ReOpen*(Point*10)){
            tradeDirection = -1;
         }
      }
   }//-CONDITIONS
   
   //---MASTER RESET---//
   if(TimeCurrent()>=ordExpire || TimeCurrent()<boxEnd){
      tradeDirection=0;
      trade_num=0;
      lastResult=0;
      ticket=0;
      tck2=0;
   }
   
   //---FILTERS---//
   if(tradeDirection!=0){
      //MA FILTER
      if(Stop_Inside_Box){   
         if(buySignal>EMA && sellSignal<EMA){
            tradeDirection=0;
         }
      }
      if(Use_MAFilter){
         if(buySignal<EMA && tradeDirection>0){
            tradeDirection=0;
         }
         else if(sellSignal>EMA && tradeDirection<0){
            tradeDirection=0;
         }
      }
      //NUMBER OF TRADES FILTER
      if(MaxTrades<=trade_num){
         tradeDirection=0;
      }
      //ONE TRADE PER BAR FILTER
      if(One_Trade_Bar && tradeBar==Bars){
         tradeDirection=0;
      }
      //LAST RESULT FILTER
      if(lastResult>5){
         tradeDirection=0;
      }
      //OPEN ORDER FILTER
      if(tckOrder && lastCloseT==0){
         tradeDirection=0;
      }
   }//-FILTERS
   
   //---ORDERS---//
   if(tradeDirection!=0){
      ticket = PlaceOrder(tradeDirection, TradeSize1, Slip, SL1, TP1, MagicNumber, "London BO - Trade1");
      trade_num++;
      if(TradeSize2>0){
         tck2 = PlaceOrder(tradeDirection, TradeSize2, Slip, SL1, TP2, MagicNumber, "London BO - Trade2");
      }
   }
   //---ORDER MANAGEMENT---//
   //TRAILING STOP
   if(UseTrail){
      EvalTrail(ticket, Target_Increment, Stop_Increment, Initial_Jump, "inc");
   }
   //BE STOP
   if(Use_BE){
      EvalBE(ticket, BE_Stop);
   }
   //Comment();
//----
   return(0);
  }
//+------------------------------------------------------------------+
void EvalTrail(int Ticket, int Target_Increment, int Stop_Increment, int Initial_Jump, string Mode){
   
   bool tckOrder = OrderSelect(Ticket,SELECT_BY_TICKET);
   int ordType = OrderType();
   double ordLots = OrderLots();
   double orderOpen = OrderOpenPrice();
   double orderSL = OrderStopLoss();
   datetime closeTime = OrderCloseTime();
   
   //INCREMENTAL MODE
   if(tckOrder && closeTime==0 && Mode=="inc"){ //terminates if tck doesn't exist or if closed
      //BUY ORDER CONTROL
      if(ordType==0){
         if(trailTarget==0){
            trailTarget = orderOpen + (Initial_Jump*(Point*10));
         }
         if(Bid>PriceReached){//Price Reached incr.
            PriceReached=Bid;
         }
         if(PriceReached>=trailTarget){// Stop and Target Incremement
            if(nSL==0){ 
               nSL = orderSL;
            }
            nSL+=(Stop_Increment*(Point*10));
            trailTarget+= (Target_Increment*(Point*10));
         }
         // BUY ORDER CLOSE
         if(Bid<=nSL && nSL!=0){// Close Order
            RefreshRates();
            OrderClose(Ticket, ordLots, Bid, Slip,Yellow);
            PriceReached = 0;
            trailTarget = 0;
            nSL = 0;
         }
      }  
      //SELL ORDER CONTROL
      else if(ordType>0){
         if(trailTarget==0){
            trailTarget = orderOpen - (Initial_Jump*(Point*10));
            PriceReached=100000;// so that price starts automatically above Price Reached
         }
         if(Ask<=PriceReached){//Price Reached incr.
            PriceReached=Ask;
         }
         if(PriceReached<=trailTarget){// Stop and Target Incremement
            if(nSL==0){ 
               nSL = orderSL;
            }
            nSL-=(Stop_Increment*(Point*10));
            trailTarget-= (Target_Increment*(Point*10));
         }
         // SELL ORDER CLOSE
         if(Ask>=nSL && nSL!=0){// Close Order
            RefreshRates();
            OrderClose(Ticket, ordLots, Ask, Slip,Yellow);
            PriceReached = 0;
            trailTarget = 0;
            nSL = 0;
         }
      }
   }
   else{ //RESETS
      PriceReached = 0;
      trailTarget = 0;
      nSL = 0;
   }
}
/*
//---IN CODE INSERTS
   EXECUTION
   if(UseTrail){
      EvalTrail(ticket, Target_Increment, Stop_Increment, Initial_Jump, "inc");   ///One for each ticket(order)managed
   }
   
   // EXTERNAL VARIABLES
   extern bool    UseTrail= true;
   extern int     Target_Increment= 15;
   extern int     Stop_Increment= 15;
   extern int     Initial_Jump= 30;
   
   // GLOBAL VARIABLES
   double PriceReached;
   double trailTarget;
   double nSL;
*/
//+------------------------------------------------------------------+
void EvalBE(int Ticket, int BE_Stop){
   
   bool tckOrder = OrderSelect(Ticket,SELECT_BY_TICKET);
   int ordType = OrderType();
   double ordLots = OrderLots();
   double orderOpen = OrderOpenPrice();
   double orderSL = OrderStopLoss();
   datetime closeTime = OrderCloseTime();
   double Spread = MarketInfo(Symbol(),MODE_SPREAD)*(Point*10);
   
   //---LAST CLOSE TIMER---//
   if(closeTime!=0){
      int timerLCb = TimeCurrent() - closeTime;
   }
   else timerLCb = 0;    
      
      //BUY ORDER CONTROL
   if(tckOrder && closeTime==0){
      if(ordType==0){
         if(BE_Target==0){
            BE_Target = orderOpen + (BE_Stop*(Point*10));
         }
         if(Bid>PriceReached){//Price Reached incr.
            PriceReached=Bid;
         }
         if(PriceReached>=BE_Target){// B/E SET
            if(beSL==0){ 
               beSL = orderOpen;
            }
         }
         // BUY ORDER CLOSE
         if(Bid<=beSL+Spread && beSL!=0){// Close Order - - should be bid ?
            RefreshRates();
            OrderClose(Ticket, ordLots, Bid, Slip, Yellow);
            PriceReached = 0;
            BE_Target = 0;
            beSL = 0;
         }
      }  
      //SELL ORDER CONTROL
      else if(ordType>0){
         if(BE_Target==0){
            BE_Target = orderOpen - (BE_Stop*(Point*10));
            PriceReached=100000;// so that price starts automatically Below Price Reached
         }
         if(Ask<=PriceReached){//Price Reached incr.
            PriceReached=Ask;
         }
         if(PriceReached<=BE_Target){// B/E SET
            if(beSL==0){ 
               beSL = orderOpen;
            }
         }
         // SELL ORDER CLOSE
         if(Ask>=beSL-Spread && beSL!=0){// Close Order - - should be ask ?
            RefreshRates();
            OrderClose(Ticket, ordLots, Ask, Slip,Yellow);
            PriceReached = 0;
            BE_Target = 0;
            beSL = 0;
         }
      }
   }
   else{ //RESETS
      PriceReached = 0;
      BE_Target = 0;
      beSL = 0;
   }
}
/*
//---IN CODE INSERTS
   EXECUTION
   if(Use_BE){
      EvalBE(ticket, BE_Stop);   ///One for each ticket(order)managed
   }
   
   // EXTERNAL VARIABLES
   extern bool    Use_BE= true;
   extern int     BE_Stop= 15;
   
   // GLOBAL VARIABLES
   int timerLCb;
   double PriceReached;
   double BE_Target;
   double beSL;
*/
//+------------------------------------------------------------------+
double BoxDefinition(string Symb, string StartTime, string EndTime, string ReturnType, bool Draw, color BoxColor){
// Calculates and Returns Box information, if curHour< than EndHour Returns 0;
// Optional - Draws Box on Chart

   int BoxLength,OffsetCalc;
   double dtOffset;
   double BoxHigh, BoxLow, BoxHeight, info;
   datetime dtTimeBegin, dtTimeEnd;
   
   int curTime= TimeCurrent();
   int TF=Period();
   dtTimeBegin = StrToTime(TimeToStr(curTime, TIME_DATE) + " " + StartTime);
   dtTimeEnd = StrToTime(TimeToStr(curTime, TIME_DATE) + " " + EndTime);
   OffsetCalc = curTime - dtTimeEnd;
   dtOffset = OffsetCalc/60/TF;
   
   if(dtTimeBegin>dtTimeEnd){ //sets Start time 1 day back if Start>End
      dtTimeBegin = dtTimeBegin - 86400; // number of seconds in a day
   }
    
   BoxLength= MathAbs(dtTimeEnd - dtTimeBegin)/60/TF;

   string stime = TimeToStr(dtTimeBegin);
   string etime = TimeToStr(dtTimeEnd);
   
   if(OffsetCalc>0){
      BoxHigh= High[iHighest(Symb,TF,MODE_HIGH,BoxLength,dtOffset)];
      BoxLow= Low[iLowest(Symb,TF,MODE_LOW,BoxLength,dtOffset)];
      BoxHeight= BoxHigh - BoxLow;  
      if(ReturnType=="high"){
         info = BoxHigh;
      }
      else if(ReturnType=="low"){
         info = BoxLow;
      }
      else if(ReturnType=="height"){
         info = BoxHeight;
      }
      if(Draw){
         string BoxID = "BoxID";
         ObjectCreate(BoxID, OBJ_RECTANGLE ,0,0,0,0);
         ObjectSet(BoxID, OBJPROP_TIME1 , dtTimeBegin);
         ObjectSet(BoxID, OBJPROP_TIME2 , dtTimeEnd);
         ObjectSet(BoxID, OBJPROP_PRICE1, BoxHigh);  
         ObjectSet(BoxID, OBJPROP_PRICE2, BoxLow);
         ObjectSet(BoxID, OBJPROP_STYLE, STYLE_SOLID);
         ObjectSet(BoxID, OBJPROP_COLOR, BoxColor);
         ObjectSet(BoxID, OBJPROP_BACK, True);
      }
   }
   return(info);
}
//+------------------------------------------------------------------+
int PlaceOrder(int OrdType, double TradeSize, int Slippage, int StopLoss, int TakeProfit, int MagicNumber, string Strategy){
//Places a Corresponding Market order and returns ticket #, if failed returns -1
//INCREMENTS TradeBar 

   int ticket;
   string Journal;
   
   if(OrdType == 0) return(0);

   else if(OrdType>0){ //BUY ORDER
      Journal = StringConcatenate(Strategy," Buy Order");
      RefreshRates();
      ticket=OrderSend(Symbol(),OP_BUY,TradeSize,Ask,Slippage,Ask-StopLoss*(Point*10),Ask+TakeProfit*(Point*10),Journal,MagicNumber,0,Green);
      if(ticket<0) Print("OrderBUY error #",GetLastError());
      tradeBar=Bars;
      return(ticket); 
   }
   else{ //SELL ORDER
      Journal = StringConcatenate(Strategy," Sell Order");
      RefreshRates();
      ticket=OrderSend(Symbol(),OP_SELL,TradeSize,Bid,Slippage,Bid+StopLoss*(Point*10),Bid-TakeProfit*(Point*10),Journal,MagicNumber,0,Red);
      if(ticket<0)Print("OrderSELL error #",GetLastError());
      tradeBar=Bars; 
      return(ticket);
   }
}
//+------------------------------------------------------------------+