//+------------------------------------------------------------------+
//|                                      Trade_Manager_EA_wTrail.mq4 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Financial Freedom With FX"
#property link      "none"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////                                 
//NOTE:  1ST YOU PLACE YOUR ORDER... THEN YOU SET THIS EA TO MANAGE THAT ORDER... THIS EA WILL ONLY MANAGE (1) PAIR AT A TIME //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//============================= TAKE PROFIT LEVELS (Set on "Inputs" tab once EA is attached to chart)==========================

extern string  PreSet_Name         = "Trade_Manager_Trail";    // Text name assigned to THIS expert. This is used to differentiate between EAs which might be managing two DIFFERENT trades on the SAME pair.


//============================= TAKE PROFIT LEVELS (Set on "Inputs" tab once EA is attached to chart)==========================

extern int     First_TP_Target     = 30;     // First take profit target ("Sell X lots when X pips in profit is reached)
extern int     TP_Target_Increment = 50;     // Once the "First Target" profit level is reached, the next X lots will be sold in increments specified here. 
extern double  Close_Lots          = 0.1;    // Number of lots you want to take out when each profit target is reached.

///////////////////////////////////////////// TAKE PROFIT EXAMPLE ////////////////////////////////////////////////////////
// EXAMPLE: Initial Order = 2 lots.                                                                                     //
// When profit is +20 pips (First Target = 20) = sell .5 lots (Close Lots)                                              //
// When profit is +40 pips (Target Increment = 20) = sell .5 lots (Close Lots)                                          //
// When profit is +60 pips (Target Increment = 20) = sell .5 lots (Close Lots)                                          //
// When profit is +80 pips (Target Increment = 20) = sell .5 lots (Close Lots) - Final lot sold and trade is done       //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern bool    Use_Max_Loss        = true;   // Set to "true" to use a Stop Loss. "False" if you don't want to use a "Stop Loss"
                                             // NOTE: SETTING A STOP LOSS HERE HIDES IT FROM YOUR BROKER, SO THEY CAN'T STOP-HUNT!!! 

extern int     Max_Loss            = 50;     // Your stop loss setting. If "Use Max Loss" is set to "false", this value is irrelevant


//================================ STOP LOSS (Set on "Inputs" tab once EA is attached to chart)================================

extern bool    Move_Stops          = true;   // If "true"... EA will move stop loss according to your settings. If "false"... Take profits will work but it will NOT move S/L levels
extern int     First_Stop_Target   = 50;     // When profit level reaches X (THIS SETTING) pips, move the stop loss to... (see next line)
extern int     First_Stop          = 1;      // When trade is X pips in profit (set in "First Stop Target", move S/L to X pips from ENTRY (Can be postive or negative)
extern int     Second_Stop_Target  = 80;     // Same as "First stop target"... 
extern int     Second_Stop         = 30;     // Same as "First stop"... 
extern int     Third_Stop_Target   = 100;    // Same as "First stop target"... 
extern int     Third_Stop          = 50;     // Same as "First stop"... 
                                             // NOTE: You do not have to use all three Stop_Targets. You can just set to "0" those you do not wish to use.

///////////////////////////////////////////// STOP-LOSS MANAGEMENT ///////////////////////////////////////////////////////
// Original Stop Loss (S/L) set to 25 (Max Loss = 25)                                                                   //
// When profit is +20 pips (First Stop Target = 20) = move S/L to 10 pips BELLOW ENTRY (First stop = (-10))             //
// When profit is +35 pips (Second Stop Target = 35) = move S/L to 10 pips ABOVE ENTRY (Second stop = ( 10))            //
// When profit is +50 pips (Third Stop Target = 50) = move S/L to 30 pips ABOVE ENTRY (Third stop = ( 30))              //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern int     Trail_Stop_By       = 0;      // Once THIRD STOP LEVEL is reached (trade is + X pips and stop loss moved)... Trail from STOP LOSS level by pips set here
                                             // Example: 3rd stop Target reached at +50 and S/L moved to +30.
                                             //          A trail of 30 will kick in when trade is at +60 (Currently at +50 & S/L of +30 = (trail) 20.
                                             //          At +60 & S/L at +30 = 30 and trail starts from there

extern bool    Alert_Sound         = true;   // If "true" - Alarm sounds at Take Profit levels and when Stop Loss is hit
extern bool    Alert_Email         = false;  // If "true" - Sends e-mail alert
extern int     Magic_Number        = 0;      // Used to manage multiple trades on same pair... REQUIRES A SCRIPT FOR INITIAL ORDER ENTRY... Leave this at "0"

//=============== VARS internal
int nextTP;
int sl;
int range = 5;
int multiplier;
int Trail_Stop;
int Trail_Trigger;
int temp;
string trailon;
//string version="MTP 1.5 8-28-07 ";  //---Displays "Version" information on top line of actual chart display

// OrderType == 1 is OP_SELL


//=============== FUNCTION init
int init()
  {
   if(First_Stop==0 && First_Stop_Target !=0) First_Stop=1;
   if(Max_Loss < 0) Max_Loss=(-1*Max_Loss);
   if(Trail_Stop_By < 0) Trail_Stop_By = -1*Trail_Stop_By;
   sl = -1*Max_Loss;
   nextTP = First_TP_Target;
   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;
   
   Comment(/*version ,*/"PreSet... ", PreSet_Name,   //==== USE THIS to differentiate btwn trades on same pair (i.e.. "LongTrmTrade" ; "BounceTrade", etc...)
   "\nClose Lots: ", Close_Lots,
   "\nTP @ +", First_TP_Target, " then incrmnt by ", TP_Target_Increment,
   "\nSL1: @ +",First_Stop_Target, " > ",First_Stop,
   "\nSL2: @ + ",Second_Stop_Target, " > ",Second_Stop,
   "\nSL3: @ +",Third_Stop_Target,  " > ",Third_Stop,
   "\nTrail SL:  ", Trail_Stop_By,
   "\nMax Loss:  ", Max_Loss);
  }
//== end function


//=============== FUNCTION deinit
int deinit()
  {
//----
   sl = -1*Max_Loss;
   nextTP = First_TP_Target;
   Trail_Stop = sl;
//----
   return(0);
  }
//== end function

//========== FUNCTION Start
int start()
  {
//----
   getOpenOrders();
   getSpread();
   //Comment(sl);
//----
   return(0);
  }
//== end function

//========== FUNCTION getPipValue
double getPipValue(double ord,int dir)
{
   double val;
   RefreshRates();
   if(dir == 1) val=(NormalizeDouble(ord,Digits) - 
NormalizeDouble(Ask,Digits));
   else val=(NormalizeDouble(Bid,Digits) - NormalizeDouble(ord,Digits));
   val = val/Point;
   return(val);
}
//== end function

int getSpread()
{
   int spread=MarketInfo(Symbol(),MODE_SPREAD);
   return(spread);
}


int getMaxLoss()
{
   int calcMaxLoss;
   calcMaxLoss = Max_Loss;
   return(calcMaxLoss);
}
//========== FUNCTION getOpenOrders
void getOpenOrders()
{
   int nsl, nsd;
   string mngMagic;
   int totalorders = OrdersTotal();
   for(int j=0; j<totalorders;j++)
     {
         OrderSelect(j, SELECT_BY_POS, MODE_TRADES);
         if((OrderType() == OP_BUY || OrderType() == OP_SELL) && 
OrderSymbol() == Symbol()&&(Magic_Number==0 || Magic_Number == 
OrderMagicNumber()))
         {

            double val=getPipValue(OrderOpenPrice(),OrderType());
            //int val = OrderProfit()/(OrderLots()*10);
            if(Move_Stops) checkStops(val,OrderTicket());
            if(First_TP_Target !=0) takeProfit(val,OrderTicket());

         }

         if(Magic_Number == 0)
         mngMagic = "All "+Symbol()+" trades.";
         else
         mngMagic = "Trades with magic number = "+Magic_Number;


         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";  
            }
         //RefreshRates();

         Comment(/* version ,*/"PreSet... ", PreSet_Name,
         "\nClose Lots:  ", Close_Lots,
         "\nTP @ +", First_TP_Target, " then incrmnt by ", TP_Target_Increment,
         "\nSL1: @ +",First_Stop_Target, " > ",First_Stop,
         "\nSL2: @ + ",Second_Stop_Target, " > ",Second_Stop,
         "\nSL3: @ +",Third_Stop_Target,  " > ",Third_Stop,
         "\nTrail SL:  ", Trail_Stop_By,
         "\nMax Loss:  ", Max_Loss,
         "\n----------------------------",
         "\nOrder Open: ",OrderOpenPrice(),
         "\nPip Count: ", val,
         "\nNext TP: ", nextTP,
         "\nCurr SL: ", sl,
         "\nTrail SL Trigger: ", Trail_Trigger, "   ", trailon,
         "\nManaging: ", mngMagic);
     }
}

//========== FUNCTION takeProfit
void takeProfit(int pips, int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
      if(pips >= nextTP)
      {
         if(Alert_Sound) PlaySound("TakeProfitHit.wav");
         if(OrderType()==1)    // 1 = OP_Sell
         {
            if(OrderClose(ticket, Close_Lots, Ask, 3, Lime))
            nextTP+=TP_Target_Increment;
            else
            Print("Error closing order : ",GetLastError());
         }
         else
         {
            if(OrderClose(ticket, Close_Lots, Bid, 3, Lime))
            nextTP+=TP_Target_Increment;
            else
            Print("Error closing order : ",GetLastError());
         }

      }

   }
}

//== end function



//========== FUNCTION moveStops
void checkStops(int pips,int ticket)
{
   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";  
   }
   if(pips <= sl) stopTrade(pips,OrderTicket());  
}

//== end function

//========== FUNCTION moveStops
void moveStops(int ticket,int stopDiff)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
      Print("moveStops called ",ticket, " ",stopDiff);
      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;
      }
   }
}

//== end function

//========== FUNCTION killTrades
void stopTrade(int pips, int ticket)
{
   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("TakeProfitHit.wav");
          else PlaySound("StopLossHit.wav");
          
   }
}
//== end function

