//+--------+
//|FollowMe|
//+--------+
#property copyright "Ron Thompson"
#property link      "http://www.ForexMT4.com/"

// This EA is NEVER to be SOLD individually
// This EA is NEVER to be INCLUDED as part of a collection that is SOLD


// user input
extern int    IPeriod             =      55    ;
extern double Lots                =       0.01 ;
extern int    TotalOrders         =       1    ;
extern double ProfitMade          =       0.0  ;
extern double LossLimit           =       0.0  ;
extern double BasketProfit        =       0.0  ;

// Trade control
int    Slippage=2;                           // how many pips of slippage can you tolorate
int    maxloop=25;                           // maximum number of attempts to handle errors
int    LL2SL=10;                             // LossLimit to StopLoss server spread
int    MagicNumber  = 354656;                // allows multiple experts to trade on same account
string TradeComment = "_follow05.txt";       // where to log information

// Bar handling
datetime bartime=0;                          // used to determine when a bar has moved

//objects
int i;

//info
string   cmt;


// used for verbose error logging
#include <stdlib.mqh>

// EA specific
string   sDir;
int      currdir;
int      prevdir;
bool     WaitForNextTrend=true;


//+-------------+
//| Custom init |
//|-------------+
// Called ONCE when EA is added to chart or recompiled

int init()
  {
   if( IsTesting() ) LL2SL=50;
   
   // current bar is current bar
   // prevents trade when placing EA on chart
   bartime=Time[0];

   Comment(" ");
  }

//+----------------+
//| Custom DE-init |
//+----------------+
// Called ONCE when EA is removed from chart

int deinit()
 {
  Comment(" ");
 }


//+-----------+
//| Main      |
//+-----------+
// Called EACH TICK and each Bar[]

int start()
  {

   // EA specific
   double ma0, ma1;

   int      cnt=0;
   int      gle=0;
   int      ticket=0;
   int      OrdersPerSymbol=0;

   // stoploss and takeprofit and close control
   double SL=0;
   double TP=0;

   double CurrentProfit=0;

   // order management
   string oTK;
   string oSL;
   string oTP;
   string oPM;
   string oLL;
   string oER;

   
   // limit the orders 
   if(TotalOrders>0 && OrdersTotal()>=TotalOrders) WaitForNextTrend=true;
   
   
   // bar open, so do all the calcs
   if(bartime!=Time[0])
     {
      bartime=Time[0];
      
   //+---------------------------------+
   //| Insert your MA or iCustom here  |
   //+---------------------------------+

      ma1=iMA(Symbol(),0,IPeriod,0,MODE_EMA,MODE_OPEN,1);
      ma0=iMA(Symbol(),0,IPeriod,0,MODE_EMA,MODE_OPEN,0);

   //+-------------+
   //| END Insert  |
   //+-------------+

      sDir=" Sideways";

      //check for Rising including slope
      if(ma0>ma1)
       {
        currdir=2;
        sDir="Rising";

        // has the direction changed
        if(currdir!=prevdir)
          {
           prevdir=currdir;
           CloseEverything();
           WaitForNextTrend=false;
           sDir="Rising was Falling";
          }

        if(!WaitForNextTrend) OpenBuy("BUY",    Lots);

       }//rising
       


      //check for Falling including slope
      if(ma0<ma1)
       {
        currdir=1;
        sDir="Falling";

        // has the direction changed
        if(currdir!=prevdir)
          {
           prevdir=currdir;
           CloseEverything();
           WaitForNextTrend=false;
           sDir="Falling was Rising";
          }

        if(!WaitForNextTrend) OpenSell("SELL",    Lots);
       
       }//falling


     cmt="MA[0]="+ma0+" MA[1]="+ma1+" DIFF="+(ma0-ma1)+" DIRECTION="+sDir;
     Comment(cmt);

    }//bartime



  //Basket profit

  double CurrentBasket=0;
  for(cnt=OrdersTotal();cnt>=0;cnt--)
    {
     OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
     if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber )
       {
        CurrentBasket=CurrentBasket+OrderProfit();
       }
    }
  Comment(cmt+" Profit="+CurrentBasket);

  if( BasketProfit>0  && CurrentBasket>=BasketProfit)
    {
     CloseEverything();
     WaitForNextTrend=true;
    }



  //
  // Order Management
  //
  for(cnt=OrdersTotal();cnt>=0;cnt--)
    {
     OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
     if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber )
       {

        if(OrderType()==OP_BUY)
          {
           CurrentProfit=(Bid-OrderOpenPrice()) ;

           // Did we make a profit
           //======================
           if(ProfitMade>0 && CurrentProfit>=(ProfitMade*Point))
             {
              oTK=" Ticket="+OrderTicket();
              oSL=" SL="+OrderStopLoss();
              oTP=" TP="+OrderTakeProfit();
              oPM=" PM="+ProfitMade;
              oLL=" LL="+LossLimit;
              OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
             }


           // Did we take a loss
           //====================
           if(LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*Point))
             {
              oTK=" Ticket="+OrderTicket();
              oSL=" SL="+OrderStopLoss();
              oTP=" TP="+OrderTakeProfit();
              oPM=" PM="+ProfitMade;
              oLL=" LL="+LossLimit;
              OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
             }

          } // if BUY


        if(OrderType()==OP_SELL)
          {
           CurrentProfit=(OrderOpenPrice()-Ask);

           // Did we make a profit
           //======================
           if( ProfitMade>0 && CurrentProfit>=(ProfitMade*Point) )
             {
              oTK=" Ticket="+OrderTicket();
              oSL=" SL="+OrderStopLoss();
              oTP=" TP="+OrderTakeProfit();
              oPM=" PM="+ProfitMade;
              oLL=" LL="+LossLimit;
              OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Red);
             }


           // Did we take a loss
           //====================
           if( LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*Point) )
             {
              oTK=" Ticket="+OrderTicket();
              oSL=" SL="+OrderStopLoss();
              oTP=" TP="+OrderTakeProfit();
              oPM=" PM="+ProfitMade;
              oLL=" LL="+LossLimit;
              OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Red);
             }

          } //if SELL

       } // if(OrderSymbol)

    } // for

 } // start()




//+-----------------+
//| CloseEverything |
//+-----------------+
// Closes all OPEN and PENDING orders

int CloseEverything()
 {
  double myAsk;
  double myBid;
  int    myTkt;
  double myLot;
  int    myTyp;
  int    mygle;

  int i;
  bool result = false;

  for( i=(OrdersTotal()-1); i>=0; i-- )
    {
     OrderSelect(i, SELECT_BY_POS);
     if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
       {
        myAsk=MarketInfo(OrderSymbol(),MODE_ASK);
        myBid=MarketInfo(OrderSymbol(),MODE_BID);
        myTkt=OrderTicket();
        myLot=OrderLots();
        myTyp=OrderType();

        switch( myTyp )
          {
           //Close opened long positions
           case OP_BUY      :CloseBuy("CLOSEEVERYTHING BUY");
           break;

           //Close opened short positions
           case OP_SELL     :CloseSell("CLOSEEVERYTHING SELL");
           break;
         }

        Sleep(500);

       }//symbol&MagicNumber

    } //for

 } // closeeverything



//ENTRY LONG (buy, Ask)
void OpenBuy (string myInfo, double myLots)
 {
  int loopcount=0;
  double SL,TP;
  int ticket;
  int gle;

  if(!IsTradeAllowed())
    {
     return(0);
    }

  while(true)
    {
     if(LossLimit ==0) SL=0; else SL=Ask-((LossLimit+LL2SL)*Point );
     if(ProfitMade==0) TP=0; else TP=Ask+((ProfitMade+LL2SL)*Point );
     ticket=OrderSend(Symbol(),OP_BUY,myLots,Ask,Slippage,SL,TP,TradeComment,MagicNumber,White);
     gle=GetLastError();
     if(gle==0)
       {
        break;
       }

     loopcount++;
     if(loopcount>maxloop)
       {
        Alert("Order failed to OPEN - See Journal for errors");
        break;
       }

     Sleep(500);
     RefreshRates();

    }//while
 }//OpenBuy


//ENTRY SHORT (sell, Bid)
void OpenSell (string myInfo, double myLots)
 {
  int loopcount=0;
  double SL,TP;
  int ticket;
  int gle;

  if(!IsTradeAllowed())
    {
     return(0);
    }

  while(true)
    {
     if(LossLimit ==0) SL=0; else SL=Bid+((LossLimit+LL2SL)*Point );
     if(ProfitMade==0) TP=0; else TP=Bid-((ProfitMade+LL2SL)*Point );
     ticket=OrderSend(Symbol(),OP_SELL,myLots,Bid,Slippage,SL,TP,TradeComment,MagicNumber,Red);
     gle=GetLastError();
     if(gle==0)
       {
        break;
       }

     loopcount++;
     if(loopcount>maxloop)
       {
        Alert("Order failed to OPEN - See Journal for errors");
        break;
       }

     Sleep(500);
     RefreshRates();

    }//while

 }//SELLme



void CloseBuy (string myInfo)
 {
  int gle;
  int cnt;

  int loopcount=0;

  while(true)
    {
     OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
     gle=GetLastError();
     if(gle==0)
       {
        break;
       }

     loopcount++;
     if(loopcount>maxloop)
       {
        Alert("Order failed to CLOSE - See Journal for errors");
        break;
       }

     Sleep(500);
     RefreshRates();

    }//while

 }


void CloseSell (string myInfo)
 {
  int gle;
  int cnt;

  int loopcount=0;

  while(true)
    {
     OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Red);
     gle=GetLastError();
     if(gle==0)
       {
        break;
       }

     loopcount++;
     if(loopcount>maxloop)
       {
        Alert("Order failed to CLOSE - See Journal for errors");
        break;
       }

     Sleep(500);
     RefreshRates();

    }//while
 }