//+------------------------------------------------------------------+
#define SIGNAL_NONE 0
#define SIGNAL_BUY   1
#define SIGNAL_SELL  2

#property copyright "Jim Richards"

//Define external variables

extern string Remark1              = "== Main Settings ==";
extern int    MagicNumber          = 0;
bool          SignalsOnly          = False;
bool          Alerts               = False;
bool          SignalMail           = False;
bool          PlaySounds           = False;
extern bool   ECNBroker            = False;
bool          EachTickMode         = True;
extern double Lots                 = 0.01;
extern double Stoplossmargin       = 0.0001;
extern double takeprofitmultiplier = 3.0;

bool          MoneyManagement      = False;
int           Risk                 = 0;
extern int    Slippage             = 3;
bool  UseStopLoss          = False;
int    StopLoss             = 100;
bool   UseTakeProfit        = False;
int    TakeProfit           = 60;

extern string Remark2              = "== Fast MA Settings ==";

extern int    MA1Period            = 20;
int           MA1Shift             = 0;
int           MA1Method            = 1;
int           MA1Price             = 0;

extern string Remark3              = "== Slow MA Settings ==";

extern int    MA2Period            = 60;
int           MA2Shift             = 0;
int           MA2Method            = 1;
int           MA2Price             = 0;

extern string Remark4              = "== Trend MA Settings ==";

extern int    MATrendperiod        = 70;
int           MATrendshift         = 0;
int           MATrendmethod        = 0;
int           MATrendprice         = 0;

extern double minimumgapdistance   = 0.00030;
extern double minimumgapdistance2  = 0.00010;

string        SymbolUsed;
int           TickCount            = 0;
int           RecordDay            = -1;
string        UserName             = "";
bool          ShowDiagnostics      = False;

int           TradeBar;
int           TradesThisBar;

int           OpenBarCount;
int           CloseBarCount;

string        BrokerType           = "4-Digit Broker";
double        BrokerMultiplier     = 1;
double        lotmultiplier        = 10000;
int           Current;
bool          TickCheck            = False;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init() {
   OpenBarCount = Bars;
   CloseBarCount = Bars;
   
   TickCount = 0;
   
   SymbolUsed = StringSubstr(Symbol(), 0, 6);   
   RecordDay = TimeDayOfYear(TimeCurrent());
   
   if(!IsDllsAllowed())
      {
      Alert("ERROR: Please enable DLL calls.");
      Comment("Enable DLL Calls");
      return(0);
      }  

   
   if(Digits == 3 || Digits == 5)
      {
      BrokerType = "5-Digit Broker";
      BrokerMultiplier = 10;
      }


   if (EachTickMode) Current = 0; else Current = 1;

   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit() {

   return(0);
}
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start() 

//This section defines the variables//
{
   int Order                     = SIGNAL_NONE;
   int Total;
   int Ticket;
   
   double StopLossLevel; 
   double TakeProfitLevel;
   double highstoplosslevel;
   double lowstoplosslevel;
   double highestma;
   double lowestma;
   double highestma2;
   double lowestma2;
   double highcandlethree        = High[3];
   double highcandletwo          = High[2];
   double highcandleone          = High[1];
   double lowcandlethree         = Low[3];
   double lowcandletwo           = Low[2];
   double lowcandleone           = Low[1];
   double closecandleone         = Close[1];
   double lowcurrentcandle       = Low[0];
   double highcurrentcandle      = High[0];
   /*double Lots                   = AccountBalance()/lotmultiplier;*/
    
   double MA1Current             = iMA(NULL, 0, MA1Period, MA1Shift, MA1Method, MA1Price, Current + 1);
   double MA2Current             = iMA(NULL, 0, MA2Period, MA2Shift, MA2Method, MA2Price, Current + 1);
   double MA2Previous            = iMA(NULL, 0, MA2Period, MA2Shift, MA2Method, MA2Price, Current + 2);
   double MATrend                = iMA(NULL, 0, MATrendperiod, MATrendshift, MATrendmethod, MATrendprice,Current + 1);

   bool   towersdown             = false;
   bool   towersup               = false;
   bool   towersdowntouchmaone   = false;
   bool   towersdowntouchmatwo   = false;
   bool   towersuptouchmaone     = false;
   bool   towersuptouchmatwo     = false;
   bool   trendlong              = false;
   bool   trendshort             = false;
   bool   triggerlongtrade       = false;
   bool   triggershorttrade      = false;
   bool   isma2higherthanmatrend = false;
   bool   isma2lowerthanmatrend  = false;
   bool   MA2slopingdown         = false;
   bool   MA2slopingup           = false;
   bool   decentgapbetween       = false;
   bool   decentgapbetween2      = false;
   
   string TradeTrigger = "None";

   if (EachTickMode && Bars != CloseBarCount) TickCheck = False;
   Total = OrdersTotal();
   Order = SIGNAL_NONE;

//This section of code limits the trades per bar

   if(TradeBar != Bars)
   {
   TradeBar = Bars;
   TradesThisBar = 0;
   }


//This section of code is the money management sequence

   if (MoneyManagement)
   {
      if (Risk<1 || Risk>100)
      {
         Comment("Invalid Risk Value.");
         return(0);
      }
      else
      {
         Lots=MathFloor((AccountFreeMargin()*AccountLeverage()*Risk*Point*BrokerMultiplier*100)/(Ask*MarketInfo(Symbol(),MODE_LOTSIZE)*MarketInfo(Symbol(),MODE_MINLOT)))*MarketInfo(Symbol(),MODE_MINLOT);
      }
   }

//This section defines the logic and the logical conditions that must be met in order to take a trade//

if(lowcandletwo < lowcandleone)   lowstoplosslevel  = lowcandletwo;
if(highcandletwo > highcandleone) highstoplosslevel = highcandletwo;
if(lowcandletwo > lowcandleone)   lowstoplosslevel  = lowcandleone;
if(highcandletwo < highcandleone) highstoplosslevel = highcandleone;
if(lowcurrentcandle < lowcandleone) lowstoplosslevel = lowcurrentcandle;
if(highcurrentcandle > highcandleone) highstoplosslevel = highcurrentcandle;

if(MA2Current > MA1Current) highestma   = MA2Current;
if(MA2Current > MA1Current) lowestma    = MA1Current;
if(MA2Current < MA1Current) lowestma    = MA2Current;
if(MA2Current < MA1Current) highestma   = MA1Current;
if(MA2Current > MATrend)    highestma2  = MA2Current;
if(MA2Current > MATrend)    lowestma2   = MATrend;
if(MA2Current < MATrend)    lowestma2   = MA2Current;
if(MA2Current < MATrend)    highestma2  = MATrend;

double gap    = highestma - lowestma;
double gap2   = highestma2 - lowestma2;  

if (MA2Previous > MA2Current)                                        MA2slopingdown         = true;
if (MA2Previous < MA2Current)                                        MA2slopingup           = true;
if (gap > minimumgapdistance)                                        decentgapbetween       = true;
if (gap2 > minimumgapdistance2)                                      decentgapbetween2      = true;
if(highcandlethree > highcandletwo && highcandletwo > highcandleone) towersdown             = true;
if(lowcandlethree < lowcandletwo && lowcandletwo < lowcandleone)     towersup               = true;
if(lowcandleone < MA1Current)                                        towersdowntouchmaone   = true;
if(lowcandleone > MA2Current || closecandleone > MA2Current)         towersdowntouchmatwo   = true;
if(highcandleone > MA1Current)                                       towersuptouchmaone     = true;
if(highcandleone < MA2Current || closecandleone < MA2Current)        towersuptouchmatwo     = true;
if(closecandleone > MATrend)                                         trendlong              = true;
if(closecandleone < MATrend)                                         trendshort             = true;
if(Bid > highcandleone)                                              triggerlongtrade       = true;
if(Ask < lowcandleone)                                               triggershorttrade      = true;
if(MA2Current > MATrend)                                             isma2higherthanmatrend = true;
if(MA2Current < MATrend)                                             isma2lowerthanmatrend  = true;



if(
   trendlong && 
   isma2higherthanmatrend && 
   towersdown && 
   towersdowntouchmaone && 
   towersdowntouchmatwo && 
   triggerlongtrade && 
   MA2slopingup && 
   decentgapbetween && 
   decentgapbetween2
   )
   
   TradeTrigger = "Open Long"; 
   
   
if(
   trendshort && 
   isma2lowerthanmatrend && 
   towersup && 
   towersuptouchmaone && 
   towersuptouchmatwo && 
   triggershorttrade && 
   MA2slopingdown && 
   decentgapbetween && 
   decentgapbetween2
   ) 
   
   TradeTrigger = "Open Short";



   //This section checks for open trades
   bool IsTrade = False;

   for (int i = 0; i < Total; i ++) {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderType() <= OP_SELL &&  OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) 
         IsTrade = True;
        }
            
            
//This section defines the type of trade to be taken

if(TradeTrigger == "Open Long") Order = SIGNAL_BUY;
if(TradeTrigger == "Open Short") Order = SIGNAL_SELL;



   //Buy order
   if (Order == SIGNAL_BUY && ((EachTickMode && !TickCheck) || (!EachTickMode && (Bars != OpenBarCount)))) {
      if(SignalsOnly) {
         if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "Buy Signal");
         if (Alerts) Alert("[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "Buy Signal");
         if (PlaySounds) PlaySound("alert.wav");
     
      }
      
      if(!IsTrade && !SignalsOnly && TradesThisBar < 1) {
         //Check free margin
         if (AccountFreeMarginCheck(Symbol(), OP_BUY, Lots) < 0) {
            Print("We have no money. Free Margin = ", AccountFreeMargin());
            return(0);
         }

         if (UseStopLoss) StopLossLevel = Ask - StopLoss * Point; else StopLossLevel = lowstoplosslevel - Stoplossmargin;
         if (UseTakeProfit) TakeProfitLevel = Ask + TakeProfit * Point; else TakeProfitLevel = Ask + ((Ask - StopLossLevel)*takeprofitmultiplier);
         if(ECNBroker) Ticket = OrderModify(OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0, "Buy(#" + MagicNumber + ")", MagicNumber, 0, DodgerBlue), OrderOpenPrice(), StopLossLevel, TakeProfitLevel, 0, CLR_NONE);
         if(!ECNBroker) Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, StopLossLevel, TakeProfitLevel, "Buy(#" + MagicNumber + ")", MagicNumber, 0, DodgerBlue);
            if(Ticket > 0) {
               if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {
				  Print("BUY order opened : ", OrderOpenPrice());
                  if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "Buy Signal");
			         if (Alerts) Alert("[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "Buy Signal");
                  if (PlaySounds) PlaySound("alert.wav");
                  TradesThisBar++;
			   } else {
   				Print("Error opening BUY order : ", GetLastError());
			   }
            }
            
         if (EachTickMode) TickCheck = True;
         if (!EachTickMode) OpenBarCount = Bars;
         return(0);
      }
   }

   //Sell order
   if (Order == SIGNAL_SELL && ((EachTickMode && !TickCheck) || (!EachTickMode && (Bars != OpenBarCount)))) {
      if(SignalsOnly) {
          if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "Sell Signal");
          if (Alerts) Alert("[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "Sell Signal");
          if (PlaySounds) PlaySound("alert.wav");
         }
      if(!IsTrade && !SignalsOnly && TradesThisBar < 1) {
         //Check free margin
         if (AccountFreeMarginCheck(Symbol(), OP_SELL, Lots) < 0) {
            Print("We have no money. Free Margin = ", AccountFreeMargin());
            return(0);
         }

         if (UseStopLoss) StopLossLevel = Bid + StopLoss * Point; else StopLossLevel = highstoplosslevel + Stoplossmargin;
         if (UseTakeProfit) TakeProfitLevel = Bid - TakeProfit * Point; else TakeProfitLevel = Bid - ((StopLossLevel - Bid)* takeprofitmultiplier) ;

         if(ECNBroker) Ticket = OrderModify(OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, 0, "Sell(#" + MagicNumber + ")", MagicNumber, 0, DeepPink), OrderOpenPrice(), StopLossLevel, TakeProfitLevel, 0, CLR_NONE);
         if(!ECNBroker) Ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, StopLossLevel, TakeProfitLevel, "Sell(#" + MagicNumber + ")", MagicNumber, 0, DeepPink);
         if(Ticket > 0) {
            if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {
				Print("SELL order opened : ", OrderOpenPrice());
                if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "Sell Signal");
			       if (Alerts) Alert("[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "Sell Signal");
                if (PlaySounds) PlaySound("alert.wav");
                TradesThisBar++;
			} else {
				Print("Error opening SELL order : ", GetLastError());
			}
         }
         if (EachTickMode) TickCheck = True;
         if (!EachTickMode) OpenBarCount = Bars;
         return(0);
      }
   }

   if (!EachTickMode) CloseBarCount = Bars;
   
   return(0);
}

//END