//+------------------------------------------------------------------+
//|                                                   TakeProfit.mq4 |
//|                                                 Copyright © 2010 |
//|                                                           FnickB |
//|                                                    Version: 2.5  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010 original code by Stockwet"
#property link      "Nick"


/*
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.
  4/22/2010::  Added StopLoss Increments by Nick Benedict 2010 benni12@gmail.com 
               allows for setting an initial First_Stop_Target which when hit will
               set the First_Stop, then every Stop_Target_Increment move in pips will
               reset the stop loss by adding the SL_Increment to the previously set SL.
               Also, removed the original fixed stop losses. If looking for fixed
               search for version 2.4.
               And a Thank you to Taylor Stockwell for the original EA, Great work!
4/28/2010:: adjusted comments to show spread even when no open orders exist               
5/15/2010:: fix the close_Lots thing... just a test to see if close_lots is less than open lots, if so then set Close_lots to open,
            also TakeProfit now only enters if Close_Lots does not equal 0, so if you dont want to take profit, then put a 0 in Close_Lots
            stopped using OrdersTotal() to test if open positions since this also returned opened Orders, CalculateCurrentOrders only returns open positions for the
            Current symbol. ALso placed this test in INIT, DEINIT, START for any resetting of variables.
            
5/18/2010:: Close Lots was not resetting, so this is fixed, BUT this EA must be attached to a chart BEFORE an open trade on that chart/pair or 
            Close_Lots will not initialize. Changed the extern from Close_Lots to Lots_to_Close, which now resets when there are no open positions
*/
//=============== VARS external
extern int First_Target = 100;
extern int Target_Increment = 900;
extern double Lots_to_Close = 2.0;
extern bool Move_Stops = true;
extern int First_Stop_Target = 50;
extern int Stop_target_Increment = 50;
extern int First_Stop = 0;
extern int SL_Increment = 50;
extern bool Use_Max_Loss = true;
extern int Max_Loss = 400;
extern int Magic_Number=0;

//=============== VARS internal
int nextTP;
bool sl;
int range = 5;
int multiplier;
// OrderType == 1 is OP_SELL
int nextSL;
int nextSLT;
double pipVal;
double Close_Lots;
//=============== FUNCTION init
int init()
  {  
      int tOrdersinit = CalculateCurrentOrders();
 
     if(tOrdersinit == 0){
       Close_Lots = Lots_to_Close;
       sl=0;
       nextTP = First_Target;
       nextSL = First_Stop + SL_Increment;
       nextSLT = First_Stop_Target + SL_Increment;
   }
     
       getMaxLoss();
       getSpread();
  }
//== end function


//=============== FUNCTION deinit
int deinit()
  {
//----

//----
   return(0);
  }
//== end function

//========== FUNCTION Start
int start()
  {
    int tOrdersinit = CalculateCurrentOrders();
    if(tOrdersinit == 0){ 
        sl=0;
        Close_Lots = Lots_to_Close;
        nextTP = First_Target;
        nextSL = First_Stop + SL_Increment;
        nextSLT = First_Stop_Target + SL_Increment;
   }
   
   getOpenOrders();
           Comment("Order Open: ",OrderOpenPrice(), 
         "\nClose_Lots: ",Close_Lots,
         "\nPip Count: ", pipVal,
         "\nFirst Target: ", First_Target,
         "\nFirst Stop: ", First_Stop,
         "\nFirst Stop Target: ", First_Stop_Target,
         "\nNext Stop Target: ",nextSLT,
         "\nNext Stop Increment: ", Stop_target_Increment,
         "\nNext Stop: ", nextSL, 
         "\nNext TP: ", nextTP,
         "\nSpread: ",getSpread());      
 
     
   //Comment(sl);
//----
   return(0);
  }
//== end function

//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders()
  {
                  int pos=0;
               //----
                  for(int i=0;i<OrdersTotal();i++)
                    {
                     if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
                     if(OrderSymbol()==Symbol() )
                       {
                        if(OrderType()==OP_BUY)  pos++;
                        if(OrderType()==OP_SELL) pos++;
                       }
                    }
               //---- return orders volume
                return(pos);
  }
  
//+------------------------------------------------------------------+
//========== 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 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()); 
            pipVal = val;
            //int val = OrderProfit()/(OrderLots()*10);
            if(Use_Max_Loss && Max_Loss > 0) killTrade(val,OrderTicket());
            if(Move_Stops) checkStops(val,OrderTicket());
            if(Close_Lots != 0)  takeProfit(val,OrderTicket());            
            
         }
         
    
         
   


     }  
}

//========== FUNCTION takeProfit
void takeProfit(int pips, int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
if(OrderLots() <= Close_Lots) Close_Lots = OrderLots();
      if(pips >= nextTP && pips < (nextTP + Target_Increment))
      {
         if(OrderType()==1)
         {
            if(OrderClose(ticket, Close_Lots, Ask, 3, YellowGreen))
            nextTP+=Target_Increment;
            else
            Print("Error closing order : ",GetLastError()); 
         } 
         else
         {
            if(OrderClose(ticket, Close_Lots, Bid, 3, YellowGreen))
            nextTP+=Target_Increment;
            else
            Print("Error closing order : ",GetLastError()); 
         }
              
      }

   }
}

//== end function



//========== FUNCTION moveStops
void checkStops(int pips,int ticket)
{
   
 if(sl==0 && pips >=  First_Stop_Target && pips < (First_Stop_Target + SL_Increment )){  
         moveStops(ticket,First_Stop);
	     // nextSL += SL_Increment;
      }else if(pips >= (nextSLT )){
	      moveStops(ticket,nextSL);
	      nextSL += SL_Increment;
      	nextSLT += Stop_target_Increment;
}
}


//== 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) 
      {
      OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()-stopDiff*Point, OrderTakeProfit(),0,Plum);
      sl=1;
      }
      else 
      {
      OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()+stopDiff*Point, OrderTakeProfit(),0,Plum);
    sl=1;
      }
   }

   
}

//== end function

//========== FUNCTION killTrades
void killTrade(int pips, int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET)==true)
   {
      if(pips <= -1*getMaxLoss())
      {
         if(OrderType()==1) OrderClose(ticket,OrderLots(),Ask,3,Red);     
         else OrderClose(ticket,OrderLots(),Bid,3,Red); 
      }      
   }
}
//== end function