//+------------------------------------------------------------------+
//|                                               The Holy Grail.mq4 |
//|              Copyright © 2009, Mark Johnson. All rights reserved |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+

#property show_inputs

//+------------------------------------------------------------------+
//| expert External variables                                        |
//+------------------------------------------------------------------+

extern int    Magic  = 1801;
extern string Key    = "mK0lK8Ai3rRmRDd";
extern int    Rsi    = 3;

//+------------------------------------------------------------------+
//| expert Internal variables                                        |
//+------------------------------------------------------------------+

string Pairs[] = {"AUDCAD","AUDCHF","AUDJPY","AUDNZD","AUDUSD",
                  "CADCHF","CADJPY","CHFJPY","EURAUD","EURCAD",
                  "EURCHF","EURGBP","EURJPY","EURNZD","EURUSD",
                  "GBPAUD","GBPCAD","GBPCHF","GBPJPY","GBPUSD",
                  "NZDCAD","NZDCHF","NZDJPY","NZDUSD","SGDJPY",
                  "USDCAD","USDCHF","USDDKK","USDHKD","USDNOK",
                  "USDSEK","USDSGD","USDJPY","XAGUSD","XAUUSD"};

string Author  = "Copyright © 2009, Mark Johnson. All rights reserved.";
string Suffix;
int    Step;
int    M01, M05, M15, H01, H04, D01;

//+------------------------------------------------------------------+
//| expert Initialization function                                   |
//+------------------------------------------------------------------+

int init()
  {

    Suffix = StringSubstr(Symbol(),6,StringLen(Symbol())-6);

    for(int a = 0; a < ArraySize(Pairs); a++)
      {
        Pairs[a] = Pairs[a] + Suffix;
      }
      
    if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.01) Step = 2;
    if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.10) Step = 1;
    if(MarketInfo(Symbol(),MODE_LOTSTEP) == 1.00) Step = 0;

    M01 = PERIOD_M1;
    M05 = PERIOD_M5;
    M15 = PERIOD_M15;
    H01 = PERIOD_H1;
    H04 = PERIOD_H4;
    D01 = PERIOD_D1;

    Comment("\nWaiting for tick update...");

    return(0);
    
  }
  
//+------------------------------------------------------------------+
//| expert Deinitialization function                                 |
//+------------------------------------------------------------------+

int deinit()
  {

    Comment("");
    
    return(0);

  }
  
//+------------------------------------------------------------------+
//| expert Start function                                            |
//+------------------------------------------------------------------+

int start()
  {
    
    double Lots = NormalizeDouble(AccountBalance()/50000,Step);
    double Min  = MarketInfo(Symbol(),MODE_MINLOT);
    double Max  = MarketInfo(Symbol(),MODE_MAXLOT);

    if(Lots < Min) Lots = Min;
    if(Lots > Max) Lots = Max;
    
    Comment("\n",Author,"\n\n","Lots = ",DoubleToStr(Lots,2));

    if(TimeDayOfWeek(TimeLocal()) == 5 && TimeHour(TimeLocal()) >= 11)
      {
        return(0);
      }

    for(int b = 0; b < ArraySize(Pairs); b++)
      {

        if(OrdersTotal() == 5)
          {
            break;
          }
        
        double EMA_020 = iMA(Pairs[b],H04,020,0,MODE_EMA,PRICE_CLOSE,0);
        double EMA_200 = iMA(Pairs[b],H04,200,0,MODE_EMA,PRICE_CLOSE,0);
        
        double RSI_H04 = iRSI(Pairs[b],H04,Rsi,PRICE_CLOSE,0);
        double RSI_H01 = iRSI(Pairs[b],H01,Rsi,PRICE_CLOSE,0);
        double RSI_M15 = iRSI(Pairs[b],M15,Rsi,PRICE_CLOSE,0);
        double RSI_M05 = iRSI(Pairs[b],M05,Rsi,PRICE_CLOSE,0);
        
        if(EMA_020 > EMA_200 && RSI_M05 > 20 && RSI_M15 < 20 && RSI_H01 < 20 && RSI_H04 < 20)
          {
            if(TradeExist(Pairs[b]) == false && NewsExist(Pairs[b]) == false)
              {
                if(IsTradeAllowed() == true) SendOrder(Pairs[b],OP_BUY,Lots);
              }
          }
          
        if(EMA_020 < EMA_200 && RSI_M05 < 80 && RSI_M15 > 80 && RSI_H01 > 80 && RSI_H04 > 80)
          {
            if(TradeExist(Pairs[b]) == false && NewsExist(Pairs[b]) == false)
              {
                if(IsTradeAllowed() == true) SendOrder(Pairs[b],OP_SELL,Lots);
              }
          }

      }
      
    return(0);

  }

//+------------------------------------------------------------------+
//| expert TradeExists function                                      |
//+------------------------------------------------------------------+

bool TradeExist(string symbol)
  {

    bool Found = false;

    for(int c = 0; c <= OrdersTotal(); c++)
      {
        if(OrderSelect(c,SELECT_BY_POS,MODE_TRADES) == true)
          {
            if(OrderSymbol() == symbol && OrderMagicNumber() == Magic)
              {
                Found = true;
              }
          }
      }

    return(Found);

  }

//+------------------------------------------------------------------+
//| expert SendOrder function                                        |
//+------------------------------------------------------------------+  

void SendOrder(string symbol, int dir, double lots)
  {
    
    double price;
    double point;
    double sl;
    double tp;

    int ticket = -1;
    int spread = 10;
    int digit  = 0;
    int take   = 25;
    int stop   = 100;
        
    if(Digits == 3 || Digits == 5)
      {
        spread *= 10;
        take   *= 10;
        stop   *= 10;
      }
    
    if(dir == OP_BUY && iClose(symbol,0,0) > 0 && MarketInfo(symbol,MODE_SPREAD) <= spread)
      {
        while(ticket < 0)
          {
            RefreshRates();
            price  = MarketInfo(symbol,MODE_ASK);
            point  = MarketInfo(symbol,MODE_POINT);
            digit  = MarketInfo(symbol,MODE_DIGITS);
            sl     = NormalizeDouble(price-stop*point,digit);
            tp     = NormalizeDouble(price+take*point,digit);
            ticket = OrderSend(symbol,dir,lots,price,3,sl,tp,Key,Magic,0,CLR_NONE);
            Sleep(10);
          }
      }
      
    if(dir == OP_SELL && iClose(symbol,0,0) > 0 && MarketInfo(symbol,MODE_SPREAD) <= spread)
      {
        while(ticket < 0)
          {
            RefreshRates();
            price  = MarketInfo(symbol,MODE_BID);
            point  = MarketInfo(symbol,MODE_POINT);
            digit  = MarketInfo(symbol,MODE_DIGITS);
            sl     = NormalizeDouble(price+stop*point,digit);
            tp     = NormalizeDouble(price-take*point,digit);
            ticket = OrderSend(symbol,dir,lots,price,3,sl,tp,Key,Magic,0,CLR_NONE);
            Sleep(10);
          }
      }
  
  }
  
//+------------------------------------------------------------------+
//| expert News function                                             |
//+------------------------------------------------------------------+  

bool NewsExist(string symbol)
  {
  
    string NewsPairs[5];
    int    MinutesSincePrevEvent;
    int    MinutesUntilNextEvent;
    bool   News;

    NewsPairs[0] = "EURUSD" + Suffix;
    NewsPairs[1] = "USDJPY" + Suffix;
    NewsPairs[2] = "GBPUSD" + Suffix;
    NewsPairs[3] = "USDCHF" + Suffix;
    NewsPairs[4] = symbol;
    
    for(int d = 0; d < ArraySize(NewsPairs); d++)
      {
        MinutesSincePrevEvent =
          iCustom(NULL, 0, "Economic News", NewsPairs[d], true, false, false, true, true, 1, 0);

        MinutesUntilNextEvent =
          iCustom(NULL, 0, "Economic News", NewsPairs[d], true, false, false, true, true, 1, 1);

        if((MinutesUntilNextEvent <= 60) || 
           (MinutesSincePrevEvent <= 15))
          {
            News = true;
          }
      }
      
    return(News);

  }
   