//+------------------------------------------------------------------+
//|                                       H4Media200StrategeTest.mq4 |
//|                                       Rodolfo Leonardo de Morais |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "rodolfo.leonardo@gmail.com"
#property link "https://www.mql5.com"
#property version "1.00"
//#property strict

extern string ___Configuracoes_Gerais___ = "------------Configuracoes Gerais------------";
extern bool chartDisplay = FALSE; // Habilita informa��es na tela
extern color   background_color = Teal; // Cor de fundo das informa��es

extern bool UseManualLots = FALSE; // Usa Lote Manual (Desabilita RiskPercent)
extern double Lots = 1; // Quantidade de Lote caso UseManualLots = false

extern double TakeProfit =0.0; // Lucro planejado -  0 desativa
extern double MaxSpread = 20.0; // Maximo de Spread p/ abertura de Ordem
extern double TrailingStop = 0.0; // Deslize de StopLoss -  0 desativa
extern int     slippage    = 3; // Toler�ncia de ordem desliza / cota��es de fechamento

extern string system1_comment = "Forex ROBO H4 V2.0"; // Coment�rio EA
extern int MagicNumber = 20160905; // Identificador de EA
extern ENUM_TIMEFRAMES  TimeFrame = PERIOD_H4; // Periodo de atua��o
extern int     PeriodoMM    = 500;
extern double vMargem = 30; // Margem da MM p/ inicio da Compra/Venda

extern bool DiminuirCadaLoteAberto = true; // Diminui a Qtd de Lotes a cada lote aberto
extern bool  Martingale = false; // Habilita Martingale

extern double RiskPercent = 1; // Percentual de Risco (RiskPercent)
extern double MaxLotOrder = 0.0; // Maximo de Lote por Ordem -  0 desativa
extern double MaxOrderLot = 0.0; // Maximo de Ordem a ser aberto conjuntas  -  0 desativa
//extern string Chave = "";

extern string ___HORARIO_ATUACAO___ = "------------HORARIO DE ATUACAO------------";
extern bool Trade_in_Monday  =true; 
extern bool Trade_in_Tuesday =true; 
extern bool Trade_in_Wednesday=true;
extern bool Trade_in_Thursday=true; 
extern bool Trade_in_Friday  =true;

extern string StartHour = "00:00"; 
extern string EndHour   = "23:00";  

bool gi_244 = TRUE;
int gi_800;
bool Gi_596 = true;

int vQtdOrdensAbertas = 0;

datetime vUltCandleVerificado;
int maxOrdens = 1;
double vSpread = 0;
double vFundo = 0;

int sinal = 0;
int vNovoFundo = 0;
double shortEma, longEma;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init() {
    //---
 
    if (gi_244) gi_800 = 0;
    else gi_800 = 1;
    //---
    return (0);
    
  // TakeProfit =  10.0 * TakeProfit;
    
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit() {
    return (0);
}


void Informacoes() {
   double Ld_0;
   double Ld_8;
   double Ld_16;
   double Ld_24;
   double Ld_32;
   double Ld_40;
   double Ld_48;
   double Ld_56;
   string Ls_64;
   string Ls_72;
   int Li_84;

   if ( !IsOptimization())
    {
     
      Ls_64 = "==========================\n";
      Ls_64 = Ls_64 + "               " + "ROBO H4 v2.00" 
      + "\n";
      Ls_64 = Ls_64 + "==========================\n";
      Ls_64 = Ls_64 + "  Base Lot Size: " + DoubleToStr(Lots, 2) + " lots\n";
      Ls_64 = Ls_64 + "  Slippage: " + DoubleToStr(slippage, 2) + " \n";
      Ls_64 = Ls_64 + "  TakeProfit: " + DoubleToStr(TakeProfit, 2) + " pips\n";
      Ls_64 = Ls_64 + "  TrailingStop: " + DoubleToStr(TrailingStop, 2) + " pips\n";
      Ls_64 = Ls_64 + "  UseManualLots: " + UseManualLots + "\n";
      Ls_64 = Ls_64 + "  RiskPercent: " + DoubleToStr(RiskPercent, 2) + " %\n";
      Ls_64 = Ls_64 + "  MaxOrderLot: " + DoubleToStr(MaxOrderLot, 2) + " \n";
      Ls_64 = Ls_64 + "  MaxLotOrder: " + DoubleToStr(MaxLotOrder, 2) + " lots\n";
      Ls_64 = Ls_64 + "  MaxSpread: " + DoubleToStr(MaxSpread, 2) + " pips\n";
      Ls_64 = Ls_64 + "==========================\n";
      Ls_64 = Ls_64 + "  QtdOrderOpen: " + vQtdOrdensAbertas + " \n";
      Ls_64 = Ls_64 + "  Spread: " + vSpread + " \n";
      Ls_64 = Ls_64 + "  Lucro/Perda: " + SomaOrderProfitDoDia() + " \n";
      Ls_64 = Ls_64 + "  Fundo/Topo: " + vFundo + " \n";
      Ls_64 = Ls_64 + "  Margem NEG : " + NormalizeDouble((longEma - vMargem * Point), Digits) + " \n";
      Ls_64 = Ls_64 + "  Margem POS : " + NormalizeDouble((longEma + vMargem * Point), Digits) + " \n";
      Ls_64 = Ls_64 + "  Last Close : " + NormalizeDouble(iClose(Symbol(),TimeFrame,1), Digits) + " \n";
      Ls_64 = "==========================\n";
      Ls_64 = "Creditos: rodolfo.leonardo@gmail.com \n";
      Ls_64 = "==========================\n";
      
      
      Comment(Ls_64);
      Li_84 = 11;
    
      if (Gi_596 || Seconds() % 5 == 0) {
         Gi_596 = FALSE;
         for (int count_88 = 0; count_88 < 9; count_88++) {
            for (int count_92 = 0; count_92 < Li_84; count_92++) {
               ObjectDelete("background" + count_88 + count_92);
               ObjectDelete("background" + count_88 + ((count_92 + 1)));
               ObjectDelete("background" + count_88 + ((count_92 + 2)));
               ObjectCreate("background" + count_88 + count_92, OBJ_LABEL, 0, 0, 0);
               ObjectSetText("background" + count_88 + count_92, "n", 30, "Wingdings", background_color);
               ObjectSet("background" + count_88 + count_92, OBJPROP_XDISTANCE, 20 * count_88);
               ObjectSet("background" + count_88 + count_92, OBJPROP_YDISTANCE, 23 * count_92 + 9);
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
int start()

{

if(chartDisplay){
   Informacoes();
}


    int cnt, ticket, total;


    if (Bars < 10) {
        Print("bars less than 100");
        return (0);
    }
  
   //double max = NormalizeDouble(iHigh(Symbol(),1440,0),Digits);
   //double min = NormalizeDouble(iLow (Symbol(),1440,0),Digits);
   //double opp=NormalizeDouble(iOpen(Symbol(),1440,0),Digits);
   //double cl=NormalizeDouble(iClose(Symbol(),1440,0),Digits);

     if(!TimeFilter()) return (0);
     if(!IsExpertEnabled()) return (0);
     

    //Caso o spreed seja maior que o parametrizado foge
    vSpread = MarketInfo(Symbol(), MODE_SPREAD);
    if (vSpread > MaxSpread) return (0);
    
    
   
    if(!UseManualLots){
       Lots = CalculaQtdLotesRisco(RiskPercent);
       }
    
    if(Martingale &&  vQtdOrdensAbertas>0 ) Lots = Lots * 1.5 ;
    
    if(DiminuirCadaLoteAberto && vQtdOrdensAbertas>0 ) Lots = Lots / vQtdOrdensAbertas;
    

    
    if( MaxLotOrder > 0 && Lots > MaxLotOrder) Lots=MaxLotOrder;
    
    
    
    Lots = NormalizaLotes(Lots);

   
    
    longEma = iMA(Symbol(), TimeFrame, PeriodoMM, 0, MODE_EMA, PRICE_CLOSE, gi_800 + 0);

    int isCrossed = Crossed(iClose(Symbol(),TimeFrame,2), longEma);
    
    total = OrdersTotal();
    
    if(MaxOrderLot > 0 && vQtdOrdensAbertas > MaxOrderLot ) return(0);
    
    //Cruzou p/ baixo compra
    if (NormalizeDouble(iClose(Symbol(),TimeFrame,1), Digits) < NormalizeDouble((longEma - vMargem * Point),Digits) ) {
       
       //Indentifica novo Fundo
       if(NormalizeDouble(iLow (Symbol(),TimeFrame,1),Digits) <   vFundo && vNovoFundo == 0 ) {
           vNovoFundo = 1;
           vFundo = NormalizeDouble(iLow (Symbol(),TimeFrame,1),Digits);
        }
    
    
       // verifica se candle anterior fechou vermelho (fechamento abaixo da abertura)
       if( vNovoFundo == 1 && iClose(Symbol(),TimeFrame,1) < iOpen(Symbol(),TimeFrame,1 )  && vUltCandleVerificado != iTime(Symbol(),TimeFrame,1) ){
      
           vNovoFundo = 0;
           ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, slippage, 0, NormalizeDouble(TKCompra(Ask,TakeProfit), Digits), system1_comment, MagicNumber, 0, Green);
           if (ticket > 0) {
          
               if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) {
               
               Print("BUY order opened : ", OrderOpenPrice());
               vUltCandleVerificado = iTime(Symbol(),TimeFrame,1);
               
               }
           } else Print("Error opening BUY order : ", GetLastError());
   
           return (0);
        }
        
         

    }

    //Cruzou p/ cima vende
    if (NormalizeDouble(iClose(Symbol(),TimeFrame,1), Digits) > NormalizeDouble((longEma + vMargem * Point), Digits)) {
    
      //Identificou Novo Topo
      if(NormalizeDouble(iHigh(Symbol(),TimeFrame,1),Digits) >   vFundo  && vNovoFundo == 0 )  {
          vNovoFundo = 1 ;
          vFundo = NormalizeDouble(iHigh(Symbol(),TimeFrame,1),Digits);
       }
      
      // verifica se candle anterior fechou verde (fechamento acima da abertura)
       if( vNovoFundo == 1 &&  iClose(Symbol(),TimeFrame,1) > iOpen(Symbol(),TimeFrame,1) && vUltCandleVerificado != iTime(Symbol(),TimeFrame,1) ){
   
           vNovoFundo = 0;
           ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, slippage, 0,NormalizeDouble(TKVenda(Bid, TakeProfit), Digits), system1_comment, MagicNumber, 0, Red);
           
           if (ticket > 0) {
               if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)){
               vUltCandleVerificado = iTime(Symbol(),TimeFrame,1);
                Print("SELL order opened : ", OrderOpenPrice());
                }
           } else Print("Error opening SELL order : ", GetLastError());
   
           return (0);
        }
        
        
    }

       vQtdOrdensAbertas = 0;
       for (cnt = 0; cnt < total; cnt++) {
        //Sleep(1000);
        OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
        if (OrderType() <= OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) {
            vQtdOrdensAbertas++;
            if (OrderType() == OP_BUY) // long position is opened
            {
                // should it be closed?
                if (iClose(Symbol(),TimeFrame,1) > longEma ) {
               // if(iClose(Symbol(),PERIOD_H4,1) > iOpen(Symbol(),PERIOD_H4,2 )){
                    OrderClose(OrderTicket(), OrderLots(), Bid, 3, Violet);
                    // close position
                    return (0); // exit
                }
                //// check for trailing stop
                if (TrailingStop > 0) {
                    if (Bid - OrderOpenPrice() > Point * TrailingStop) {
                        if (OrderStopLoss() < Bid - Point * TrailingStop) {
                            OrderModify(OrderTicket(), OrderOpenPrice(), Bid-Point * TrailingStop, OrderTakeProfit(), 0, Green);
                            return (0);
                        }
                    }
                }
            } else // go to short position
            {
                // should it be closed?
                if (iClose(Symbol(),TimeFrame,1) < longEma) {
               //if( iClose(Symbol(),PERIOD_H4,1) < iOpen(Symbol(),PERIOD_H4,2)){
                    OrderClose(OrderTicket(), OrderLots(), Ask, 3, Violet);
                    // close position
                    return (0); // exit
                }
                // check for trailing stop
                if (TrailingStop > 0) {
                    if ((OrderOpenPrice() - Ask) > (Point * TrailingStop)) {
                        if ((OrderStopLoss() > (Ask + Point * TrailingStop)) || (OrderStopLoss() == 0)) {
                            OrderModify(OrderTicket(), OrderOpenPrice(), Ask + Point * TrailingStop, OrderTakeProfit(), 0, Red);
                            return (0);
                        }
                    }
                }
            }
            }

           }
        return (0);

    }
    //+------------------------------------------------------------------+
    int Crossed(double line1, double line2) {
        static int last_direction = 0;
        static int current_direction = 0;
        if (line1 > line2) current_direction = 1; //up
        if (line1 < line2) current_direction = 2; //down
        if (current_direction != last_direction) //changed
        {
            last_direction = current_direction;
            return (last_direction);
        } else {
            return (0);
        }
    }
  

double TKVenda(double Ad_0, int Ai_8) {
   if (Ai_8 == 0) return (0.0);
   return (Ad_0 - Ai_8 * Point);
}


double TKCompra(double Ad_0, int Ai_8) {
   if (Ai_8 == 0) return (0.0);
   return (Ad_0 + Ai_8 * Point);
}

double NormalizaLotes(double ad_0) 
{
   if (ad_0 > MarketInfo(Symbol(), MODE_MAXLOT)) ad_0 = MarketInfo(Symbol(), MODE_MAXLOT);
   else
      if (ad_0 < MarketInfo(Symbol(), MODE_MINLOT)) ad_0 = MarketInfo(Symbol(), MODE_MINLOT);
   return (ad_0);
}

//Calcula a quantidade de lotes  conforme o risco
double CalculaQtdLotesRisco(double vRiskPercent) 
{
   bool vTrailingStop = TRUE;
   double minlot_12 = MarketInfo(Symbol(), MODE_MINLOT);
   double maxlot_12 = MarketInfo(Symbol(), MODE_MAXLOT);
   double vMODE_POINT = MarketInfo(Symbol(), MODE_LOTSIZE) / AccountLeverage();
   double ld_28 = vRiskPercent / 100.0 * AccountBalance() / vMODE_POINT;
   double vRetorno = MathFloor(ld_28);
   while (vTrailingStop) 
   {
      vRetorno += minlot_12;
      if (vRetorno > ld_28) 
      {
         vTrailingStop = FALSE;
         vRetorno -= minlot_12;
      }
   }
   if(vRetorno > maxlot_12)  return (maxlot_12);
   else
   return (vRetorno);
}


double SomaOrderProfitDoDia() {
   int day_0 = Day();
   double ld_ret_4 = 0;
   for (int pos_12 = 0; pos_12 < OrdersHistoryTotal(); pos_12++) {
      OrderSelect(pos_12, SELECT_BY_POS, MODE_HISTORY);
      if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
      //if (TimeDay(OrderOpenTime()) == day_0) 
      ld_ret_4 += OrderProfit();
   }
   return (ld_ret_4);
}

int SomaTrades() {
   int count_0 = 0;
   for (int pos_4 = 0; pos_4 < OrdersTotal(); pos_4++) {
      OrderSelect(pos_4, SELECT_BY_POS, MODE_TRADES);
      if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
      count_0++;
   }
   return (count_0);
}



bool TimeFilter(){

 bool _res = false;
   datetime _time_curent = TimeCurrent();
   datetime _time_start = StrToTime(DoubleToStr(Year(),0)+"."+DoubleToStr(Month(),0)+"."+DoubleToStr(Day(),0)+" "+StartHour);
   datetime _time_stop = StrToTime(DoubleToStr(Year(),0)+"."+DoubleToStr(Month(),0)+"."+DoubleToStr(Day(),0)+" "+EndHour);
   if(((Trade_in_Monday==true) && (TimeDayOfWeek(Time[0]) == 1)) ||
   ((Trade_in_Tuesday==true) && (TimeDayOfWeek(Time[0]) == 2)) ||
   ((Trade_in_Wednesday==true) && (TimeDayOfWeek(Time[0]) == 3)) ||
   ((Trade_in_Thursday==true) && (TimeDayOfWeek(Time[0]) == 4)) ||
   ((Trade_in_Friday==true) && (TimeDayOfWeek(Time[0]) == 5)))
   
   
   if(_time_start > _time_stop){
      if(_time_curent >= _time_start || _time_curent <= _time_stop) _res = true;
   }else   
      if(_time_curent >= _time_start && _time_curent <= _time_stop) _res = true;
      
      return(_res); 
  
 }