//+------------------------------------------------------------------+
//+                           Code generated using FxPro Quant 2.1.4 |
//+------------------------------------------------------------------+
#property strict

#define __STRATEGY_MAGIC 1001000000
#define __SLEEP_AFTER_EXECUTION_FAIL 400

//Input variables
input double _TP_SELL = 420;			// TP SELL
input double _SL_SELL = 20;			// SL SELL
input double _BREAK_EVEN_BUY = 30;			// BREAK EVEN BUY
input double _LOTE_COMPRA = 0.05;			// LOTE COMPRA
input double _LOTE_VENTA = 0.05;			// LOTE VENTA
input double _HORA_FINAL = 20;			// HORA FINAL
input double _EMA_CRUCE = 10;			// EMA CRUCE
input double _HORA_INICIO = 6;			// HORA INICIO
input double _TP_BUY = 115;			// TP BUY
input double _BREAK_EVEN_SELL = 105;			// BREAK EVEN SELL
input double _SL_BUY = 25;			// SL BUY

//Global declaration
bool _AND_2;
bool _AND;

int init() {

   return(0);
}

int start() {

   
   //Local declaration
   bool _BreakEvenBUY = false;
   bool _Break_Even = false;
   bool _Sell = false;
   bool _Buy = false;
   _BreakEvenBUY = Break_Even(2, _BREAK_EVEN_BUY);
   _Break_Even = Break_Even(0, _BREAK_EVEN_SELL);
   _AND_2 = ((iMA(Symbol(), 0, _EMA_CRUCE, 0, 0, 0, 1) > iIchimoku(Symbol(), 0, 7, 21, 42, 4, 1)) && 
   (iMA(Symbol(), 0, _EMA_CRUCE, 0, 0, 0, 2) < iIchimoku(Symbol(), 0, 7, 21, 42, 3, 2)) && 
   (iMA(Symbol(), 0, _EMA_CRUCE, 0, 0, 0, 1) > iIchimoku(Symbol(), 0, 7, 21, 42, 3, 1)) && 
   IsTime(_HORA_INICIO, _HORA_FINAL, 0, 0));
   _AND = (IsTime(_HORA_INICIO, _HORA_FINAL, 0, 0) && 
   (iMA(Symbol(), 0, _EMA_CRUCE, 0, 0, 0, 1) < iIchimoku(Symbol(), 0, 7, 21, 42, 3, 1)) && 
   (iMA(Symbol(), 0, _EMA_CRUCE, 0, 0, 0, 2) > iIchimoku(Symbol(), 0, 7, 21, 42, 4, 2)) && 
   (iMA(Symbol(), 0, _EMA_CRUCE, 0, 0, 0, 1) < iIchimoku(Symbol(), 0, 7, 21, 42, 4, 1)));
   if( _AND ) _Sell = Sell(0, _LOTE_VENTA, 1, _SL_SELL, 1, _TP_SELL, 4, 1, 0, "");
   if( _AND_2 ) _Buy = Buy(2, _LOTE_COMPRA, 1, _SL_BUY, 1, _TP_BUY, 3, 1, 0, "");

   return(0);
}

bool Break_Even(int MagicIndex, int BreakEvenPoints)
{
   double pnlPoints=0;   
   double price, sl, tp;
   double point = MarketInfo(Symbol(),MODE_POINT);
   int stopLevel = int(MarketInfo(Symbol(),MODE_STOPLEVEL) + MarketInfo(Symbol(),MODE_SPREAD));  
   int cmd; 
      
   bool result = true;   
   double newSl;

   int total = OrdersTotal();
      for(int i=total-1;i>=0;i--){
      if (!OrderSelect(i, SELECT_BY_POS)) continue;
      if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;
      
      cmd = OrderType();      
      sl = NormalizeDouble(OrderStopLoss(),Digits);
      tp = OrderTakeProfit();
       
      if (OrderType() == OP_BUY)
      {
         price = MarketInfo(Symbol(),MODE_BID);
         newSl = NormalizeDouble(OrderOpenPrice(), Digits);    
         if(((tp - price)/point) < stopLevel && tp != 0) continue;         
         if(((price - newSl)/point) < stopLevel)continue;         
         pnlPoints = (price - OrderOpenPrice())/point; 
         if ( pnlPoints < BreakEvenPoints ) continue;          
         if (sl >= newSl) continue;       
         
         if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSl, tp, 0))
         {
            printf("Error: Failed to modify trade. Ticket #%i, error code: %i", OrderTicket(), GetLastError());
            result = false;
            Sleep(__SLEEP_AFTER_EXECUTION_FAIL);
         }
      }  
      else if (OrderType() == OP_SELL)
      {
         price = MarketInfo(Symbol(),MODE_ASK);
         newSl = NormalizeDouble(OrderOpenPrice(), Digits);
         if(((price - tp)/point) < stopLevel) continue;
         if(((newSl - price)/point) < stopLevel) continue;      
         pnlPoints = (OrderOpenPrice() - price)/point;
         if (pnlPoints < BreakEvenPoints) continue;        
         if (sl <= newSl && sl != 0) continue; 
         
         if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSl, tp, 0))
         {
            printf("Error: Failed to modify trade. Ticket #%i, error code: %i", OrderTicket(), GetLastError());
            result = false;
            Sleep(__SLEEP_AFTER_EXECUTION_FAIL);
         }         
       }      
   }   
   return(result);
}   


bool Sell(int MagicIndex, double Lots, int StopLossMethod, double StopLossPoints, int TakeProfitMethod, double TakeProfitPoints, int Slippage, int MaxOpenTrades,
          int MaxFrequencyMins, string TradeComment)
{
   static double pipSize = 0;   
   if(pipSize == 0) pipSize = Point * (1 + 9 * (Digits == 3 || Digits == 5));

   double sl = 0, tp = 0;
   double stopLossPoints = 0, takeProfitPoints = 0;

   int numberOfOpenTrades = 0;
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i, SELECT_BY_POS)) continue;
      if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;
      numberOfOpenTrades ++;    
   }   

   if(MaxOpenTrades > 0 && numberOfOpenTrades >= MaxOpenTrades) return(false);  
       
   if(MaxFrequencyMins  > 0)
   {   
      int recentSeconds = MaxFrequencyMins * 60;

      for(int i=OrdersTotal()-1;i>=0;i--){
         if(!OrderSelect(i, SELECT_BY_POS)) continue;
         if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;
         if(TimeCurrent() - OrderOpenTime() < recentSeconds) return(false);
      }  

      int hstTotal=OrdersHistoryTotal();
   
      for(int i=hstTotal-1;i>=0;i--)
      {  
         if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
         if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;      
         if(TimeCurrent() - OrderOpenTime() < recentSeconds) return(false);
         break;            
      }  
   }
   
   if(Lots < MarketInfo(Symbol(),MODE_MINLOT)) return(false);
   
   if(AccountFreeMarginCheck(Symbol(), OP_SELL,Lots) <= 0) {
      Print("Sell order error: insufficient capital");
      return(false);
   }     	
   
   if (StopLossPoints > 0)
   {
      if(StopLossMethod == 0)
      {
         sl = NormalizeDouble(Bid + StopLossPoints * Point, Digits);
         stopLossPoints = StopLossPoints;
      }
      else if(StopLossMethod == 1)
      {
         sl = NormalizeDouble(Bid + StopLossPoints * pipSize, Digits);
         stopLossPoints = StopLossPoints * (1 + 9 * (Digits == 3 || Digits == 5));
      }
      else
      {
         sl = StopLossPoints;
         stopLossPoints = (sl - Bid)/Point;         
      }
   }
 
   if (TakeProfitPoints > 0)
   {
      if(TakeProfitMethod == 0)
      {
         tp = NormalizeDouble(Bid - TakeProfitPoints * Point, Digits);
         takeProfitPoints = TakeProfitPoints;
      }
      else if (TakeProfitMethod == 1)
      {
         tp = NormalizeDouble(Bid - TakeProfitPoints * pipSize, Digits);
         takeProfitPoints = TakeProfitPoints * (1 + 9 * (Digits == 3 || Digits == 5));
      }
      else
      {
         tp = TakeProfitPoints;
         takeProfitPoints = (Bid - tp)/Point; 
      }
   }     
      
   double stopLevel = MarketInfo(Symbol(),MODE_STOPLEVEL) + MarketInfo(Symbol(),MODE_SPREAD);
   
   if( (sl > 0 && stopLossPoints <= stopLevel) || (tp > 0 && takeProfitPoints <= stopLevel) )
   {
      Print("Cannot Sell: Stop loss and take profit must be at least " 
      + DoubleToStr(MarketInfo(Symbol(),MODE_STOPLEVEL) + MarketInfo(Symbol(),MODE_SPREAD),0) 
      + " points away from the current price");
      return (false);
   }
      
   RefreshRates();
	int result = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, sl, tp, "FxProQuant" + "(" + WindowExpertName() + ") " + TradeComment,__STRATEGY_MAGIC + MagicIndex);

	if (result == -1){
	   Print("Failed to Sell: " + IntegerToString(GetLastError()));
	   Sleep(__SLEEP_AFTER_EXECUTION_FAIL); 
	   return(false); 
	} 
	
   return(true);	
}


bool Buy(int MagicIndex, double Lots, int StopLossMethod, double StopLossPoints, int TakeProfitMethod, double TakeProfitPoints, int Slippage, int MaxOpenTrades,
         int MaxFrequencyMins, string TradeComment)
{
   static double pipSize = 0;   
   if(pipSize == 0) pipSize = Point * (1 + 9 * (Digits == 3 || Digits == 5));

   double sl = 0, tp = 0;
   double stopLossPoints = 0, takeProfitPoints = 0;
   
   int numberOfOpenTrades = 0;
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i, SELECT_BY_POS)) continue;
      if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;
      numberOfOpenTrades ++;    
   }   

   if(MaxOpenTrades > 0 && numberOfOpenTrades >= MaxOpenTrades) return(false);       
  
   if(MaxFrequencyMins  > 0)
   {   
      int recentSeconds = MaxFrequencyMins * 60;

      for(int i=OrdersTotal()-1;i>=0;i--){
         if(!OrderSelect(i, SELECT_BY_POS)) continue;
         if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;
         if(TimeCurrent() - OrderOpenTime() < recentSeconds) return(false);
      }  

      int hstTotal=OrdersHistoryTotal();
   
      for(int i=hstTotal-1;i>=0;i--)
      {  
         if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
         if(OrderMagicNumber() != __STRATEGY_MAGIC + MagicIndex || OrderSymbol() != Symbol()) continue;      
         if(TimeCurrent() - OrderOpenTime() < recentSeconds) return(false);
         break;            
      }  
   }
   
   if(Lots < MarketInfo(Symbol(),MODE_MINLOT)) return(false);
   
   if(AccountFreeMarginCheck(Symbol(), OP_SELL,Lots) <= 0) {
      Print("Buy error: insufficient capital");
      return(false);
   }   

   if (StopLossPoints > 0)
   {
      if(StopLossMethod == 0)
      {
         sl = NormalizeDouble(Ask - StopLossPoints * Point, Digits);
         stopLossPoints = StopLossPoints;
      }
      else if (StopLossMethod == 1)
      {
         sl = NormalizeDouble(Ask - StopLossPoints * pipSize, Digits);
         stopLossPoints = StopLossPoints * (1 + 9 * (Digits == 3 || Digits == 5));
      }
      else
      {
         sl  = StopLossPoints;
         stopLossPoints = (Ask - sl)/Point; 
      }
   }
   
   if (TakeProfitPoints > 0)
   {
      if(TakeProfitMethod == 0)
      {
         tp = NormalizeDouble(Ask + TakeProfitPoints * Point, Digits);
         takeProfitPoints = TakeProfitPoints;
      }
      else if (TakeProfitMethod == 1)
      {
         tp = NormalizeDouble(Ask + TakeProfitPoints * pipSize, Digits);
         takeProfitPoints = TakeProfitPoints * (1 + 9 * (Digits == 3 || Digits == 5));
      }
      else
      {
         tp = TakeProfitPoints;
         takeProfitPoints = (tp - Ask)/Point; 
      }
   }  
   
   double stopLevel = MarketInfo(Symbol(),MODE_STOPLEVEL) + MarketInfo(Symbol(),MODE_SPREAD);
   
   if( (sl > 0 && stopLossPoints <= stopLevel) || (tp > 0 && takeProfitPoints <= stopLevel) )
   {
      Print("Cannot Buy: Stop loss and take profit must be at least " 
      + DoubleToStr(MarketInfo(Symbol(),MODE_STOPLEVEL) + MarketInfo(Symbol(),MODE_SPREAD),0) 
      + " points away from the current price");
      return (false);
   }
          
   RefreshRates();
	int result = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, sl, tp, "FxProQuant" + "(" + WindowExpertName() + ") " + TradeComment, __STRATEGY_MAGIC + MagicIndex);
	
	if (result == -1){
		Print("Failed to Buy: " + IntegerToString(GetLastError()));
		Sleep(__SLEEP_AFTER_EXECUTION_FAIL);
	   return(false); 
	}
	 
   return(true); 
}


bool IsTime (int startHour, int endHour, int startMinute, int endMinute)
{
   if (startHour < 0 || startHour > 23 || endHour < 0 || endHour > 23 ||
       startMinute < 0 || startMinute > 59 || endMinute < 0 || endMinute > 59)
       return false;
   
   int startTime = startHour*60 + startMinute;
   int endTime = endHour*60 + endMinute;
   int time = Hour()*60 + Minute();
   
   if (startTime < endTime)
      return (time >= startTime && time <= endTime);
   else if (startTime > endTime)
      return (time >= startTime || time <= endTime);
   else
      return (time == startTime);
}
