//+------------------------------------------------------------------+
//|                                         H1DailyHighestLowest.mq4 |
//|                                                             jdfx |
//|                                         https://www.twitter.com/ |
//+------------------------------------------------------------------+
#property copyright "jdfx"
#property link      "https://www.twitter.com/"
#property version   "1.00"
#property strict

//--- input parameters
input double   Lots=0.4;
input int      MagicNumber=9997;
input bool     CloseHalfOrder=false;
double         PreviusDayHigh=0,
               PreviusDayLow=0,
               CurrentDayHigh=0,
               CurrentDayLow=0;
bool           LongSignal=false,
               ShortSignal=false,
               LongEntry=false,
               ShortEntry=false,
               HalfReady=false;               
double         trackPrice=0;
int            openedOrderTicket=0,
               TrailingStopMult=1,
               DigitMultiplier=1,
               pips=1;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("Hello World!");
//--- create timer
   EventSetTimer(60);
   if(Digits == 5 || Digits == 3)
   {
      DigitMultiplier = 10;
   }
//---
   CreateLine("prevDH",0,STYLE_SOLID,clrRed);
   CreateLine("prevDL",0,STYLE_SOLID,clrRed);
   
   CreateLine("currDH",0,STYLE_DOT,clrRed);
   CreateLine("currDL",0,STYLE_DOT,clrRed);
   
   CreateLine("tdHO",0,STYLE_DOT,clrYellow);
   CreateLine("tdLO",0,STYLE_DOT,clrYellow);
   
   //CreateLine("sl",0,STYLE_DOT,clrAqua);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
      
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   PreviusDayHigh = iHigh(Symbol(),PERIOD_D1,1);
   PreviusDayLow = iLow(Symbol(),PERIOD_D1,1);
   
   if(PreviusDayHigh == CurrentDayHigh && PreviusDayLow == CurrentDayLow)
   {
      LongSignal=false;
      ShortSignal=false;
   }
   
   MoveLine("prevDH",PreviusDayHigh);
   MoveLine("prevDL",PreviusDayLow);
   
   CurrentDayHigh = iHigh(Symbol(),PERIOD_D1,0);
   CurrentDayLow = iLow(Symbol(),PERIOD_D1,0);
   
   MoveLine("currDH",CurrentDayHigh);
   MoveLine("currDL",CurrentDayLow);
   
   datetime now  = Time[0],
            bod  = now - now % 86400;
            
   double highestTodayOpen = iOpen(Symbol(),PERIOD_H1,0),
          lowestTodayOpen = iOpen(Symbol(),PERIOD_H1,0);

   int i = 0;
   datetime currentH1Time;
   do
   {
      currentH1Time = iTime(Symbol(),PERIOD_H1,i);
      double openH1Price = iOpen(Symbol(),PERIOD_H1,i);
      if(highestTodayOpen < openH1Price) {highestTodayOpen = openH1Price;}
      if(lowestTodayOpen > openH1Price) {lowestTodayOpen = openH1Price;}
      i++;
   }
   while(currentH1Time>bod);   
   
   MoveLine("tdHO",highestTodayOpen);
   MoveLine("tdLO",lowestTodayOpen);
   
   //trading logic
   
   //Trail StopLoss and Closed Orders update
   if(IsTradeAllowed() && openedOrderTicket!=0)
   {
      if(!VerifEntryState())
      {
         if(OrderSelect(openedOrderTicket,SELECT_BY_TICKET,MODE_TRADES))
         {
            pips = 10*DigitMultiplier;
            //if(LongEntry)
            //{
            //   MoveLine("sl",Bid);
            //   //MoveLine("sl",NormalizeDouble(Bid-((pips*TrailingStopMult)+(1*DigitMultiplier))*Point,Digits));
            //}
            //else if(ShortEntry)
            //{
            //   MoveLine("sl",Ask);
            //   //MoveLine("sl",NormalizeDouble(Ask+(pips*TrailingStopMult)*Point,Digits));
            //}
            
            
            if(LongEntry && NormalizeDouble(Bid-((pips*TrailingStopMult)+(1*DigitMultiplier))*Point,Digits) >= OrderOpenPrice())
            {
               Print("LongEntry: Moving StopLoss");
               bool l = OrderModify(openedOrderTicket,OrderOpenPrice(),NormalizeDouble(Bid-(pips+(1*DigitMultiplier))*Point,Digits),OrderTakeProfit(),0,clrBlueViolet);
               if(!HalfReady && CloseHalfOrder)
               {
                  if(OrderClose(openedOrderTicket,NormalizeDouble(Lots/2,2),Bid,3,clrGray))
                  {
                     openedOrderTicket++;
                     HalfReady=true;
                  }
               }
               TrailingStopMult++;
            }
            else if(ShortEntry && NormalizeDouble(Ask+(pips*TrailingStopMult)*Point,Digits) <= OrderOpenPrice())
            {
               Print("ShortEntry: Moving StopLoss");
               bool s = OrderModify(openedOrderTicket,OrderOpenPrice(),NormalizeDouble(Ask+(pips-(1*DigitMultiplier))*Point,Digits),OrderTakeProfit(),0,clrOrangeRed);
               if(!HalfReady && CloseHalfOrder)
               {
                  if(OrderClose(openedOrderTicket,NormalizeDouble(Lots/2,2),Ask,3,clrGray))
                  {
                     openedOrderTicket++;
                     HalfReady=true;
                  }
               }
               TrailingStopMult++;
            }
         }
      
         if(OrderSelect(openedOrderTicket,SELECT_BY_TICKET,MODE_HISTORY))
         {
            bool closedBySL = false;
            if(true)
            {
               Print("WUT! ",openedOrderTicket," ",OrderClosePrice()," ",OrderStopLoss());
               Print("OrderCloseTime: ",OrderCloseTime());
               
               if(OrderType()==OP_BUY && OrderClosePrice() <= OrderStopLoss())
               {
                  Print("OP_BUY: Order Closed by StopLoss");
                  closedBySL = true;
               }
               else if(OrderType()==OP_SELL && OrderClosePrice() >= OrderStopLoss())
               {
                  Print("OP_SELL: Order Closed by StopLoss");
                  closedBySL = true;
               }
               
               if(closedBySL)
               {
                  closedBySL = false;
                  LongEntry = false;
                  ShortEntry = false;
                  openedOrderTicket = 0;
                  TrailingStopMult = 1;
                  HalfReady=false;
               }
            }
         }
      }
   }
   
   double currentM15OpenPrice = iOpen(Symbol(),PERIOD_M15,0);
   //Signal and Entry Logic
   if(trackPrice!=currentM15OpenPrice)
   {   
      if(VerifState() && currentM15OpenPrice < lowestTodayOpen) //buy signal
      {
         Print("M15 Long Signal, waiting price rising.");
         if(currentM15OpenPrice < CurrentDayLow)
         {
            Print("Warning: Price breackout current day lowest price.");
         }
         LongSignal = true;
      }
      else if(VerifState() && currentM15OpenPrice > highestTodayOpen) //sell signal
      {
         Print("M15 Short Signal, waiting price dropping.");
         if(currentM15OpenPrice > CurrentDayHigh)
         {
            Print("Warning: Price breackout current day highest price.");
         }
         ShortSignal = true;
      }
      
      Print("new M15 open");
      Print("Ready for trade:",VerifState(),LongSignal,LongEntry,ShortSignal,ShortEntry);
      Print("LongSingal:",currentM15OpenPrice < lowestTodayOpen);
      Print("ShortSignal:",currentM15OpenPrice > highestTodayOpen);
      
      if(IsTradeAllowed())
      {
         pips = 1*DigitMultiplier;
         if(openedOrderTicket==0)
         {
            Print("LE:",Ask > lowestTodayOpen);
            Print("SE:",Bid < highestTodayOpen);
            if(LongSignal && VerifEntryState() && Ask > lowestTodayOpen)
            {
               openedOrderTicket = OrderSend(Symbol(),OP_BUY,Lots,Ask,3,NormalizeDouble(CurrentDayLow-pips*Point,Digits),NULL,NULL,MagicNumber,NULL,clrBlue);
               if(openedOrderTicket>0)
               {
                  Print("Ticket #",openedOrderTicket);   
                  LongEntry = true;
                  LongSignal = false;
               }
            }
            else if(ShortSignal && VerifEntryState() && Bid < highestTodayOpen){
               openedOrderTicket = OrderSend(Symbol(),OP_SELL,Lots,Bid,3,NormalizeDouble(CurrentDayHigh+pips*Point,Digits),NULL,NULL,MagicNumber,NULL,clrRed);
               if(openedOrderTicket>0)
               {
                  Print("Ticket #",openedOrderTicket);
                  ShortEntry = true;
                  ShortSignal = false;
               }
            }
            
            if(openedOrderTicket!=0)
            {
               Print("Ticket:",openedOrderTicket);
               Print("Open positions:",OrderSelect(openedOrderTicket,SELECT_BY_TICKET,MODE_TRADES));
               Print("Closed positions:",OrderSelect(openedOrderTicket,SELECT_BY_TICKET,MODE_HISTORY));
            }
         }
      }
      trackPrice = currentM15OpenPrice;
   }
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double ret=0.0;
//---

//---
   return(ret);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }
//+------------------------------------------------------------------+

void CreateLine(string name,double price,int style,color cl)
{
   if (ObjectFind(0,name) < 1)
   {
      if (!ObjectCreate(
         name,
         OBJ_HLINE,
         0,    
         0,
         price,
         0,
         0,
         0,
         0
         ))
         {
            Print("Error: can't create line! code #",GetLastError());
            return;
         }
      ObjectSetInteger(0,name,OBJPROP_COLOR,cl);
      ObjectSetInteger(0,name,OBJPROP_STYLE,style);
   }
}

void MoveLine(string name,double price)
{
   if(!ObjectMove(0,name,0,0,price))
     {
      Print(__FUNCTION__,
            ": failed to move the horizontal line! Error code = ",GetLastError());
      return;
     }
}

bool VerifState()
{
   return !LongSignal && !LongEntry && !ShortSignal && !ShortEntry;
}

bool VerifEntryState()
{
   return !LongEntry && !ShortEntry;
}