//+------------------------------------------------------------------+
//| 4macd.mq4 |
//| Copyright 2015, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- input parameters
input double aLot=0.01; // Lot size
input int stopLoss=100; // Maximum pips for a stoploss
input int candleNr=10; // Bars to look back for stoploss level
input int takeProfit=40; // Plus pips when to move to BE
input double multiplier=2; // Reward to Risk ratio (?:1)
input int pipTolerance=25; // Pips to add to SL for safety
input int pipTolerance_89=5; // Min amount of pips from MA89
input int pipTolerance_21=5; // Min pips between MA8 and MA21
input int pipTolerance_8=25; // Max pips away from MA8
input int MACD_bar=10; // MACD bars to analyze (min=4)
input int magicNr=123; // Magic number
//--- emmas
double ma_365;
double ma_200;
double ma_89;
double ma_21;
double ma_8;
//--- mcdonalds
int MACD_bars=0;
double macd_main[];
double macd_signal[];
//--- gaps
double gap=0;
double gap_89=0;
double gap_21=0;
double gap_8=0;
//--- misc
int candles=0;
int objects=0;
double pipsis=0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(Point==0.00001 || Point==0.001)
      pipsis=Point*10;
   else pipsis=Point;

   gap=pipsis*pipTolerance;
   gap_89=pipsis*pipTolerance_89;
   gap_21=pipsis*pipTolerance_21;
   gap_8=pipsis*pipTolerance_8;

   if(MACD_bar<4)
      MACD_bars=4;
   else MACD_bars=MACD_bar;

   ArrayResize(macd_main,MACD_bars);
   ArrayResize(macd_signal,MACD_bars);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(new_candle())
     {
      Emmas();
      Mcds();
      trend_cont();
     }
   break_even();
  }
//+------------------------------------------------------------------+
//| get MA data |
//+------------------------------------------------------------------+
void Emmas()
  {
   ma_365=iMA(NULL,0,365,0,MODE_EMA,PRICE_CLOSE,0);
   ma_200=iMA(NULL,0,200,0,MODE_SMA,PRICE_CLOSE,0);
   ma_89=iMA(NULL,0,89,0,MODE_SMA,PRICE_CLOSE,0);
   ma_21=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE,0);
   ma_8=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
  }
//+------------------------------------------------------------------+
//| get MACD data |
//+------------------------------------------------------------------+
void Mcds()
  {
   for(int j=0; j<MACD_bars; j++)
     {
      macd_main[j]=iMACD(NULL,0,5,13,1,PRICE_CLOSE,MODE_MAIN,j);
      macd_signal[j]=iMACD(NULL,0,5,13,1,PRICE_CLOSE,MODE_SIGNAL,j);
     }
  }
//+------------------------------------------------------------------+
//| wait for new candle to born |
//+------------------------------------------------------------------+
bool new_candle()
  {
   if(Bars!=candles)
     {
      candles=Bars;
      return(1);
     }
   else return(0);
  }
//+------------------------------------------------------------------+
//| not being used |
//+------------------------------------------------------------------+
bool lower_high()
  {
   if(macd_signal[1]>pipsis*45)
      return(1);
   else return(0);
  }
//+------------------------------------------------------------------+
//| not being used |
//+------------------------------------------------------------------+
bool higher_low()
  {
   if(macd_signal[1]<-pipsis*45)
      return(1);
   else return(0);
  }
//+------------------------------------------------------------------+
//| Trend continuation pattern |
//+------------------------------------------------------------------+
void trend_cont()
  {
   if(Ask>ma_89+gap_89)
      if(Ask<ma_8+gap_8 && Ask>ma_21)
         if(ma_8-ma_21>gap_21)
            if(macd_signal[1]>0 && macd_signal[1]<pipsis*30)
               if(macd_main[3]>macd_main[2] && macd_main[2]<macd_main[1])
                 {
                  objects++;
                  ObjectCreate(ChartID(),IntegerToString(objects),OBJ_ARROW,0,TimeCurrent(),Ask);
                  ObjectSet(IntegerToString(objects),OBJPROP_COLOR,clrBlue);
                  Print("BUY");
                  open_buy();
                 }
   if(Bid<ma_89-gap_89)
      if(Bid<ma_21 && Bid>ma_8-gap_8)
         if(ma_21-ma_8>gap_21)
            if(macd_signal[1]<0 && macd_signal[1]>-pipsis*30)
               if(macd_main[3]<macd_main[2] && macd_main[2]>macd_main[1])
                 {
                  objects++;
                  ObjectCreate(ChartID(),IntegerToString(objects),OBJ_ARROW,0,TimeCurrent(),Bid);
                  ObjectSet(IntegerToString(objects),OBJPROP_COLOR,clrRed);
                  Print("SELL");
                  open_sell();
                 }
  }
//+------------------------------------------------------------------+
//| BUY position |
//+------------------------------------------------------------------+
void open_buy()
  {
   double buy_sl=iLow(NULL,0,iLowest(NULL,0,MODE_LOW,candleNr,1))-gap;
   double buy_tp=(Ask-buy_sl)*multiplier;
   Comment(buy_sl);
   if(buy_sl>Ask-stopLoss*pipsis)
     {
      if(OrderSend(Symbol(),OP_BUY,aLot,Ask,5,buy_sl,Ask+buy_tp,"buy "+IntegerToString(objects),magicNr,0,clrNONE)!=-1)
         Comment("TRUE buy "+IntegerToString(objects));
      else Comment(GetLastError());
     }
  }
//+------------------------------------------------------------------+
//| SELL position |
//+------------------------------------------------------------------+
void open_sell()
  {
   double sell_sl=iHigh(NULL,0,iHighest(NULL,0,MODE_HIGH,candleNr,1))+gap;
   double sell_tp=(sell_sl-Bid)*multiplier;
   if(sell_sl<Bid+stopLoss*pipsis)
     {
      if(OrderSend(Symbol(),OP_SELL,aLot,Bid,5,sell_sl,Bid-sell_tp,"sell "+IntegerToString(objects),magicNr,0,clrNONE)!=-1)
         Comment("TRUE sell "+IntegerToString(objects));
      else Comment(GetLastError());
     }
  }
//+------------------------------------------------------------------+
//| Move to BE |
//+------------------------------------------------------------------+
void break_even()
  {
   if(OrdersTotal()!=0)
      for(int i=0;i<OrdersTotal();i++)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
            if(OrderOpenPrice()-OrderStopLoss()>pipsis || OrderStopLoss()-OrderOpenPrice()>pipsis)
               if(OrderProfit()>aLot*takeProfit*10)
                  if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,clrNONE))
                     Print(GetLastError());
        }
  }
//+------------------------------------------------------------------+
