//+------------------------------------------------------------------+
//|                                                          MTP.mq4 |
//|                               Copyright © 2006, Taylor Stockwell |
//|                                                    Version: 1.7  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Taylor Stockwell"
#property link      "stockwet@yahoo.com"


/*
Updates:

   11/2/2006:: Fixed bug that caused the sl var to be set to 1 when a 
               pending order was > than the First_Stop_Target value.
   1/23/2007:: Fixed pip calculation. The old way of calculating pips 
               could be off by 1 pip, resulting in missed TP or move 
               stops. The new calculation is more accurate.
   5/31/2007:: Lousan:  Added a Third Stop Loss.  Renamed EA to MTP 
               to differentiate it from Stockwell's version.
   6/01/2007:: Lousan:  Added a pip by pip trailing stop loss to kick 
               in after the last fixed Stop Loss is in place.
   7/27/2007:: Lousan:  Ver 1.2  Added Version # and Revision date and 
               Pre-Set Name to display.   
   8/09/2007:: Lousan:  Ver 1.3  Trailing stop was not being moved when
               fixed stops were zero.
   8/14/2007:: Lousan:  Cosmetic change to Legend
   8/17/2007:: Lousan:  Ver 1.31  Added email and sound alerts
   8/24/2007:: Lousan:  Ver 1.4  Revised to make the Trailing Stop an 
               imaginary stop, ie. don't send a Move Stop request to the 
               server, but keep track of the stop within MTP, like it 
               does with Max Loss.
   8/27/2007:: Lousan:  Ver 1.5 If fixed Stop 2 or 3 was zero, then 
               previous current stop would be set to zero.  Fixed that.
   9/03/2007:: Lousan:  Ver 1.51  Revised to set Max_Loss to 999 if 
               input value is zero.  Also added display for open and close 
               (last) spreads and for Max Pips (high water mark).
   9/21/2007:: Lousan:  Ver. 1.6  Added option to choose of closing lots.  
               Method 1 closes one position at each TP point.  Method 2  
               increases number of lots to close at each TP point by 
               adding the original Lots to Close to the current number.
   9/26/2007:: Lousan:  Ver. 1.7  Increased the number of TP targets from 
               1 to 3.  Removed the Move_Stops and Use_Max_Loss input 
               parameters.   
   7/31/2009:: Vignesh: Ver 1.71 Divided pips by Digits
   8/05/2009:: Vignesh: Set value for First, second and third tp  
  20/01/2010:: Vignesh: Removed the comments as it is creating too much logs.    
                                   
*/

//=============== VARS external
extern string PreSet_Name = "Default";
extern int First_TP = 10;
extern int Second_TP = 15;
extern int Third_TP = 20;
extern int TP_Increment = 10;
extern double Close_Lots = 0.50;
extern int Close_Method = 1;
extern int First_Stop_Target = 10;
extern int First_Stop = 1;
extern int Second_Stop_Target = 20;
extern int Second_Stop = 11;
extern int Third_Stop_Target = 30;
extern int Third_Stop = 21;
extern int Trail_Stop_By = 10;
extern int Max_Loss = 15;
extern bool Alert_Sound = true;
extern bool Alert_Email = false;
extern int Magic_Number=0;

//=============== VARS internal
int nextTP;
int sl;
int range = 5;
int multiplier;
int Trail_Stop;
int Trail_Trigger;
int Open_Spread=0;
int Close_Spread=0;
int Max_Pips=-99;
int temp;
double Lots2Close;
string trailon;
string version="MTP 1.711  Sept. 26, 2007   ";

// OrderType == 1 is OP_SELL


//=============== FUNCTION init
int init()
  {
  // Print("Entering init");
  // Print("First_stop ", First_Stop );
  // Print("First_stop_target ", First_Stop_Target );

   if(First_Stop==0 && First_Stop_Target !=0) First_Stop=1;
//   Print("First_stop  ", First_Stop );
//   Print("Max_Loss  ", Max_Loss );
 
   if(Max_Loss < 0) Max_Loss=(-1*Max_Loss);
 //  Print("Max_Loss  ", Max_Loss );

   if(Max_Loss==0)  Max_Loss=999;
//   Print("Max_Loss  ", Max_Loss );
  // Print("Trail_stop_by  ", Trail_Stop_By );
   if(Trail_Stop_By < 0) Trail_Stop_By = -1*Trail_Stop_By;
//   Print("Trail_stop_by  ", Trail_Stop_By );
   sl = -1*Max_Loss;
//   Print("Tsl ", sl );
//   Print("First_TP  ", First_TP );

   if(First_TP!=0) nextTP = First_TP;
   else nextTP = TP_Increment;
//  Print("nextTP  ", nextTP );

   Trail_Stop = sl;
   trailon = "Off ";
   getMaxLoss();    // ???? Why is getMaxLoss function necessary? ~Lousan
   if(Third_Stop!=0) Trail_Trigger=Third_Stop+Trail_Stop_By;
   else if(Second_Stop!=0) Trail_Trigger=Second_Stop+Trail_Stop_By;
   else if(First_Stop!=0) Trail_Trigger=First_Stop+Trail_Stop_By;
   else Trail_Trigger=sl+Trail_Stop_By;
   
//  Print("Trail_Trigger ", Trail_Trigger );

   Lots2Close = Close_Lots;
//     Print("Lots2Close ", Lots2Close );

   
   Comment(version, 
   "\nPreSet . . . ", PreSet_Name,
   "\nClose Method:  ", Close_Method,  
   "\nClose Lots:    ", Close_Lots,
   "\nTP:   ", First_TP, "  ", Second_TP, "  ",
               Third_TP, "  +", TP_Increment,
   "\nSL1:  ", First_Stop_Target, "  ", First_Stop,
   "\nSL2:  ", Second_Stop_Target, "  ", Second_Stop,
   "\nSL3:  ", Third_Stop_Target,  "  ", Third_Stop,
   "\nTSL:  ", Trail_Stop_By,
   "\nMax Loss:  ", Max_Loss);
  //   Print("Exiting init" );

  }
//== end function


//=============== FUNCTION deinit
int deinit()
  {
//----
//  Print("Entering deinit" );

   sl = -1*Max_Loss;
//     Print("sl ", sl );

   nextTP = First_TP;
//     Print("nextTP ", nextTP );

   Trail_Stop = sl;
//     Print("Trail_sTOP ", Trail_Stop );

//----
//  Print("Exiting deinit" );

   return(0);
  }
//== end function

//========== FUNCTION Start
int start()
  {
//----
//  Print("Entering start" );
//  Print("Calling getopenorders" );

   getOpenOrders();
//   Print("Calling getSpread" );
  
   getSpread();
   //Comment(sl);
//----
//  Print("Exiting start" );

   return(0);
  }
//== end function

//========== FUNCTION getPipValue
double getPipValue(double ord,int dir)
{
   double val;
//     Print("Entering getPipValue" );
 // Print("Calling refreshrates" );

   RefreshRates();
//    Print("dir ", dir );
  //  Print("NormalizeDouble(ord, Digits )", NormalizeDouble(ord, Digits ) );
   //  Print("NormalizeDouble(Ask, Digits )", NormalizeDouble(Ask, Digits ) );
    
    //    Print("NormalizeDouble(Bid, Digits )", NormalizeDouble(Bid , Digits ) );
 //   Print("Point ", Point );
// Print("Digits", Digits ) ;
   if(dir == 1) val=(NormalizeDouble(ord,Digits) - 
NormalizeDouble(Ask,Digits));
   else val=(NormalizeDouble(Bid,Digits) - NormalizeDouble(ord,Digits));
  //      Print("val ", val );

//   Print (" New calc ", NormalizeDouble((Bid-ord)/Point,Digits));

//   Print (" New calc 2  ", val * MathPow(10, Digits ));

   val = val * MathPow(10, (Digits - 1) );
//     Print("val ", val );
   
   return(val);
}
//== end function

int getSpread()
{
   int spread=MarketInfo(Symbol(),MODE_SPREAD);
   
//        Print("Entering getspread");

   if(Open_Spread==0) Open_Spread=spread;
   Close_Spread=spread;
   
//        Print("Open_spread ", Open_Spread );
  //      Print("Close_Spread ", Close_Spread );


   return(spread);
}


int getMaxLoss()
{
   int calcMaxLoss;
//   Print("Entering getMaxloss ");

   calcMaxLoss = Max_Loss;
//        Print("calcMaxLoss", calcMaxLoss );

   return(calcMaxLoss);
}
//========== FUNCTION getOpenOrders
void getOpenOrders()
{
   int nsl, nsd;
   string mngMagic;
//        Print("Entering getOpenOrders ");

   int totalorders = OrdersTotal();
//        Print("totalorders  ", totalorders );

   for(int j=0; j<totalorders;j++)
     {
         OrderSelect(j, SELECT_BY_POS, MODE_TRADES);
//              Print("OrderType ", OrderType());
  //   Print("OrderSymbol ", OrderSymbol() );
    //      Print("Magi_number", Magic_Number  );


         if((OrderType() == OP_BUY || OrderType() == OP_SELL) && 
            OrderSymbol() == Symbol()&&(Magic_Number==0 || Magic_Number == 
            OrderMagicNumber()))
         {
            double val=getPipValue(OrderOpenPrice(),OrderType());
//                 Print("val ", val );
//     Print("calling checkstops ");

            checkStops(val,OrderTicket());
//                 Print("val ", val );
  //                    Print("nextTP ", nextTP );


            if(val > nextTP) takeProfit(val,OrderTicket());
         }

         if(Magic_Number == 0)
         mngMagic = "All "+Symbol()+" trades.";
         else
         mngMagic = "Trades with magic number = "+Magic_Number;

//     Print("mngMagic ", mngMagic );

         if(sl==-1*Max_Loss)
            {
               nsl = First_Stop_Target;
               nsd = First_Stop;
            }
         else if(sl==First_Stop)
            {
               nsl = Second_Stop_Target;
               nsd = Second_Stop;
            } 
         else if(sl==Second_Stop)
            {
               nsl = Third_Stop_Target;
               nsd = Third_Stop;
            }
         else if(Trail_Stop_By != 0 && val >= Trail_Trigger)
            {
               nsl = val + 1;
               nsd = val + 1 - Trail_Stop_By; 
               trailon = " On";  
            }
            
//                 Print("nsl ", nsl );
  //               Print("nsd ", nsd );
    //             Print("trailon ", trailon );



         //RefreshRates();
         Comment(version, 
         "\nPreSet . . . ", PreSet_Name,
         "\nClose Method:  ", Close_Method,
         "\nClose Lots:    ", Close_Lots,
         "\nTP:   ", First_TP, "  ", Second_TP, "  ",
                     Third_TP, "  +", TP_Increment,
         "\nSL1:  ", First_Stop_Target, "  ", First_Stop,
         "\nSL2:  ", Second_Stop_Target, "  ", Second_Stop,
         "\nSL3:  ", Third_Stop_Target,  "  ", Third_Stop,
         "\nTSL:  ", Trail_Stop_By,
         "\nMax Loss:  ", Max_Loss,
         "\n----------------------------",
         "\nOrder Open: ",OrderOpenPrice(),
         "\nOpen Spread:  ",Open_Spread,
         "\nClose Spread:  ",Close_Spread,
         "\nMax Pips:    ",Max_Pips,
         "\nPip Count:   ", val,
         "\nNext TP:     ", nextTP, "   ", Lots2Close, " Lots",
         "\nCurr  SL:     ", sl,
         "\nTSL Trigger:   ", Trail_Trigger, "   ", trailon,
         "\nManaging:  ", mngMagic);


     }
}

//========== FUNCTION takeProfit
void takeProfit(int pips, int ticket)
{
//     Print("Entering takeprofit" );

   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
//         Print("pips  ", pips );
//              Print("nextTP ", nextTP );


      if(pips >= nextTP)
      {
         if(Alert_Sound) PlaySound("mtp2.wav");
//              Print("OrderType ", OrderType() );

         if(OrderType()==1)    // 1 = OP_Sell
         {
            if(OrderClose(ticket, Lots2Close, Ask, 3, Lime)) temp=0;
            else Print("Error closing order : ",GetLastError());
         }
         else
         {
            if(OrderClose(ticket, Lots2Close, Bid, 3, Lime)) temp=0;
            else Print("Error closing order : ",GetLastError());
         }
         if(Close_Method==2) Lots2Close = Lots2Close + Close_Lots;
//           Print("Lots2Close ", Lots2Close );

         if(nextTP == Third_TP) nextTP = nextTP + TP_Increment;
         else if (nextTP == Second_TP) nextTP = Third_TP;
         else if (nextTP == First_TP) nextTP = Second_TP;
         else nextTP = nextTP + TP_Increment;
      }
   }
//        Print("nextTP ", nextTP );
  //        Print("Exiting takeprofit");
}



//== end function



//========== FUNCTION moveStops
void checkStops(int pips,int ticket)
{

//     Print("Entering checkstops" );
  //   Print("sl ", sl );
    // Print("max_loss ", Max_Loss );
 //    Print("First_Stop ", First_Stop );
 //    Print("pips ", pips );
 //    Print("First_stop_target ", First_Stop_Target );


   if(sl==-1*Max_Loss && First_Stop != 0 && pips >= First_Stop_Target)
   {
      moveStops(ticket, First_Stop);
   }
   else if(sl==First_Stop && First_Stop != 0 && pips >= Second_Stop_Target && Second_Stop !=0)
   {
      moveStops(ticket,Second_Stop);
   }
   else if(sl==Second_Stop && Second_Stop != 0 && pips >= Third_Stop_Target && Third_Stop !=0)
   {
      moveStops(ticket,Third_Stop);
   }
   else if(Trail_Stop_By != 0 && pips >= Trail_Trigger && pips - Trail_Stop_By > sl)
   {
      Trail_Stop = pips - Trail_Stop_By;
      sl = Trail_Stop;
      trailon = " ON";  
   }
   
//      Print("pips ", pips );
//     Print("sl ", sl );
//          Print("Max_pips ", Max_Pips );

  
   if(pips <= sl) stopTrade(pips,OrderTicket());  
   if(pips > Max_Pips) Max_Pips = pips;
//        Print("Exiting checkstops " );

   
}

//== end function

//========== FUNCTION moveStops
void moveStops(int ticket,int stopDiff)
{

//     Print("Entering movestops " );

   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
//      Print("moveStops called ",ticket, " ",stopDiff);
  //    Print("ordertype ", OrderType() );

      if(OrderType()==1)     // 1 = OP_Sell
      {
      OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()-stopDiff*Point, 
OrderTakeProfit(),0,Plum);
      sl=stopDiff;
      }
      else
      {
      OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()+stopDiff*Point, 
OrderTakeProfit(),0,Plum);
      sl=stopDiff;
      }
   }
//        Print("Exiting movestops" );

}

//== end function

//========== FUNCTION killTrades
void stopTrade(int pips, int ticket)
{

//      Print("Entering stoptrade" );

   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
       if(OrderType()==1) OrderClose(ticket,OrderLots(),Ask,3,DarkViolet);
       else OrderClose(ticket,OrderLots(),Bid,3,DarkViolet);
       
       if(Alert_Email) SendMail("MTP:  Trade Stopped "+pips," ");
       if(Alert_Sound) 
          if(pips > 0) PlaySound("mtp3.wav");
          else PlaySound("mtp1.wav");
          
   }
//        Print("Exiting stopTrade");

}
//== end function