//+------------------------------------------------------------------+
//|                                           Join the dots-v1.5.mq4 |
//|                                        Copyright © 2008, LEGRUPO |
//|                                           http://www.legrupo.com |
//|                                                     Version: 1.5 |
//| History:                                                         |
//| 1.0 => Release version to the public                             |
//| 1.1 => StopLoss bug fixed                                        |
//| 1.2 => fixes on this releases:                                   |
//|        1) More StopLoss bug fixed;                               |
//|        2) Now the EA close on the next oposite dot               |
//|           Make sure that CloseOrdersOnNextDot is true            |
//|1.2.1 => Stoploss Bug fixed by Saidas                             |
//|1.2.1A=> Added Money Management and UseTripleIndicators filter    |
//|         by Azmel                                                 |
//|1.3   => Added TradeDelay switch. If enabled, it will wait for    |
//|         next candle and only trade if dot does not repaint.      |
//|1.4   => fixes on this release:                                   |
//|         1) Added the feature for long on price above megatrend   |
//|         and sell whe price is bellow megatrande                  |
//|         2) Added the option to filter trades by time             |
//|1.5   => Added limit orders to see if becomes more profitable     |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, LEGRUPO"
#property link      "http://www.legrupo.com"
//+------------------------------------------------------------------+
//| EX4 imports                                                      |
//+------------------------------------------------------------------+
#include <stdlib.mqh>
int MagicNumber = 0;
int ticket = 0;
double Price[2];
int    giSlippage;
extern int    ExpertID             = 994488;
extern int    TakeProfit           = 200;
extern bool   autoChooseProfit = true;
extern double StopLoss             = 50;
extern double LotSize              = 0.1;
extern bool   useTakeProfit        = true;
extern bool   useStopLoss          = true;
extern bool   CloseOrdersOnNextDot = true;
extern bool   UseTripleIndicators  = true;
extern bool   TradeDelay           = true;
extern bool   MoneyManagement      = false;
extern int    PercentageToTrade    = 80;
extern int    AccountType          = 3;
extern int    Leverage             = 100;

extern bool   useTimeFilter        = false;
extern int   startTradeTime       = 07;
extern int   endTradeTime         = 22;

extern int    Slippage             = 5;
color ExitLongColor = CLR_NONE;
color ExitShortColor = CLR_NONE;
extern string BuyComment           = "Join the Dots BUY";
extern string SellComment          = "Join the Dots SELL";

double PricePerPip;
double DecimalCorrection;
double DecimalPlaces;
double TP;
bool   BuySignal;
bool   SellSignal;

bool   CurrentBuyDot;
bool   CurrentSellDot;

bool   PreviousBuyDot;
bool   PreviousSellDot;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   if (useTimeFilter) {
      if (Hour() <= startTradeTime || Hour() >= endTradeTime) {
         return(0);
      }
   }
   
   if (autoChooseProfit == true) {
      if (Symbol() == "EURUSD" || Symbol() == "EURUSDm" ||
      Symbol() == "GBPUSD" || Symbol() == "GBPUSDm" ||
      Symbol() == "USDCHF" || Symbol() == "USDCHFm") {
         TakeProfit = 50;
      } // end TakeProfit 50's
       
      else if (Symbol() == "GBPJPY" || Symbol() == "GBPJPYm") {
         TakeProfit = 200;
      } // end TakeProfit 200's
      
      else if (Symbol() == "USDJPY" || Symbol() == "USDJPYm" ||
      Symbol() == "USDCAD" || Symbol() == "USDCADm") {
         TakeProfit = 100; // end TakeProfit 100's
      }
      else {
            TakeProfit = 75;
      }
   }
//--- by Saidas
   double SL = StopLoss*Point;//by Saidas
   
   //---- MoneyManagement feature by Azmel
   if (AccountType==0)
   {
      PricePerPip       = 10;
      DecimalCorrection = 0.5;
      DecimalPlaces     = 0;
   }
   
   if (AccountType==1)
   { 
      PricePerPip       = 10;
      DecimalCorrection = 0.05;
      DecimalPlaces     = 1;
   }
   
   if (AccountType==2)
   {
      PricePerPip       = 10;
      DecimalCorrection = 0.005;
      DecimalPlaces     = 2;
   }
   
   if (AccountType==3)
   {
      PricePerPip       = 1;
      DecimalCorrection = 0.005;
      DecimalPlaces     = 2;
   }
   
   if (MoneyManagement)
   {
      LotSize=NormalizeDouble(((AccountFreeMargin()*PercentageToTrade*Leverage)/
         (Ask*PricePerPip*1000000))-DecimalCorrection,DecimalPlaces);
   }
   //---- end of MoneyManagement feature.


   MagicNumber = MakeMagicNumber( ExpertID, false );
   double MegaTrend_up     = iCustom(NULL, 0, "Mega trend",144,3,0,0,0);
   double MegaTrend_down   = iCustom(NULL, 0, "Mega trend",144,3,0,1,0);
   double MegaTrend_buffer = iCustom(NULL, 0, "Mega trend",144,3,0,2,0);
   string megatrend_direction, trendhisto_direction, swingzz_direction;
   string price_is = "";
   if (Ask > MegaTrend_buffer) {
      price_is = "above_megatrend";
   }
   if (Bid < MegaTrend_buffer) {
      price_is = "bellow_megatrend";
   }
   Comment("MegaTrend_up: ",MegaTrend_up,"\nMegaTrend_down: ", MegaTrend_down, "\nMegaTrend_buffer: ",MegaTrend_buffer,"\nWhere is price: ",price_is);
   if (MegaTrend_buffer == MegaTrend_up) {
      //Comment("Megatrend up");
      megatrend_direction = "up";
   } else if (MegaTrend_buffer == MegaTrend_down) {
      //Comment("Megatrend down");
      megatrend_direction = "down";
   } else {
      //Comment("No trend from MegaTrend");
      megatrend_direction = "flat";
   }
   
   double TrendHisto_up     = iCustom(NULL, 0, "Trend Histo",1500,1,0);
   double TrendHisto_down   = iCustom(NULL, 0, "Trend Histo",1500,2,0);
   double TrendHisto_buffer = iCustom(NULL, 0, "Trend Histo",1500,0,0);
   
   //Comment("TrendHisto_up: ",TrendHisto_up,"\nTrendHisto_down: ", TrendHisto_down, "\nTrendHisto_buffer: ",TrendHisto_buffer);
   if (TrendHisto_buffer == TrendHisto_up) {
      //Comment("TrendHisto up");
      trendhisto_direction = "up";
   } else if (TrendHisto_buffer == TrendHisto_down) {
      //Comment("TrendHisto down");
      trendhisto_direction = "down";
   } else {
      //Comment("No trend from TrendHisto");
      trendhisto_direction = "flat";
   }
   
   double swingzz_up     = iCustom(NULL, 0, "Swing_ZZ",2,1,0);
   double swingzz_down   = iCustom(NULL, 0, "Swing_ZZ",2,2,0);
   double swingzz_buffer = iCustom(NULL, 0, "Swing_ZZ",2,0,0);
   //Comment("swingzz_up: ",swingzz_up,"\nswingzz_down: ", swingzz_down, "\nswingzz_buffer: ",swingzz_buffer);
   
   //---TradeDelay feature by Azmel.
   //---UseTripleIndicators feature by Azmel.
   if (TradeDelay)
   {
      if (UseTripleIndicators)
      {
         if (swingzz_down != 0 && megatrend_direction == "up" && trendhisto_direction == "up")
         {
            CurrentBuyDot=true;
         }
         else
         {
            CurrentBuyDot=false;
         }

         if (swingzz_up != 0 && megatrend_direction == "down" && trendhisto_direction == "down")
         {
            CurrentSellDot = true;
         }
         else
         {
            CurrentSellDot = false;
         }

         if (PreviousSellDot==true && CurrentSellDot==false)
         {
            SellSignal = true;
         }
         else
         {
            SellSignal = false;
         }

         if (PreviousBuyDot==true && CurrentBuyDot==false)
         {
            BuySignal = true;
         }
         else
         {
            BuySignal = false;
         }

         PreviousSellDot=CurrentSellDot;
         PreviousBuyDot =CurrentBuyDot;
      }
      else
      {
         if (swingzz_down != 0)
         {
            CurrentBuyDot=true;
         }
         else
         {
            CurrentBuyDot=false;
         }

         if (swingzz_up != 0)
         {
            CurrentSellDot = true;
         }
         else
         {
            CurrentSellDot = false;
         }

         if (PreviousSellDot==true && CurrentSellDot==false)
         {
            SellSignal = true;
         }
         else
         {
            SellSignal = false;
         }

         if (PreviousBuyDot==true && CurrentBuyDot==false)
         {
            BuySignal = true;
         }
         else
         {
            BuySignal = false;
         }

         PreviousSellDot=CurrentSellDot;
         PreviousBuyDot =CurrentBuyDot;
      }
   }
   else
   {
      if (UseTripleIndicators)
      {
         if (swingzz_down != 0 && megatrend_direction == "up" && trendhisto_direction == "up")
         {
            BuySignal = true;
         }
         else
         {
            BuySignal = false;
         }
       
         if (swingzz_up != 0 && megatrend_direction == "down" && trendhisto_direction == "down")
         {
            SellSignal = true;
         }
         else
         {
            SellSignal = false;
         }
      }
      else
      {
         if (swingzz_down != 0)
         {
            BuySignal = true;
         }
         else
         {
            BuySignal = false;
         }
      
         if (swingzz_up != 0)
         {
            SellSignal = true;
         }
         else
         {
            SellSignal = false;
         }
      }
   }
   //--- end of UseTripleIndicators feature.
   //--- end of TradeDelay feature.
   double price = 0.0;
   if (BuySignal && price_is == "above_megatrend") {
      CloseShorts(MagicNumber);
      //Alert("BUY");
      if (CountLongs(MagicNumber)== 0 && CountShorts(MagicNumber)== 0) {
         price = Ask-5-SL;
         if (useStopLoss) {
               SL = price-SL;//by Saidas
         } else {
               SL = 0;//by Saidas
         }
         if (useTakeProfit)
         {
            TP = price+TakeProfit*Point;
         }
         else
         {
            TP = 0;
         }
            ticket=OrderSend(Symbol(),OP_BUYLIMIT,LotSize,price,Slippage,SL,TP,BuyComment,MagicNumber,0,CLR_NONE);//by Saidas
         if(ticket<0)
            {
             Alert("OrderSend failed with error #",ErrorDescription(GetLastError()));
             return(0);
            }
      }
   }
   if (SellSignal && price_is == "bellow_megatrend") {
      CloseLongs(MagicNumber);
      //Alert("SELL");
      if (CountLongs(MagicNumber)== 0 && CountShorts(MagicNumber)== 0) {
         price = Bid+5+SL;
         if (useStopLoss) {
               SL = price+SL;//by Saidas
         } else {
               SL = 0;//by Saidas
         }
         if (useTakeProfit)
         {
            TP = price-TakeProfit*Point;
         }
         else
         {
            TP = 0;
         }
            ticket=OrderSend(Symbol(),OP_SELLLIMIT,LotSize,price,Slippage,SL,TP,SellComment,MagicNumber,0,CLR_NONE);//by Saidas
         if(ticket<0)
            {
             Alert("OrderSend failed with error #",ErrorDescription(GetLastError()));
             return(0);
            }
      }
   }
   if (CloseOrdersOnNextDot) {
      if (swingzz_up != 0) {
         CloseLongs(MagicNumber);
      }
      if (swingzz_down != 0) {
         CloseShorts(MagicNumber);
      }
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Make Magic Number                                                |
//+------------------------------------------------------------------+
int MakeMagicNumber( int ExpertID, bool TimeSpecific )
{
   int SymbolCode  = 0;
   int PeriodCode  = 0;
   int MagicNumber = 0; 
   
   //---- Symbol Code
        if( Symbol() == "AUDCAD" || Symbol() == "AUDCADm" ) { SymbolCode = 1000; }
   else if( Symbol() == "AUDJPY" || Symbol() == "AUDJPYm" ) { SymbolCode = 2000; }
   else if( Symbol() == "AUDNZD" || Symbol() == "AUDNZDm" ) { SymbolCode = 3000; }
   else if( Symbol() == "AUDUSD" || Symbol() == "AUDUSDm" ) { SymbolCode = 4000; }
   else if( Symbol() == "CHFJPY" || Symbol() == "CHFJPYm" ) { SymbolCode = 5000; }
   else if( Symbol() == "EURAUD" || Symbol() == "EURAUDm" ) { SymbolCode = 6000; }
   else if( Symbol() == "EURCAD" || Symbol() == "EURCADm" ) { SymbolCode = 7000; }
   else if( Symbol() == "EURCHF" || Symbol() == "EURCHFm" ) { SymbolCode = 8000; }
   else if( Symbol() == "EURGBP" || Symbol() == "EURGBPm" ) { SymbolCode = 9000; }
   else if( Symbol() == "EURJPY" || Symbol() == "EURJPYm" ) { SymbolCode = 1000; }
   else if( Symbol() == "EURUSD" || Symbol() == "EURUSDm" ) { SymbolCode = 1100; }
   else if( Symbol() == "GBPCHF" || Symbol() == "GBPCHFm" ) { SymbolCode = 1200; }
   else if( Symbol() == "GBPJPY" || Symbol() == "GBPJPYm" ) { SymbolCode = 1300; }
   else if( Symbol() == "GBPUSD" || Symbol() == "GBPUSDm" ) { SymbolCode = 1400; }
   else if( Symbol() == "NZDJPY" || Symbol() == "NZDJPYm" ) { SymbolCode = 1500; }
   else if( Symbol() == "NZDUSD" || Symbol() == "NZDUSDm" ) { SymbolCode = 1600; }
   else if( Symbol() == "USDCAD" || Symbol() == "USDCADm" ) { SymbolCode = 1700; }
   else if( Symbol() == "USDCHF" || Symbol() == "USDCHFm" ) { SymbolCode = 1800; }
   else if( Symbol() == "USDJPY" || Symbol() == "USDJPYm" ) { SymbolCode = 1900; }
                     
   
   //---- Period Code
   if( TimeSpecific )
   {
              if( Period() == 1 )    { PeriodCode = 10; }
         else if( Period() == 5 )    { PeriodCode = 20; }
         else if( Period() == 15 )   { PeriodCode = 30; }
         else if( Period() == 30 )   { PeriodCode = 40; }
         else if( Period() == 60 )   { PeriodCode = 50; }
         else if( Period() == 240 )  { PeriodCode = 60; }
         else if( Period() == 1440 ) { PeriodCode = 70; }
         else if( Period() == 10080 ){ PeriodCode = 80; }
   }
   else
   {
      PeriodCode = 0;
   }
   //---- Calculate MagicNumber
   MagicNumber = ExpertID+SymbolCode+PeriodCode;
   return(MagicNumber);
}
//+------------------------------------------------------------------+
//| Calculate concurrent Long position                               |
//+------------------------------------------------------------------+
int CountLongs(int MagicNumber)
{
 int count=0;
 int trade;
 int trades=OrdersTotal();
 for(trade=0;trade<trades;trade++)
 {
  OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
  
  if( OrderSymbol()!=Symbol() || OrderMagicNumber() != MagicNumber )
   continue;
   
  if(OrderType()==OP_BUY || OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP)
   count++;
 }//for
 return(count);
}
//+------------------------------------------------------------------+
//| Calculate concurrent short position                              |
//+------------------------------------------------------------------+
int CountShorts(int MagicNumber)
{
 int count=0;
 int trade;
 int trades=OrdersTotal();
 for(trade=0;trade<trades;trade++)
 {
  OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
  
  if(OrderSymbol()!=Symbol() || OrderMagicNumber() != MagicNumber )
   continue;
   
  if(OrderType()==OP_SELL || OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP)
  count++;
 }//for
 return(count);
}
//+------------------------------------------------------------------+
//| Close Long Position                                              |
//+------------------------------------------------------------------+
void CloseLongs(int MagicNumber)
{
 int i = OrdersTotal();
 
 while( CountLongs(MagicNumber) != 0 && i >= 0 )
 {  
   OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
   
   if( OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber )
   {
     i--;
     continue;
   }
   else if(OrderType()==OP_BUY || OrderType()== OP_BUYLIMIT)
   {
     OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,ExitLongColor);
     OrderDelete(OrderTicket());
     i--;
   }
 }
}
//+------------------------------------------------------------------+
//| Close Short Position                                             |
//+------------------------------------------------------------------+
void CloseShorts(int MagicNumber)
{
 int i = OrdersTotal();
 
 while( CountShorts(MagicNumber) != 0 && i >= 0 )
 {  
   OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
   
   if( OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber)
   {
     i--;
     continue;
   }
   else if(OrderType()== OP_SELL || OrderType()==OP_SELLLIMIT )
  {
   OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,ExitShortColor);
   OrderDelete(OrderTicket());
  }
 }
}