//+-----------------------------------------------------------------------------+
//|                                                    Daily Scalping v1.0e.mq4 |
//|                                                                Skyline 2007 |
//|                                                                             |
//+-----------------------------------------------------------------------------+
#property copyright "Skyline 2007"
#property link      ""
#include <stdlib.mqh>

// v1.0  (07 Feb 2007) : Start Project 
// v1.0a (07 Feb 2007) : Add GMT_Shift variable
// v1.0b (16 Feb 2007) : Added MagicNumber routine based on pair and timeframe
// v1.0c (17 Feb 2007) : Added routine TotalOrders to count only active order related to current EA (Thanks to Vitalykk)
//                       Added routine OrdersLossInDay to control losses in the same day. Users have the option to change how much loss trade they want setting external variable MaxLossesTradesPerDay.
// v1.0d (19 Feb 2007) : Fixed bug that prevent , when an order was not dispatched, to open reverse trade correctly. 
//                       Handled the case of doji candle that EA now will ignore to determine the trend situation from last 3 candles.
// v1.0e (19 Feb 2007) : Fixed bug on CheckTrend for doji candle routine (Thanks to Vitalykk)
//                       Added function OrdersTakeProfit to avoid EA enter again the market until next day.


//---- Definizione parametri esterni 
extern double    GMT_Shift             = 0;
extern int       TakeProfit            = 100;
extern int       StopLoss              = 40;  
extern int       HourToCloseOrders     = 23;
extern bool      SundayCandleExists    = true;
extern double    Lots                  = 0.1; 
extern bool      UseMoneyManagement    = false;
extern int       Risk                  = 0;
extern int       Slippage              = 3;
extern int       MaxLossesTradesPerDay = 2; 
extern string    EAComment;

//----- Definizione parametri interni 
static int TradeStatus = 0; //0 = Trades disabilitati , 1 = Solo Buy permessi, 2 = Solo Sell permessi 
int MagicNumber;
string EA_Comment="";

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   string TradeMode;
   
   // Calcola dimensione Lot in base all'Equity
   if (UseMoneyManagement==true) Lots = CalcolaLot(Risk);   
   
   // Calcola MagicNumber a seconda della coppia e timeframe 
   MagicNumber = MagicFromSymbol();

   // Attiva ordine alle 00:00 GMT 
   OpenOrderMidnight(Lots);
 
   // Controlla ordini chiusi in perdita
   OrdersLossInDay();
   
   // Controlla se TP è stato raggiunto 
   OrdersTakeProfit();

   // Attiva ordini successivi
   OpenNextOrders(Lots);
   
   // Chiude ordini allo scadere di HourToCloseOrders
   CloseAllOrders(HourToCloseOrders);
   
   // Commenti
   if (TradeStatus == 0) TradeMode = "NONE";
   if (TradeStatus == 1) TradeMode = "BUY";
   if (TradeStatus == 2) TradeMode = "SELL";
   
   Comment("\nDaily Scalping EA v1.0b (Skyline 2007.e3)",
           "\nCompiled version on 16 Feb 2007",
           "\n\n---------------------------------------",
           "\nMagicNumber : ",MagicNumber,
           "\nNext Trade : ",TradeMode,
           "\nTimeFrame to be used : H1",
           "\n---------------------------------------");
	EA_Comment = EAComment + " Skyline";
           
   return(0);
  }

// ===== Routine per controllare se il TP è stato raggiunto e disabilitare i trades =====
int OrdersTakeProfit()
{
 int total,cnt;
 int TradeWin=0;
 
 int hstTotal=OrdersHistoryTotal();
   
 for(cnt=0;cnt<hstTotal;cnt++)
 {
   OrderSelect(cnt, SELECT_BY_POS, MODE_HISTORY);
   if (OrderMagicNumber()==MagicNumber)
   {
    if (NormalizeDouble(OrderClosePrice(),Digits)==NormalizeDouble(OrderTakeProfit(),Digits) && TimeDay(OrderCloseTime())==Day()) TradeWin++;
   }  // if (OrderMagicNumber()==MagicNumber)
 }  // for 
 if ( TradeWin == 1 ) TradeStatus = 0; // disable trades
 //Print("TradeLoss = ",TradeLoss);
}

// ===== Routine per contare gli ordini chiusi in perdita nello stesso giorno =====
int OrdersLossInDay()
{
 int total,cnt;
 int TradeLoss=0;
 
 int hstTotal=OrdersHistoryTotal();
   
 for(cnt=0;cnt<hstTotal;cnt++)
 {
   OrderSelect(cnt, SELECT_BY_POS, MODE_HISTORY);
   if (OrderMagicNumber()==MagicNumber)
   {
    if (NormalizeDouble(OrderClosePrice(),Digits)==NormalizeDouble(OrderStopLoss(),Digits) && TimeDay(OrderCloseTime())==Day()) TradeLoss++;
   }  // if (OrderMagicNumber()==MagicNumber)
 }  // for 
 if ( TradeLoss == MaxLossesTradesPerDay ) TradeStatus = 0; // disable trades
 //Print("TradeLoss = ",TradeLoss);
}
  
// ===== Routine per chiudere tutti gli ordini =====
void CloseAllOrders(int Ora)
{
 int total,cnt;
 
 total = TotalOrders();
 
 if ( Hour()==MathMod(Ora+GMT_Shift,24) )
 {
  TradeStatus = 0; // azzera variabile globale per non aprire più trade
  
  for(cnt=0;cnt<total;cnt++)
  {
   OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
   if (OrderMagicNumber()==MagicNumber)
   {
    if (OrderType() == OP_BUY)  OrderClose(OrderTicket(),OrderLots(), Bid, Slippage, LimeGreen);
    if (OrderType() == OP_SELL) OrderClose(OrderTicket(),OrderLots(), Ask, Slippage, Red);
   }  // if (OrderMagicNumber()==MagicNumber)
  }  // for 
 } // if
}

// ===== Routine per aprire il primo ordine alle 00:00 GMT =====
void OpenOrderMidnight(double Lot)
{  int Ticket,Errore; 
   double SL,TP;
   int ActualSpread;
   
   RefreshRates();
    
   int Total = TotalOrders();
   
   if ( Total < 1 && Hour()==MathMod(24+GMT_Shift,24) && DayOfWeek()>=1 && DayOfWeek()<=5 ) 
   {
     TradeStatus = 0; // azzera variabile globale 
      
   // Controlla BUY Order
   if (CheckTrend()=="BUY")
    {   
      
      // Controlla SL 
      if (StopLoss < MarketInfo(Symbol(),MODE_STOPLEVEL)) StopLoss = MarketInfo(Symbol(),MODE_STOPLEVEL);
      if (StopLoss == 0) SL = 0;
      SL = Ask-StopLoss*Point;
      if (TakeProfit == 0) TP = 0;
      else TP = Ask+TakeProfit*Point;
      // Piazza l'ordine BUY
      Ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,SL,TP,EA_Comment,MagicNumber,0,Blue);
          
      if(Ticket<0)
      {
       Errore=GetLastError();
       Print("ERROR ON BUY ORDER (",Errore,") : ",ErrorDescription(Errore));
      } 
      else 
      {
       TradeStatus = 2; // Prossimo trade è Sell
      } 
     } 
   }
   
   // Rileva ordini relativi a questa EA (thanks to Vitalykk)
   Total = TotalOrders(); 
   
   if ( Total < 1 && Hour()==MathMod(24+GMT_Shift,24) && DayOfWeek()>=1 && DayOfWeek()<=5 ) 
   {
   
     // Controlla SELL Order
     if (CheckTrend()=="SELL")
     {
 
      // Setta SL 
      if (StopLoss < MarketInfo(Symbol(),MODE_STOPLEVEL)) StopLoss = MarketInfo(Symbol(),MODE_STOPLEVEL);
      if (StopLoss == 0) SL = 0;
      SL = Bid+StopLoss*Point;
      if (TakeProfit == 0) TP = 0;
      else TP = Bid-TakeProfit*Point;
      
      // Piazza Ordine SELL       
      Ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,SL,TP,EA_Comment,MagicNumber,0,Blue);
         
      if(Ticket<0)
      {
       Errore=GetLastError();
       Print("ERROR ON SELL ORDER (",Errore,") : ",ErrorDescription(Errore));
      } 
      else
      {
       TradeStatus = 1; // Prossimo trade è Buy
      }
     }    
   }
}

// ===== Routine per aprire ordini durante la giornata al raggiungimento dello SL o TP =====
void OpenNextOrders(double Lot)
{  int Ticket,Errore; 
   double SL,TP;
   int ActualSpread;
   
   RefreshRates();

   int Total = TotalOrders();
   
   if ( Total < 1 && DayOfWeek()>=1 && DayOfWeek()<=5 ) 
   {
   // Controlla BUY Order
   if ( TradeStatus == 1 )
    {   
      
      // Controlla SL 
      if (StopLoss < MarketInfo(Symbol(),MODE_STOPLEVEL)) StopLoss = MarketInfo(Symbol(),MODE_STOPLEVEL);
      if (StopLoss == 0) SL = 0;
      SL = Ask-StopLoss*Point;
      if (TakeProfit == 0) TP = 0;
      else TP = Ask+TakeProfit*Point;
      
      // Piazza l'ordine BUY
      Ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,SL,TP,EA_Comment,MagicNumber,0,Blue);    
         
      if(Ticket<0)
      {
       Errore=GetLastError();
       Print("ERROR ON BUY ORDER (",Errore,") : ",ErrorDescription(Errore));
      }  
      else
      {
       TradeStatus = 2; // Prossimo trade è Sell 
      }
     } 
   }
  
   Total = TotalOrders();
   if ( Total < 1 && DayOfWeek()>=1 && DayOfWeek()<=5 ) 
   {  
     // Controlla SELL Order
     if ( TradeStatus == 2 )
     {
 
      // Setta SL 
      if (StopLoss < MarketInfo(Symbol(),MODE_STOPLEVEL)) StopLoss = MarketInfo(Symbol(),MODE_STOPLEVEL);
      if (StopLoss == 0) SL = 0;
      SL = Bid+StopLoss*Point;
      if (TakeProfit == 0) TP = 0;
      else TP = Bid-TakeProfit*Point;
      
      // Piazza Ordine SELL       
      Ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,SL,TP,EA_Comment,MagicNumber,0,Blue);
          
      if(Ticket<0)
      {
       Errore=GetLastError();
       Print("ERROR ON SELL ORDER (",Errore,") : ",ErrorDescription(Errore));
      } 
      else
      {
       TradeStatus = 1; // Prossimo trade è Buy
      }
     }    
   }
}

// ===== Routine per controllare il trend ===== 
string CheckTrend()
{

 // Check 1 day ago candle
 int DaysShift = 1;
 string C1="NONE",C2="NONE",C3="NONE";
 //if ( SundayCandleExists == true && DayOfWeek() == 1 ) DaysShift++; // if today is Monday then skip the Sunday candle
 if (SundayCandleExists == true && TimeDayOfWeek(iTime(NULL,PERIOD_D1,DaysShift)) == 0)  DaysShift++; // if candle is Monday then skip Sunday candle
 if (iOpen(NULL,PERIOD_D1,DaysShift)==iClose(NULL,PERIOD_D1,DaysShift)) DaysShift++;
 if (iOpen(NULL,PERIOD_D1,DaysShift)<iClose(NULL,PERIOD_D1,DaysShift)) C1 = "BULLISH";
 if (iOpen(NULL,PERIOD_D1,DaysShift)>iClose(NULL,PERIOD_D1,DaysShift)) C1 = "BEARISH";
 // Print("C1_DaysShift = ",DaysShift); // for debug purpouse

 // Check 2 days ago candle
 DaysShift++;
 if (SundayCandleExists == true && TimeDayOfWeek(iTime(NULL,PERIOD_D1,DaysShift)) == 0)  DaysShift++; // if candle is Monday then skip Sunday candle
 if (iOpen(NULL,PERIOD_D1,DaysShift)==iClose(NULL,PERIOD_D1,DaysShift)) DaysShift++;
 if (iOpen(NULL,PERIOD_D1,DaysShift)<iClose(NULL,PERIOD_D1,DaysShift)) C2 = "BULLISH";
 if (iOpen(NULL,PERIOD_D1,DaysShift)>iClose(NULL,PERIOD_D1,DaysShift)) C2 = "BEARISH";
 //Print("C2_DaysShift = ",DaysShift); // for debug purpouse

 // Check 3 days ago candle
 DaysShift++;
 if (SundayCandleExists == true && TimeDayOfWeek(iTime(NULL,PERIOD_D1,DaysShift)) == 0) DaysShift++; // if candle is Monday then skip Sunday candle
 if (iOpen(NULL,PERIOD_D1,DaysShift)==iClose(NULL,PERIOD_D1,DaysShift)) DaysShift++;
 if (iOpen(NULL,PERIOD_D1,DaysShift)<iClose(NULL,PERIOD_D1,DaysShift)) C3 = "BULLISH";
 if (iOpen(NULL,PERIOD_D1,DaysShift)>iClose(NULL,PERIOD_D1,DaysShift)) C3 = "BEARISH";
 // Print("C3_DaysShift = ",DaysShift);
 
 // Print("C1 = ",C1," C2 = ",C2," C3 = ",C3); // for debug purpouse
 
 // BULLISH Condition
 if (
    (C1=="BULLISH" && C2=="BEARISH" && C3=="BULLISH") ||
    (C1=="BULLISH" && C2=="BULLISH" && C3=="BEARISH") ||
    (C1=="BULLISH" && C2=="BEARISH" && C3=="BEARISH") ||     
    (C1=="BEARISH" && C2=="BEARISH" && C3=="BEARISH")
    )
 return("BUY"); 
 
 // BEARISH Condition
 if (
     (C1=="BEARISH" && C2=="BULLISH" && C3=="BEARISH") ||
     (C1=="BEARISH" && C2=="BEARISH" && C3=="BULLISH") ||
     (C1=="BEARISH" && C2=="BULLISH" && C3=="BULLISH") ||
     (C1=="BULLISH" && C2=="BULLISH" && C3=="BULLISH")
    )   
 return("SELL");   
}

// ===== Routine per il calcolo del Lot nel caso di Money Management =====
double CalcolaLot(int Rischio)
{
  double Lot=0;
  Lot=AccountEquity()* Rischio/100/1000;
  if( Lot>=0.1 )
  {
    Lot = NormalizeDouble(Lot,1); 
  }
  else Lot = NormalizeDouble(Lot,2);
  if (Lot > MarketInfo(Symbol(),MODE_MAXLOT)) { Lot = MarketInfo(Symbol(),MODE_MAXLOT); } // Avoid possible Lot value overflow if lot exceed maximum value allowed by broker
  if (Lot < MarketInfo(Symbol(),MODE_MINLOT)) { Lot = MarketInfo(Symbol(),MODE_MINLOT); } // Avoid possible Lot value overflow if lot exceed minimum value allowed by broker
  return(Lot);
}

// ===== Routine per calcolare MagicNumber diverso per ogni coppia e periodo =====
int MagicFromSymbol() 
{ // included by Renato 
   int MagicNumber=0;  
   for (int i=0; i<5; i++) 
   {  
     MagicNumber=MagicNumber*3+30+StringGetChar(Symbol(),i);  
   }  
   MagicNumber=MagicNumber*3+30+Period();  
   return(MagicNumber);  
}

// ===== Routine per calcolare quanti ordini aperti ci sono per questa EA ===== 
int TotalOrders()
{  
   int cnt; 
   int Total = 0;
   for(cnt=0;cnt<OrdersTotal();cnt++)
   {
    OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
    if (OrderMagicNumber()==MagicNumber) Total ++;
   }
  return(Total); 
}

//+------------------------------------------------------------------+