//+------------------------------------------------------------------+
//|                                  Multi-purpose trade manager.mq4 |
//|                                  Copyright © 2008, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+								additions by macman	04-2011		     |  	
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"

/*

Functions list:

int CountTradeLevels()
bool CheckTradingTimes()
double GetMaxLotsAllowed()


int start()   holds the always on loop that calls main(), which was the original start()
void main()
void MonitorTrades()
void ManageTrade()
void ShirtProtection()
void BreakEvenStopLoss()
void JumpingStopLoss()
bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
bool PartCloseTradeFunction()
void TryPartCloseAgain()
void SetAGlobalTicketVariable()
int GetNextAvailableVariableNumber()
void TrailingStopLoss()
void InstantTrailingStopLoss()
void HiddenStopLoss()
void HiddenTakeProfit()
void GlobalOrderClosure()
bool ExtractPartCloseVariables()
void PartCloseOrder()
bool CheckForExistingHedge()
void HedgeTrade()
void DeleteOrphanHedgeGVs()
void EvaluateCloseThis() //added by macman
void CloseThis() //added by macman
void DetermineTrendDirection(string symbol)
void MonitorBasketTrades()
void CloseBasketTrades()
void CalculateBasketPL()
bool ShouldBasketCloseAtSL()
void BasketTrailingStopManipulation()
bool ConfirmBasketClosure()
double getPipValue(double ord,int dir)
void checkStops(int pips,int ticket)
void moveStops(int ticket,int stopDiff)
void takeProfit(int pips, int ticket)
void CheckBasketTradesExpiry()
void BasketJumpingStopManipulation()
bool ShouldBasketCloseAtAutocalcTP()
double AutoPercentageBasketTp()
void InsertStopLoss()
void InsertTakeProfit()
void TightenStopLoss()

*/

//R&R inputs
extern string  gen="----General inputs----";
extern double  Lot=0.01;
extern int     MaxSpread=40;
// extern int     MagicNumber=0;
extern string  TradeComment="";
extern bool    CriminalIsECN=false;
extern int     MaxTradeLevels=6;
extern double  CashProfitPerBreakEvenPip=0.5;
extern int     FkMinimumMarginPercent=1500;
extern int     TakeProfit=0;
extern string  tt="----Trading hours----";
extern string  Trade_Hours= "Set Morning & Evening Hours";
extern string  Trade_Hoursi= "Use 24 hour, local time clock";
extern string  Trade_Hours_M= "Morning Hours 0-12";
extern  int    start_hourm = 0;
extern  int    end_hourm = 12;
extern string  Trade_Hours_E= "Evening Hours 12-24";
extern  int    start_houre = 12;
extern  int    end_houre = 24;
////////////////////////////////////
extern string  mm="----Profit settings----"; // added by macman
extern bool    ProfitTakeOn=true;
extern int 	   Slippage =         7;       // set this to an appropriate level for your broker
extern double  CloseThisProfitPercent =  10.0;  // profit closure for this symbol only
extern double  CloseThisLossPercent   =  2.0;  // loss closure for this symbol only
extern int 	   MagicNumber =      0;         // used for "CloseAllLossPercent/CloseAllProfitPercent"
////////////////////////////////////
//mptm inputs
// These allow the EA to run AlwaysOn even without any ticks
extern string	b10			= "===== AlwaysOn =====";
extern bool		AlwaysOn	= false;		// EA Run every delay (ms) (true) or every ticks (false)
extern int		delay		= 1000;		//====== Time (ms) restart adviser in AlwaysOn mode
// User can choose a variety of trade managment triggers.
// These are for use on a chart that controls the currency of that chart
bool    ManageThisPairOnly=true;
// Now give user a variety of facilities
extern string  bl1="---------------------------------------------------------------------";
extern string  ManagementFacilities="Select the management facilities you want";
extern string  slf="----Stop Loss & Take Profit Manipulation----";
extern bool    DoNotOverload5DigitCriminals=false;
extern string  BE="Break even settings";
extern bool    BreakEven=false;
extern int     BreakEvenPips=1;
extern int     BreakEvenProfit=2;
extern bool    HideBreakEvenStop=false;
extern int     PipsAwayFromVisualBE=100;
extern string  JSL="Jumping stop loss settings";
extern bool    JumpingStop=false;
extern int     JumpingStopPips=50;
extern bool    AddBEP=false;
extern bool    JumpAfterBreakevenOnly=false;
extern bool    HideJumpingStop=false;
extern int     PipsAwayFromVisualJS=100;
extern string  pcbe="PartClose settings can be used in";
extern string  pcbe1="conjunction with Breakeven settings";
extern bool    PartCloseEnabled=false;
extern double  Close_Lots = 0.02;
extern double  Preserve_Lots=0.02;
extern string  TSL="Trailing stop loss settings";
extern bool    TrailingStop=true;
extern int     TrailingStopPips=10;
extern bool    HideTrailingStop=false;
extern int     PipsAwayFromVisualTS=100;
extern bool    TrailAfterBreakevenOnly=false;
extern bool    StopTrailAtPipsProfit=false;
extern int     StopTrailPips=0;
extern string  ITSL="Instant trailing stop loss settings";
extern bool    InstantTrailingStop=false;
extern int     InstantTrailingStopPips=30;
extern int     FiveDigitIncrement=0;
extern bool    StopInstantTrailAfterBreakEven=false;
extern bool    StopInstantTrailAtPipsProfit=false;
extern int     StopInstantTrailPips=0;
extern string  hsl1="Hidden stop loss settings";
extern bool    HideStopLossEnabled=false;
extern int     HiddenStopLossPips=200;
extern string  TSF="Tightening stop feature";
extern bool    UseTigheningStop=false;
extern int     TrailAt50Percent=300;
extern int     TrailAt80Percent=200;
extern string  MSLA="Add a missing Stop Loss";
extern bool    AddMissingStopLoss=false;
extern int     MissingStopLossPips=200;
extern bool    UseSlAtr=false;
extern int     AtrSlPeriod=20;
extern int     AtrSlTimeFrame=0;
extern double  AtrSlMultiplier=2;
extern string  MTPA="Add a missing Take Profit";
extern bool    AddMissingTakeProfit=false;
extern int     MissingTakeProfitPips=200;
extern bool    UseTpAtr=false;
extern int     AtrTpPeriod=20;
extern int     AtrTpTimeFrame=0;
extern double  AtrTpMultiplier=3;
extern string  htp="Hidden take profit settings";
extern bool    HideTakeProfitEnabled=false;
extern int     HiddenTakeProfitPips=200;
extern string  bl3="---------------------------------------------------------------------";
extern string  hs="----Hedge settings----";
bool    HedgeEnabled=true;
extern int     HedgeAtLossPips=10;
extern double  HedgeLotsPercent=200;
extern int     HedgingIncrementPips=0;
extern int     HedgeTradeStopLoss=0;
extern int     HedgeTradeTakeProfit=0;
bool    CloseAtBreakEven=true;
bool    HedgingTheHedgeIsAllowed=true;
//extern double  HedgeTheHedgeLotsPercent=200;
//extern int     HedgeTheHedgeAtLossPips=10;
extern bool    AllowTrailingJumpingStops=false;
extern string  Ins14="Trend filter choices";
extern bool    UseEnvelopeTrendFilter=false;
extern int     LookBackBars=3;
extern bool    UseAdxTrendFilter=false;
extern int     AdxPeriod=14;
extern bool    UseCandleDirection=false;
extern int     LookBackCandleHours = 3;
extern string  bl6="---------------------------------------------------------------------";
extern string  OtherStuff="----Other stuff----";
extern bool    ShowAlerts=false;
// Added by Robert for those who do not want the comments.
extern bool    ShowComments = true;
// Added by Robert for those who do not want the journal messages.
extern bool    PrintToJournal = true;

double         LockedProfit=-1;
int            cnt=0; //loop counter
double         bid, ask; // For storing the Bid\Ask so that one instance of the ea can manage all trades, if required
double         point, digits; // Saves the Point and Digits of an order
// Variables for part-close reoutine
double         TargetAsPrice, TargetAsPips;
bool           TrendUp=true;
bool           TrendDown=true;
bool           CloseBasket=false;
string         ScreenMessage;
double         BasketProfit;
bool           sl;
int            nextTP;
string         TicketName = "GlobalVariableTicketNo";// For storing ticket numbers in global vars for picking up failed part-closes
bool           GlobalVariablesExist=false;
int            NoOfBasketTrades;//Holds the no of basket trades open. Set in CalculateBasketPL()
//int            TrailingStopPipsStore;//Saves the trailing stop pips setting in int init()

int            OldHourlyBars;//Used to tell the manager it is a new candle and prompt it to go looking for orphaned hedge gv's
int            Pips;//For pips target calculation
double         TotalLotsOpen;//Tells the bot if it is hedging one of the two existing original trades
double         MarginLevelPercent;//Used to stop trading when this value falls below FkMinimumMarginPercent

//////////////////////////////////// macman coding
int ThisBarTrade           =  0;
bool ClosingThis =            false;
int MN =                      0;
int OpenTrades =              0;
int NormalizeLots =           1;
////////////////////////////////////

//Matt's O-R stuff
int 	         O_R_Setting_max_retries 	= 10;
double 	      O_R_Setting_sleep_time 		= 4.0; /* seconds */
double 	      O_R_Setting_sleep_max 		= 15.0; /* seconds */

int            BuyOpen, SellOpen;//For calculating trade levels

//############## ADDED BY CACUS
string            String;
int               PairsQty;
string suffix;
string ManagePair[20];
//############## ADDED BY CACUS

//############## ADDED BY CACUS
int PairsQty()
{
   int i = 0;
   int j;
   int qty=0;
   
   while(i > -1)
      {
         i = StringFind(String, ",",j);
         if (i > -1)
         {
            qty ++;
            j = i+1;            
         }
      }
      return(qty);
}
//############## ADDED BY CACUS
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
	//////////////////////////////////// macman coding
	  MN = MagicNumber;
      if(IsTesting() == true) MN = 9999998;
     // Comment("");
    ////////////////////////////////////
		
   
   //Accommodate different quote sizes
   double multiplier;
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   if(Digits == 7) multiplier = 1000;   
   
   TakeProfit*= multiplier;
   BreakEvenPips*= multiplier;
   BreakEvenProfit*= multiplier;
   PipsAwayFromVisualBE*= multiplier;
   JumpingStopPips*= multiplier;
   PipsAwayFromVisualJS*= multiplier;
   TrailingStopPips*= multiplier;
   PipsAwayFromVisualTS*= multiplier;
   StopTrailPips*= multiplier;
   InstantTrailingStopPips*= multiplier;
   FiveDigitIncrement*= multiplier;
   StopInstantTrailPips*= multiplier;
   HiddenStopLossPips*= multiplier;
   TrailAt50Percent*= multiplier;
   TrailAt80Percent*= multiplier;
   MissingStopLossPips*= multiplier;
   MissingTakeProfitPips*= multiplier;
   HiddenTakeProfitPips*= multiplier;
   HedgeAtLossPips*= multiplier;
   //HedgeTheHedgeAtLossPips*= multiplier;   
   HedgingIncrementPips*= multiplier;
   HedgeTradeStopLoss*= multiplier;
   HedgeTradeTakeProfit*= multiplier;
   
   //*= multiplier;
   
   //HedgeTheHedgeAtLossPips/= 2;//No idea why, but the robot keeps on doubling this input, so let's halve it straignt away
   
   if (TradeComment == "") TradeComment = " ";

     return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
      Comment("");
      return(0);
  }
void MonitorTrades()
{

   bool ManageTrade; // tell the program when there is a trade to manage
   
   double spread = MarketInfo(Symbol(), MODE_SPREAD);
   
   string ScreenMessage = NL + NL;
   ScreenMessage=StringConcatenate(ScreenMessage, "                             Spread = ", 
                 spread, ": Buys ", BuyOpen, ": Sells ", SellOpen, ": Margin percent ", MarginLevelPercent, NL);
   
   for (cnt=OrdersTotal() - 1; cnt >= 0; cnt--)
   { 
      if (OrderSelect(cnt, SELECT_BY_POS) )
      {
         
         ManageTrade=false;
         // Set up bid and ask so the program can use them to calculate jumping stops, be's etc
         bid = MarketInfo(OrderSymbol(), MODE_BID);           
         ask = MarketInfo(OrderSymbol(), MODE_ASK);
         point = MarketInfo(OrderSymbol(), MODE_POINT);
         digits = MarketInfo(OrderSymbol(), MODE_DIGITS);
         
                                            
         if (ManageThisPairOnly && OrderSymbol()==Symbol())
         {   
            ManageTrade=true;            
         }
         
         if (ManageThisPairOnly && !OrderSymbol()==Symbol())
         {   
            ManageTrade=false;            
         }
         
         
         
         // Is this trade being managed by the ea?
         if (ManageTrade) ManageTrade(); // The subroutine that calls the other working subroutines
         
      } // Close if (OrderSymbol()==Symbol())
      
   
   } // Close For loop
   
   // Set up some user feedback
   
 	if (ProfitTakeOn) //added by macman
   {
     ScreenMessage = StringConcatenate(ScreenMessage, NL, "Profit taken at ", CloseThisProfitPercent, "%. Loss closed at ", CloseThisLossPercent, "%");
     
   }//if (ProfitTakeOn)  
   
     
   if (HideStopLossEnabled)
   {
     ScreenMessage = StringConcatenate(ScreenMessage, NL, "Hidden stop loss is enabled. Hidden stop = ", HiddenStopLossPips, "pips");
   }//if (HideStopLossEnabled)
   
   if (HideTakeProfitEnabled)
   {
     ScreenMessage = StringConcatenate(ScreenMessage, NL, "Hidden take profit is enabled. Hidden stop = ", HiddenTakeProfitPips, "pips");
   }//if (HideStopLossEnabled)
   
   
   
   if(BreakEven)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Break even set to ", BreakEvenPips, ". BreakEvenProfit is set to ", BreakEvenProfit, " pips");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Break even disabled");
   }
   
   if(JumpingStop==true)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Jumping stop set to ", JumpingStopPips);
      if (JumpAfterBreakevenOnly) ScreenMessage = StringConcatenate(ScreenMessage, " after breakeven is achieved");
      if (HideJumpingStop)  ScreenMessage = StringConcatenate(ScreenMessage, " (HideJumpingStop = true: PipsAwayFromVisualJS = ", PipsAwayFromVisualJS, ")");
      if(AddBEP==true)
      {
         ScreenMessage = StringConcatenate(ScreenMessage, ", also adding BreakEvenProfit (", BreakEvenProfit, " pips)");      
      }
      if (PartCloseEnabled)
      {
         ScreenMessage = StringConcatenate(ScreenMessage, NL, "Trade part-close is enabled. Closing ",Close_Lots, ": Preserving ", Preserve_Lots);
      }
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Jumping stop disabled");
   }
   
   if(TrailingStop==true)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Trailing stop on and set to ", TrailingStopPips);
      if (HideTrailingStop)  ScreenMessage = StringConcatenate(ScreenMessage, " (HideTrailingStop = true: PipsAwayFromVisualTS = ", PipsAwayFromVisualTS, ")");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Trailing stop disabled");
   }
   
   if (InstantTrailingStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Instant trailing stop on and set to ", InstantTrailingStopPips);
      if (StopInstantTrailAfterBreakEven) ScreenMessage = StringConcatenate(ScreenMessage,
            ": Will disable after breakeven");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Instant trailing stop disabled");
   }
//extern int     TrailAt50Percent=20;
//extern int     TrailAt80Percent=10;
   
   if (UseTigheningStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Using the tightening stop feature");
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "          50% = ",TrailAt50Percent," pips: 80% = ", TrailAt80Percent, " pips");
      
   }//if (UseTigheningStop)
      
   if (AddMissingStopLoss)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Adding missing Stop Loss at ", MissingStopLossPips, " pips");      
   }
   
   if (AddMissingTakeProfit)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Adding missing Tske Profit at ", MissingTakeProfitPips, " pips");      
   }
   
   
   
   // HedgeEnabled
   if (HedgeEnabled)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Hedge trade enabled at ", HedgeAtLossPips, " pips loss");
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "       HedgeLotsPercent = ", HedgeLotsPercent,
                                       ": HedgingIncrementPips = ", HedgingIncrementPips, NL, "       HedgeTradeStopLoss = ",HedgeTradeStopLoss,
                                       ": HedgeTradeTakeProfit = ", HedgeTradeTakeProfit);
      if (CloseAtBreakEven) ScreenMessage = StringConcatenate(ScreenMessage, ": Closing hedged pair at breakeven");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Hedge trade not enabled");
   }
         
   
   Comment(ScreenMessage); // User feedback
   
   
   
} // end of MonitorTrades

void DeleteOrphanHedgeGVs()
{
   //Called at the start of each day, or on loadup. Deletes orphan hedge gv's
   for (int cc = GlobalVariablesTotal() - 1; cc >=0; cc--)
   {
      string vname = GlobalVariableName(cc);
      int tnum = StrToDouble(vname);
      if (tnum > 0) //Is a ticket number
      {
         if (!OrderSelect(tnum, SELECT_BY_TICKET) || OrdersTotal() == 0 )
         {
            GlobalVariableDel(vname);
            cc++;
         }//if (!OrderSelect(tnum, SELECT_BY_TICKET) )
         
      }//if (tnum > 0)
      
   
   }//for (int cc = GlobalVariablesTotal() - 1; cc >=0; cc--)
   

}//End void DeleteOrphanHedgeGVs()

//////////////////////////////////// macman coding
void EvaluateCloseThis()
{
   double pips =0.0, lots = 0.0;
   for(int i = 0; i < OrdersTotal(); i++) {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if(OrderMagicNumber() == MN && OrderSymbol() == Symbol()) {
         pips += OrderProfit()+OrderCommission()+OrderSwap() ;
         lots += OrderLots();
      }
   }
   if (lots == 0.0) return;
   if (pips  >= AccountBalance() * (CloseThisProfitPercent/100.0) || pips <= -AccountBalance() * (CloseThisLossPercent/100.0)) {
      ClosingThis = true; 
      CloseThis();
      // lPrevPosition = 0; 
      OpenTrades =0;
      ClosingThis = false;
   }
   return;
}

// this closes for this symbol using the MagicNumber
void CloseThis()
{
   bool closed = false;
   int retries =0;
   int OrdersThis =0;
   while (true) {
      OrdersThis =0;
      for(int i = 0; i < OrdersTotal(); i++) {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

         if (OrderMagicNumber() == MN && OrderSymbol() == Symbol() ) {
             if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
               OrdersThis += 1;
               while(IsTradeContextBusy()) Sleep(100);
               RefreshRates();
               if(OrderType() == OP_BUY) {
                  closed = OrderClose( OrderTicket(),OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),Digits),Slippage * NormalizeLots,White);
                  Print(Symbol(), " CloseThis Buy order # ", i, " ", NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),MarketInfo(OrderSymbol(),MODE_DIGITS)));
               }
               if(OrderType() == OP_SELL) {
                  closed = OrderClose( OrderTicket(),OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),Digits),Slippage * NormalizeLots,White);
                  Print(Symbol(), " CloseThis Sell order # ", i, " ", NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),MarketInfo(OrderSymbol(),MODE_DIGITS)));
               }
               
            }
         }
      }
      if (closed == false) retries = retries +1;
      if(OrdersThis <= 0 || retries > 1  ) break;
      closed = false;
   }
}
////////////////////////////////////


void BreakEvenStopLoss() // Move stop loss to breakeven
{

   //Check hidden BE for trade closure
   if (HideBreakEvenStop)
   {
      bool TradeClosed = CheckForHiddenStopLossHit(OrderType(), PipsAwayFromVisualBE, OrderStopLoss() );
      if (TradeClosed) return;//Trade has closed, so nothing else to do
   }//if (HideBreakEvenStop)


   bool result;

           
   if (OrderType()==OP_BUY)
         {
            if (bid >= OrderOpenPrice () + (point*BreakEvenPips) && 
                OrderStopLoss()<OrderOpenPrice())
            {
               result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+(BreakEvenProfit*point),OrderTakeProfit(),0,CLR_NONE);
               if (result && ShowAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               if (!result)
               {
                  int err=GetLastError();
                  if (ShowAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
                  Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
               }//if !result && ShowAlerts)      
               if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               {
                  bool PartCloseSuccess = PartCloseTradeFunction();
                  if (!PartCloseSuccess) SetAGlobalTicketVariable();
               }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }
   	   }               			         
          
   if (OrderType()==OP_SELL)
         {
           if (ask <= OrderOpenPrice() - (point*BreakEvenPips) &&
              (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0)) 
            {
               result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-(BreakEvenProfit*point),OrderTakeProfit(),0,CLR_NONE);
               if (result && ShowAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               if (!result && ShowAlerts)
               {
                  err=GetLastError();
                  if (ShowAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
                  Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
               }//if !result && ShowAlerts)      
              if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               {
                  PartCloseSuccess = PartCloseTradeFunction();
                  if (!PartCloseSuccess) SetAGlobalTicketVariable();
               }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }    
         }
      

} // End BreakevenStopLoss sub


bool PartCloseTradeFunction()
   {
      // Called when any attempt to part-close a long trade is needed.
      // Trade has already been selected 
      // Returns 'true' if succeeds, else false, after setting a global variable to tell
      // the basket monitoring function that a closure failed and needs to be attempted
      // again.
      
      double price;
      if (OrderType()==OP_BUY) price = bid;
      if (OrderType()==OP_SELL) price = ask;
      
            
      bool result=OrderClose(OrderTicket(), Close_Lots, price, 5, CLR_NONE);
      if (result)
      {
         if (ShowAlerts==true) Alert("Partial close of ", OrderSymbol(), " ticket no ", OrderTicket());
         return(true);
      }
      else
      {
         int err=GetLastError();
         if (ShowAlerts==true) Alert("Partial close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         Print("Partial close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         return(false);
      }                          
   
}// End bool PartCloseTradeFunction()
   
int GetNextAvailableVariableNumber()
   {
      // Called from the SetAGlobalTicketVariable() function.
      // Returns the first integer available.
      // The globla variable name consists of "GlobalVariableTicketNo" (stored in the 
      // string TicketName) and an integer.
            
      if (GlobalVariablesTotal()==0) return(1);
      
      for (int cc=1; cc > -1; cc++)
      {
         string ThisGlobalName = StringConcatenate(TicketName,DoubleToStr(cc,0));
         double v1 = GlobalVariableGet(ThisGlobalName);
         if(v1==0) return(cc);
         if (cc>100) return;
      }
      
   }//int GetNextAvailableVariableNumber()   
   
void SetAGlobalTicketVariable()
   {
      // Called whenever an attempt to part-close a trade fails.
      // This function finds the first available global variable name and sets up 
      // a gv with the ticket number of the offending trade. These gv's will consist of
      // the string TicketName ("GlobalVariableTicketNo") and an integer
      int cc = GetNextAvailableVariableNumber();
      string GlobalName=StringConcatenate(TicketName,DoubleToStr(cc,0));
      GlobalVariableSet(GlobalName, OrderTicket());
      GlobalVariablesExist=true;
      
   } // End void SetAGlobalTicketVariable();
   
bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
{
   //Reusable code that can be called by any of the stop loss manipulation routines except HiddenStopLoss().
   //Checks to see if the market has hit the hidden sl and attempts to close the trade if so. 
   //Returns true if trade closure is successful, else returns false
   
   //Check buy trade
   if (type == OP_BUY)
   {
      double sl = NormalizeDouble(stop + (iPipsAboveVisual * point), digits);
      if (bid <= sl)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (bid <= sl)  
   }//if (type = OP_BUY)
   
   //Check buy trade
   if (type == OP_SELL)
   {
      sl = NormalizeDouble(stop - (iPipsAboveVisual * point), digits);
      if (ask >= sl)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (ask >= sl)  
   }//if (type = OP_SELL)
   
   return(result);


}//End bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )

   
void JumpingStopLoss() 
{
   // Jump sl by pips and at intervals chosen by user .
   // Also carry out partial closure if the user requires this

   // Abort the routine if JumpAfterBreakevenOnly is set to true and be sl is not yet set
   if (JumpAfterBreakevenOnly && OrderType()==OP_BUY)
   {
      if(OrderStopLoss()<OrderOpenPrice()) return(0);
   }
  
   if (JumpAfterBreakevenOnly && OrderType()==OP_SELL)
   {
      if(OrderStopLoss()>OrderOpenPrice()) return(0);
   }
  
   //Is this trade a hedge trade?
   if (!AllowTrailingJumpingStops)
   {
      int index = StringFind(OrderComment(), "Hedge ");
      if (index > -1) return;
   }//if (!AllowTrailingJumpingStops)

   double sl=OrderStopLoss(); //Stop loss

   if (OrderType()==OP_BUY)
   {
      //Check hidden js for trade closure
      if (HideJumpingStop)
      {
         bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualJS, OrderStopLoss() );
         if (TradeClosed) return;//Trade has closed, so nothing else to do
      }//if (HideJumpingStop)
      
      // First check if sl needs setting to breakeven
      if (sl==0 || sl<OrderOpenPrice())
      {
         if (ask >= OrderOpenPrice() + (JumpingStopPips*point))
         {
            sl=OrderOpenPrice();
            if (AddBEP==true) sl=sl+(BreakEvenProfit*point); // If user wants to add a profit to the break even
            bool result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               if (ShowAlerts==true) Alert("Jumping stop set at breakeven ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
               if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               {
                  bool PartCloseSuccess = PartCloseTradeFunction();
                  if (!PartCloseSuccess) SetAGlobalTicketVariable();
               }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }//if (result)
            if (!result)
            {
               int err=GetLastError();
               if (ShowAlerts) Alert(OrderSymbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(OrderSymbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            return(0);
         }//if (ask >= OrderOpenPrice() + (JumpingStopPips*point))
      } //close if (sl==0 || sl<OrderOpenPrice()

  
      // Increment sl by sl + JumpingStopPips.
      // This will happen when market price >= (sl + JumpingStopPips)
      if (bid>= sl + ((JumpingStopPips*2)*point) && sl>= OrderOpenPrice())      
      {
         sl=sl+(JumpingStopPips*point);
         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
            if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
            {
               PartCloseSuccess = PartCloseTradeFunction();
               if (!PartCloseSuccess) SetAGlobalTicketVariable();
            }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
         }//if (result)
         if (!result)
         {
            err=GetLastError();
            if (ShowAlerts) Alert(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
            Print(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)
             
      }// if (bid>= sl + (JumpingStopPips*point) && sl>= OrderOpenPrice())      
   }//if (OrderType()==OP_BUY)
   
   if (OrderType()==OP_SELL)
   {
      //Check hidden js for trade closure
      if (HideJumpingStop)
      {
         TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualJS, OrderStopLoss() );
         if (TradeClosed) return;//Trade has closed, so nothing else to do
      }//if (HideJumpingStop)
            
      // First check if sl needs setting to breakeven
      if (sl==0 || sl>OrderOpenPrice())
      {
         if (ask <= OrderOpenPrice() - (JumpingStopPips*point))
         {
            sl = OrderOpenPrice();
            if (AddBEP==true) sl=sl-(BreakEvenProfit*point); // If user wants to add a profit to the break even
            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               {
                  PartCloseSuccess = PartCloseTradeFunction();
                  if (!PartCloseSuccess) SetAGlobalTicketVariable();
               }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }//if (result)
            if (!result)
            {
               err=GetLastError();
               if (ShowAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            return(0);
         }//if (ask <= OrderOpenPrice() - (JumpingStopPips*point))
      } // if (sl==0 || sl>OrderOpenPrice()
   
      // Decrement sl by sl - JumpingStopPips.
      // This will happen when market price <= (sl - JumpingStopPips)
      if (bid<= sl - ((JumpingStopPips*2)*point) && sl<= OrderOpenPrice())      
      {
         sl=sl-(JumpingStopPips*point);
         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
            if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
            {
               PartCloseSuccess = PartCloseTradeFunction();
               if (!PartCloseSuccess) SetAGlobalTicketVariable();
            }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
         }//if (result)          
         if (!result)
         {
            err=GetLastError();
            if (ShowAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
            Print(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)

      }// close if (bid>= sl + (JumpingStopPips*point) && sl>= OrderOpenPrice())         
   }//if (OrderType()==OP_SELL)

} //End of JumpingStopLoss sub

void TrailingStopLoss()
{
      if (TrailAfterBreakevenOnly && OrderType()==OP_BUY)
      {
         if(OrderStopLoss()<OrderOpenPrice()) return(0);
      }
     
      if (TrailAfterBreakevenOnly && OrderType()==OP_SELL)
      {
         if(OrderStopLoss()>OrderOpenPrice()) return(0);
      }
     
   //Is this trade a hedge trade?
   if (!AllowTrailingJumpingStops)
   {
      int index = StringFind(OrderComment(), "Hedge ");
      if (index > -1) return;
   }//if (!AllowTrailingJumpingStops)
   
   
   bool result;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
         if (HideTrailingStop)
         {
            bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualTS, OrderStopLoss() );
            if (TradeClosed) return;//Trade has closed, so nothing else to do
         }//if (HideJumpingStop)
		   
		   if (bid >= OrderOpenPrice() + (TrailingStopPips*point))
		   {
		       if (OrderStopLoss() == 0) sl = OrderOpenPrice();
		       if (bid > sl +  (TrailingStopPips*point))
		       {
		          sl= bid - (TrailingStopPips*point);
		          // Exit routine if user has chosen StopTrailAtPipsProfit and
		          // sl is past the profit point already
		          if (StopTrailAtPipsProfit && sl>= OrderOpenPrice() + (StopTrailPips*point)) return;
		          result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (result)
               {
                  Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
               }//if (result) 
               else
               {
                  int err=GetLastError();
                  Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err));
               }//else
   
		       }//if (bid > sl +  (TrailingStopPips*point))
		   }//if (bid >= OrderOpenPrice() + (TrailingStopPips*point))
      }//if (OrderType()==OP_BUY) 

      if (OrderType()==OP_SELL) 
      {
		   if (ask <= OrderOpenPrice() - (TrailingStopPips*point))
		   {
             if (HideTrailingStop)
             {
                TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualTS, OrderStopLoss() );
                if (TradeClosed) return;//Trade has closed, so nothing else to do
             }//if (HideJumpingStop)
		   
		       if (OrderStopLoss() == 0) sl = OrderOpenPrice();
		       if (ask < sl -  (TrailingStopPips*point))
		       {
	               sl= ask + (TrailingStopPips*point);
  	               // Exit routine if user has chosen StopTrailAtPipsProfit and
		            // sl is past the profit point already
		            if (StopTrailAtPipsProfit && sl<= OrderOpenPrice() - (StopTrailPips*point)) return;
		            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
                  if (result)
                  {
                     Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", bid);
                  }//if (result)
                  else
                  {
                     err=GetLastError();
                     if (PrintToJournal) Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err));
                  }//else
    
		       }//if (ask < sl -  (TrailingStopPips*point))
		   }//if (ask <= OrderOpenPrice() - (TrailingStopPips*point))
      }//if (OrderType()==OP_SELL) 

      //TrailingStopPips = TrailingStopPipsStore;
      
} // End of TrailingStopLoss sub
   
void InstantTrailingStopLoss()
/* This is the same as TrailingStopLoss, except that it moves the sl as soon as
 the market moves ion favour of the trade. 
 It will set an initial sl of market price +- InstantTrailingStopPips, depending on the type of trade,
 then move it every time the market moves in favour of the trade. It will therefore override
 any user set sl on the trade.
 Market price +- InstantTrailingStopPips will result in breakeven, and move into profit after that.
*/ 
{
   bool result;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
		   if (bid >= sl+((InstantTrailingStopPips*point) + (FiveDigitIncrement * point))) // Has to overcome the spread first
		   {
	         sl= bid - NormalizeDouble(((InstantTrailingStopPips*point) + (FiveDigitIncrement * point)),digits);
	         if (sl <= OrderStopLoss()) return(0);
	         if (StopInstantTrailAfterBreakEven && sl>OrderOpenPrice()) return(0); // cancel instant trail after breakeven
	         // Exit routine if user has chosen StopTrailAtPipsProfit and
            // sl is past the profit point already
            if (StopInstantTrailAtPipsProfit && sl>= OrderOpenPrice() + (StopInstantTrailPips*point)) return;
		          
	         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               Print("Instant trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
            } 
		       return;
		    }//if (bid >= sl+((InstantTrailingStopPips*point) + (FiveDigitIncrement * point))) // Has to overcome the spread first
      }//if (OrderType()==OP_BUY)

      if (OrderType()==OP_SELL) 
      {
	       if ((ask <= sl - ((InstantTrailingStopPips*point) - (FiveDigitIncrement * point))) || sl==0)
	       {
	            sl= ask + NormalizeDouble(((InstantTrailingStopPips*point)) - (FiveDigitIncrement * point),digits);
   	         if (StopInstantTrailAfterBreakEven && sl<OrderOpenPrice()) return(0); // cancel instant trail after breakeven
               // Exit routine if user has chosen StopTrailAtPipsProfit and
	            // sl is past the profit point already
	            if (StopInstantTrailAtPipsProfit && sl<= OrderOpenPrice() - (StopInstantTrailPips*point)) return;
	            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (result)
               {
                  if (PrintToJournal) Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", bid);
               } 
               return;   
	       }//if ((ask <= sl - ((InstantTrailingStopPips*point) - (FiveDigitIncrement * point))) || sl==0)		   
      }//if (OrderType()==OP_SELL) 


} // End of InstantTrailingStopLoss() sub
   
/*
int CalculatePipsProfit()
{
   //Returns the pip value of the current position
   if (OrdersTotal() == 0) return(0);
   
   int multiplier, divisor;
   double pips;
   int pipstotal;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderCloseTime() > 0) continue;
      if (MarketInfo(OrderSymbol(), MODE_DIGITS)== 2) {multiplier = 100; divisor = 1;}
      if (MarketInfo(OrderSymbol(), MODE_DIGITS)== 3) {multiplier = 1000; divisor = 10;}
      if (MarketInfo(OrderSymbol(), MODE_DIGITS)== 4) {multiplier = 10000; divisor = 1;}
      if (MarketInfo(OrderSymbol(), MODE_DIGITS)== 5) {multiplier = 100000; divisor = 10;}
      if (MarketInfo(OrderSymbol(), MODE_DIGITS)== 6) {multiplier = 1000000; divisor = 100;}//Not tested this one
      
      
      
      if (OrderType() == OP_BUY) pips = (MarketInfo(OrderSymbol(), MODE_BID) - OrderOpenPrice()) * multiplier;
      if (OrderType() == OP_SELL) pips = (OrderOpenPrice() - MarketInfo(OrderSymbol(), MODE_ASK)) * multiplier;
      
      if (OrderType() == OP_BUY || OrderType() == OP_SELL) pipstotal+= pips;      
   }//for (int cc = 0; cc < OrdersHistoryTotal(); cc++)
   
   //pipstotal/= divisor;
   return(pipstotal);
   //ScreenMessage = StringConcatenate("      ", Pips, " pips");
   //Comment(ScreenMessage);

}//int CalculatePipsProfit()
*/

/*bool ExtractPartCloseVariables()
{
   
   This routine extracts the targets at which PartCloseOrder closes part of a position.
   Also tells PartCloseOrder whether the pair is enabled for part-closure.
   Written as a separate function because it is huge, so avoids clutter in PartCloseOrder
   
   
   bool PairEnabled=false;
   
   if (OrderSymbol()=="EURUSD" || OrderSymbol()=="EURUSDm") 
   {
      TargetAsPrice=EUTargetPrice;
      TargetAsPips=EUTargetPips;
      if(EU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="GBPUSD" || OrderSymbol()=="GBPUSDm") 
   {
      TargetAsPrice=GUTargetPrice;
      TargetAsPips=GUTargetPips;
      if(GU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="USDJPY" || OrderSymbol()=="USDJPYm") 
   {
      TargetAsPrice=UJTargetPrice;
      TargetAsPips=UJTargetPips;
      if(UJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="USDCHF" || OrderSymbol()=="USDCHFm") 
   {
      TargetAsPrice=UCTargetPrice;
      TargetAsPips=UCTargetPips;
      if(UC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="USDCAD" || OrderSymbol()=="USDCADm") 
   {
      TargetAsPrice=UCadTargetPrice;
      TargetAsPips=UCadTargetPips;
      if(UCad) PairEnabled=true;
   }
      
   if (OrderSymbol()=="AUDUSD" || OrderSymbol()=="AUDUSDm") 
   {
      TargetAsPrice=AUTargetPrice;
      TargetAsPips=AUTargetPips;
      if(AU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="NZDUSD" || OrderSymbol()=="NZDUSDm") 
   {
      TargetAsPrice=NUTargetPrice;
      TargetAsPips=NUTargetPips;
      if(NU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURGBP" || OrderSymbol()=="EURGBPm") 
   {
      TargetAsPrice=EGTargetPrice;
      TargetAsPips=EGTargetPips;
      if(EG) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURJPY" || OrderSymbol()=="EURJPYm") 
   {
      TargetAsPrice=EJTargetPrice;
      TargetAsPips=EJTargetPips;
      if(EJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURCHF" || OrderSymbol()=="EURCHFm") 
   {
      TargetAsPrice=ECTargetPrice;
      TargetAsPips=ECTargetPips;
      if(EC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="GBPJPY" || OrderSymbol()=="GBPJPYm") 
   {
      TargetAsPrice=GJTargetPrice;
      TargetAsPips=GJTargetPips;
      if(GJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="GBPCHF" || OrderSymbol()=="GBPCHFm") 
   {
      TargetAsPrice=GCTargetPrice;
      TargetAsPips=GCTargetPips;
      if(GC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="AUDJPY" || OrderSymbol()=="AUDJPYm") 
   {
      TargetAsPrice=AJTargetPrice;
      TargetAsPips=AJTargetPips;
      if(AJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="CHFJPY" || OrderSymbol()=="CHFJPYm") 
   {
      TargetAsPrice=CJTargetPrice;
      TargetAsPips=CJTargetPips;
      if(CJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURCAD" || OrderSymbol()=="EURCADm") 
   {
      TargetAsPrice=ECadTargetPrice;
      TargetAsPips=ECadTargetPips;
      if(ECad) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURAUD" || OrderSymbol()=="EURAUDm") 
   {
      TargetAsPrice=EATargetPrice;
      TargetAsPips=EATargetPips;
      if(EA) PairEnabled=true;
   }

   if (OrderSymbol()=="AUDCAD" || OrderSymbol()=="AUDCADm") 
   {
      TargetAsPrice=ACTargetPrice;
      TargetAsPips=ACTargetPips;
      if(AC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="AUDNZD" || OrderSymbol()=="AUDNZDm") 
   {
      TargetAsPrice=ANTargetPrice;
      TargetAsPips=ANTargetPips;
      if(AN) PairEnabled=true;
   }
      
   if (OrderSymbol()=="NZDJPY" || OrderSymbol()=="NZDJPYm") 
   {
      TargetAsPrice=NJTargetPrice;
      TargetAsPips=NJTargetPips;
      if(NJ) PairEnabled=true;
   }
      

   return (PairEnabled);

} // End ExtractPartCloseVariables 
*/


/*void PartCloseOrder()
{
            
///////////////////////////////////////////////////////////////////////////////////////////
// Previous code. Keot just in case
   int index=StringFind(OrderComment(), "split from");
   if (index>-1) return(0); // Order already part-closed
   // Extract the external part-close variables for this pairing.Put this into 
   //a separate routine to avoid clutter here. Ascertain if this pair is 
   // enabled for partial closure. 
   TargetAsPrice=0;
   TargetAsPips=0;
   bool PairEnabled=ExtractPartCloseVariables();   
   if (!PairEnabled) return(0); // Not wanted on this pair
   if(TargetAsPrice==0 && TargetAsPips==0) return(0); // User entry error

   // Got this far, so pair is enabled, trade is not already split and no user errors, so continue
   int ticket;
   double ProfitTarget;
   double LotsToClose=OrderLots()/2;
   if(!TargetAsPrice==0) ProfitTarget=TargetAsPrice;
   
            
   if (OrderType()==OP_BUY)
   {
      if(TargetAsPips>0) ProfitTarget=NormalizeDouble(OrderOpenPrice()+(TargetAsPips*point),digits);
      if (bid>=ProfitTarget)
      {         
         ticket=OrderClose(OrderTicket(), LotsToClose,bid,3,CLR_NONE);
         if (ticket>0)
         {
            if(ShowAlerts) Alert("Partial closure on ", OrderSymbol(), ": ticket no ",OrderTicket());
         } 

      }
   }
   
   if (OrderType()==OP_SELL)
   {
      if(TargetAsPips>0) ProfitTarget=NormalizeDouble(OrderOpenPrice()-(TargetAsPips*point),digits);
      if (ask<=ProfitTarget)
      {         
         ticket=OrderClose(OrderTicket(), LotsToClose,ask,3,CLR_NONE);
         if (ticket>0)
         {
            if(ShowAlerts) Alert("Partial closure on ", OrderSymbol(), ": ticket no ",OrderTicket());
         
         } 

      }
         
   }

//////////////////////////////////////////////////////////////////////////////////////////////////////
   
} // End of PartCloseOrder()*/

bool CheckForExistingHedge()
{
   int index;
   double ticketno=OrderTicket();
   string StringTicketNo=DoubleToStr(OrderTicket(),0);
   for (int cc=OrdersTotal() - 1; cc >+ 0; cc--)
   {
      OrderSelect(cc, SELECT_BY_POS);
      index=StringFind(OrderComment(),StringTicketNo);
      if (index>-1) return(true);
   }

   return(false);
   
} //End CheckForExistingHedge

bool AreHedgeAndOriginalAtBreakeven(int TempTicket)
{
   // The OrderSelect trade is a hedge, so extract the ticket number it is hedging
   string sComment=StringSubstr(OrderComment(),6);
   int TicketNo=StrToInteger(sComment);
   // Calculate to profit of the scalp and hedge trades
   double Profit=(OrderProfit() + OrderSwap());
   int levels = BuyOpen + SellOpen;
   if (TotalLotsOpen == Lot * 2) levels-= 1;//If both original trades are still open, then we are only at L1 
   double target= CashProfitPerBreakEvenPip * levels;
   
   OrderSelect(TicketNo,SELECT_BY_TICKET);
   Profit = Profit + (OrderProfit() + OrderSwap());
   // Delete the trade if be has been reached
   if (Profit>=target && CloseAtBreakEven)
   {
      int ordertype=OrderType();
      int result; 
      switch(ordertype)
      {
      //Close opened long positions
      case OP_BUY  : result = OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),1000,CLR_NONE);                     
       
      //Close opened short positions
      case OP_SELL : result = OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),1000,CLR_NONE);
                 
      }
      return(true);
   }
   else return(false);
   
}//AreHedgeAndOriginalAtBreakeven()



void HedgeTrade()
{
   if(HedgeAtLossPips==0) return(0); //Silly user choice
   
   // Check that order is not already hedged
   int TempTicket = OrderTicket(); // Temporary store for selected order ticket no
   int index; // If OrderComment includes "Hedge ";
   int HedgeTicket; // For ticket number of hedge trade
   bool BreakevenAchieved=false;
   
   
   
   // Is this trade a hedge trade?
   index = StringFind(OrderComment(), "Hedge ");
   if (index > -1) 
   {
      BreakevenAchieved=AreHedgeAndOriginalAtBreakeven(TempTicket); // The called function closes the original order if be is achieved
      if (BreakevenAchieved && CloseAtBreakEven)
      {
         OrderSelect(TempTicket, SELECT_BY_TICKET); //Re-select the current order               
         int ordertype=OrderType();
         int result; 
         switch(ordertype)
         {
            //Close opened long positions
            case OP_BUY  : result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),10,CLR_NONE);
                           break;

            //Close opened short positions
            case OP_SELL : result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),10,CLR_NONE);
        
        }
        return; // Let's do any more processing on the next tick. This is getting complicated
     }// close if (BreakevenAchieved && CloseAtBreakEven)
     else
     {   
         
         OrderSelect(TempTicket, SELECT_BY_TICKET); //Re-select the current order
         if (!HedgingTheHedgeIsAllowed) return;//Trade is already a hedge, so no further action needed if hedging hedges is not allowed
     }   
      
   }// Close if (index > -1) 
   
   bool HedgeOpen = CheckForExistingHedge();
   //If there is no hedge open, the trade is not itself a hedge trade, and is in upl loss, and has no tp, 
   //then it will need one.
   //If it has already been hedged and the hedge has itself closed
         
   if (!HedgeOpen && index == -1 && OrderProfit() < 0 && OrderTakeProfit() == 0 && OrdersHistoryTotal() > 0)
   {
      //Cycle through the history trades to find a closed hedge trade for this ticket
      for (int cc = OrdersHistoryTotal() - 1; cc >= 0; cc--)
      {
         string tick = DoubleToStr(TempTicket,0);
         OrderSelect(cc, SELECT_BY_POS, MODE_HISTORY);
         index = StringFind(OrderComment(), tick);
         if (index > -1) //A closed hedge trade
         {
            OrderSelect(TempTicket, SELECT_BY_TICKET);//Re-select the current order
            if (OrderTakeProfit() == 0)
            {
               result = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), OrderOpenPrice(), OrderExpiration(), CLR_NONE);
               if (!result)
               {
                  int err=GetLastError();
                  Alert(OrderTicket(), " TP move to BE failed with error(",err,"): ",ErrorDescription(err));
                  if (PrintToJournal) Print(OrderTicket(), " TP move to BE failed with error(",err,"): ",ErrorDescription(err));
               }//if (!result)
            }//if (OrderTakeProfit() == 0)
            break;
         }//if (index > -1) 
      }//for (cc = OrdersHistoryTotal() - 1; cc >= 0; cc--)
      
   }//if (!HedgeOpen && index == -1 && OrderProfit() < 0 && OrderTakeProfit() == 0 && OrdersHistoryTotal() > 0)
   OrderSelect(TempTicket, SELECT_BY_TICKET);//Re-select the current order
   
   
   // Does this order need hedging?
   string tn = DoubleToStr(TempTicket,0);
   double HedgePrice; 
   double NextHedge = GlobalVariableGet(tn);
   if (OrderType()==OP_BUY)
   {
      HedgePrice=NormalizeDouble(OrderOpenPrice()-(NextHedge * point),digits);
      if (ask >= HedgePrice) return; // Trade not failing sufficiently to need hedging
   }   

   if (OrderType()==OP_SELL)
   {
      HedgePrice=NormalizeDouble(OrderOpenPrice()+(NextHedge * point),digits);
      if (bid <= HedgePrice) return; // Trade not failing sufficiently to need hedging
    }
   

      
   // Got this far, so the trade needs a hedge.
   // Is it already hedged? CheckForExistingHedge returns true if so, false if not
   if (HedgeOpen)
   {
      OrderSelect(TempTicket, SELECT_BY_TICKET); //Re-select the current order
      return;
   }
   OrderSelect(TempTicket, SELECT_BY_TICKET);//Re-select the current order


   // Got this far, so send the hedge order.
   // Check trend direction first

   //Margin level check
   if (AccountMargin() > 0)
   {
      MarginLevelPercent = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2);
      if (MarginLevelPercent < FkMinimumMarginPercent)
      {      
         return;
      }//if (MarginLevelPercent < FkMinimumMarginPercent)
   }//if (AccountMargin() > 0)
   

   TrendUp=true;
   TrendDown=true;
   DetermineTrendDirection(OrderSymbol());
   bool AllowTrade=true;
   double takeprofit=0;
   double stoploss=0;
   int ticket;
   double Lots=OrderLots();
   
   //Make sure that there are not too many decimal plases in the result of the calculation
   double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   int decimals;
   if (LotStep >0 && LotStep < 0.1) decimals = 2;//0.01
   if (LotStep >0.09 && LotStep < 1) decimals = 1;//0.1
   if (LotStep >0.9) decimals = 0;//1
   
   if(HedgeEnabled && HedgeLotsPercent>0) Lots=NormalizeDouble(Lots * (HedgeLotsPercent / 100), decimals);
   
   // Is this trade a hedge trade re-check? Lots may need adjusting if so
   index = StringFind(OrderComment(), "Hedge ");
   //if (index > -1) Lots=NormalizeDouble(OrderLots() * (HedgeTheHedgeLotsPercent / 100), decimals);
   if (index > -1) Lots=NormalizeDouble(OrderLots() * (HedgeLotsPercent / 100), decimals);
   
   int error;
   
   if (OrderType()==OP_BUY)
   {
      if(!HedgeTradeTakeProfit==0) takeprofit=NormalizeDouble(bid-(HedgeTradeTakeProfit*point),digits);
      
      if(!HedgeTradeStopLoss==0) stoploss=NormalizeDouble(ask+(HedgeTradeStopLoss*point),digits); 
      
      if(UseEnvelopeTrendFilter || UseAdxTrendFilter || UseCandleDirection)
      {
         if (!TrendUp && !TrendDown) return;// No trend, so no hedge   
         if(!TrendDown) AllowTrade=false;
      }
      if (AllowTrade)
      {
         ticket=OrderSend(OrderSymbol(),OP_SELL,Lots,MarketInfo(OrderSymbol(),MODE_BID),0,stoploss,takeprofit,"Hedge " + OrderTicket(),MagicNumber,0,CLR_NONE);
         if (ticket>0)
         {
            if(ShowAlerts) Alert("Sell hedge trade set for ", OrderSymbol(), " buy");
            //if (!HedgingTheHedgeIsAllowed) NextHedge+= (HedgingIncrementPips);
            //if (HedgingTheHedgeIsAllowed) NextHedge+= (HedgeTheHedgeAtLossPips);
            NextHedge+= (HedgingIncrementPips);
            
            GlobalVariableSet(tn, NextHedge);
            //Reselect the original trade and set the sl to 0
            OrderSelect(TempTicket, SELECT_BY_TICKET);
            if (OrderStopLoss() != 0 || OrderTakeProfit() != 0)
            {
               result = OrderModify(OrderTicket(), OrderOpenPrice(), 0, 0, OrderExpiration(), CLR_NONE);
               if (!result)
               {
                  err=GetLastError();
                  Alert(OrderTicket(), " SL move to 0 failed with error(",err,"): ",ErrorDescription(err));
                  Print(OrderTicket(), " SL move to 0 failed with error(",err,"): ",ErrorDescription(err));
               }//if (!result)
            }//if (OrderStopLoss() != 0 || OrderTakeProfit() != 0)
            
         }//if (ticket>0) 
         else
         {
            error=GetLastError();
            Print("Error = ",ErrorDescription(error));
            return;
         }
      }      
   }

if (OrderType()==OP_SELL)
   {
      if(!HedgeTradeTakeProfit==0) takeprofit=NormalizeDouble(ask+(HedgeTradeTakeProfit*point),digits);
      
      if(!HedgeTradeStopLoss==0) stoploss=NormalizeDouble(bid-(HedgeTradeStopLoss*point),digits); 
      
      if(UseEnvelopeTrendFilter || UseAdxTrendFilter || UseCandleDirection)
      {
         if (!TrendUp && !TrendDown) return;// No trend, so no hedge   
         if(!TrendUp) AllowTrade=false;
      }
      if (AllowTrade)
      {      
         ticket=OrderSend(OrderSymbol(),OP_BUY,Lots,MarketInfo(OrderSymbol(),MODE_ASK),0,stoploss,takeprofit,"Hedge " + OrderTicket(),MagicNumber,0,CLR_NONE);
         if (ticket>0)
         {
            if(ShowAlerts) Alert("Buy hedge trade set for ", OrderSymbol(), " sell");
            //if (!HedgingTheHedgeIsAllowed) NextHedge+= (HedgingIncrementPips);
            //if (HedgingTheHedgeIsAllowed) NextHedge+= (HedgeTheHedgeAtLossPips);
            NextHedge+= (HedgingIncrementPips);

            GlobalVariableSet(tn, NextHedge);
            //Reselect the original trade and set the sl to 0
            OrderSelect(TempTicket, SELECT_BY_TICKET);
            if (OrderStopLoss() != 0 || OrderTakeProfit() != 0)
            {
               result = OrderModify(OrderTicket(), OrderOpenPrice(), 0, 0, OrderExpiration(), CLR_NONE);
               if (!result)
               {
                  err=GetLastError();
                  Alert(OrderTicket(), " SL move to 0 failed with error(",err,"): ",ErrorDescription(err));
                  Print(OrderTicket(), " SL move to 0 failed with error(",err,"): ",ErrorDescription(err));
               }//if (!result)
            }//if (OrderStopLoss() != 0 || OrderTakeProfit() != 0)
         }//if (ticket>0) 
         else
         {
            error=GetLastError();
            Print("Error = ",ErrorDescription(error));
            return;
         }
      }
   }

} // End of HedgeTrade()

void DetermineTrendDirection(string symbol)
   {
      // Envelope trend filter
      if(UseEnvelopeTrendFilter)
      {
         if (LookBackBars==0) return;
         int BarCounter=iBars(OrderSymbol(), PERIOD_H1);
         double HigherBand, LowerBand, ClosePrice;
         string message;
         int shift=1;
         for (int i=BarCounter; i>BarCounter-LookBackBars; i--)
         {
            HigherBand=iEnvelopes(OrderSymbol(), 0, 64, MODE_LWMA,0,PRICE_CLOSE,0.05, MODE_UPPER,shift);
            LowerBand=iEnvelopes(OrderSymbol(), 0, 64, MODE_LWMA,0,PRICE_CLOSE,0.05, MODE_LOWER,shift);
            ClosePrice=iClose(OrderSymbol(), 0,shift);
            if (ClosePrice < HigherBand) TrendUp=false;
            if (ClosePrice > LowerBand) TrendDown=false;
            if (!TrendDown && !TrendUp) return; // No discernible trend, so nothing to do
            shift++;
         }//for
      }//if   
   
      //Trend determination using ADX
      if (UseAdxTrendFilter)
      {
         double AdxMain = iADX(OrderSymbol(),0,AdxPeriod,PRICE_CLOSE,MODE_MAIN,0);
         double PlusDI = iADX(OrderSymbol(),0,AdxPeriod,PRICE_CLOSE,MODE_PLUSDI,0);
         double MinusDI= iADX(OrderSymbol(),0,AdxPeriod,PRICE_CLOSE,MODE_MINUSDI,0);
      
         // Up trend
         if (PlusDI > MinusDI) TrendDown=false;
         // Down trend
         if (MinusDI > PlusDI) TrendUp=false;
         // Does ADX main line confirm the trend
         if (AdxMain < 20)
         {
            TrendDown=false;
            TrendUp=false;
         }
     }//if (UseAdxTrendFilter)
      
     //Trend determination using candlestick direction
     if (UseCandleDirection)
     {
         for (int cc = 1; cc < LookBackCandleHours +1; cc++)
         {
            //Check long trend
            if (iClose(symbol, PERIOD_H1, cc) < iClose(symbol, PERIOD_H1, cc + 1)) TrendUp = false;
            if (iClose(symbol, PERIOD_H1, cc) > iClose(symbol, PERIOD_H1, cc + 1)) TrendDown = false;         
         }//for (int cc = 1: cc < LookBackCandleHours; cc++)
         
     }//if (UseCandleDirection)
      
   } // End of void DetermineTrendDirection(string symbol)

void TightenStopLoss()
{
   // Moves the JumpingStopPips and TrailingStopPips at 50% and 80% of tp

   
   //Calculate the number of pips in the trade tp
   int Multiplier;
   if (digits == 5) Multiplier = 100000; //5 digits
   else if (digits == 3) Multiplier = 1000; //3 digits (for Yen based pairs)   
   else if (digits == 2) Multiplier = 100; //2 digits (for Yen based pairs)   
   else Multiplier = 10000; //4 digits
   int tp = (OrderTakeProfit()*Multiplier);
   int op = (OrderOpenPrice()*Multiplier);
   

   if (OrderType() == OP_BUY) int Tpips = tp - op;
   if (OrderType() == OP_SELL) Tpips = op - tp;

   
   //Tighten JumpingStopPips and TrailingStopPips if necessary
   if (OrderType() == OP_BUY)
   {
      double Target1 = NormalizeDouble(OrderOpenPrice() + ((Tpips * 50/100) * point),digits);
      double Target2 = NormalizeDouble(OrderOpenPrice() + ((Tpips * 80/100) * point),digits);
      if (bid >= Target1 && JumpingStopPips > TrailAt50Percent) JumpingStopPips = TrailAt50Percent;
      if (bid >= Target2 && JumpingStopPips > TrailAt80Percent) JumpingStopPips = TrailAt80Percent;
      if (bid >= Target1 && TrailingStopPips > TrailAt50Percent) TrailingStopPips = TrailAt50Percent;
      if (bid >= Target2 && TrailingStopPips > TrailAt80Percent) TrailingStopPips = TrailAt80Percent;   
   }//if (OrderType() == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      Target1 = NormalizeDouble(OrderOpenPrice() - ((Tpips * 50/100) * point),digits);
      Target2 = NormalizeDouble(OrderOpenPrice() - ((Tpips * 80/100) * point),digits);
      if (ask <= Target1 && JumpingStopPips > TrailAt50Percent) JumpingStopPips = TrailAt50Percent;
      if (ask <= Target2 && JumpingStopPips > TrailAt80Percent) JumpingStopPips = TrailAt80Percent;
      if (ask <= Target1 && TrailingStopPips > TrailAt50Percent) TrailingStopPips = TrailAt50Percent;
      if (ask <= Target2 && TrailingStopPips > TrailAt80Percent) TrailingStopPips = TrailAt80Percent;   
   }//if (OrderType() == OP_SELL)
 
  
}//End void TightenStopLoss()



void InsertStopLoss()
{
   if (OrderType() != OP_BUY && OrderType() != OP_SELL) return;
   
   if (OrderStopLoss() != 0 || (MissingStopLossPips == 0 && !UseSlAtr) ) return; //Nothing to do
   
   double ConvertedMSLP = MissingStopLossPips;
   double spread = MarketInfo(OrderSymbol(), MODE_SPREAD);
   
  
   //There is the option for the user to use Atr to calculate the stop
   if (UseSlAtr) double AtrVal = iATR(OrderSymbol(), AtrSlTimeFrame, AtrSlPeriod, 0) * AtrSlMultiplier;
   
   // Buy trade
   if (OrderType() == OP_BUY)
   {
      double SL = NormalizeDouble(OrderOpenPrice() - (ConvertedMSLP * point),digits);    
      if (UseSlAtr) SL = NormalizeDouble(OrderOpenPrice() - AtrVal, digits);
   }//if (OrderType() == OP_BUY)
   
   
   // Sell trade
   if (OrderType() == OP_SELL)
   {
      SL = NormalizeDouble(OrderOpenPrice() + (ConvertedMSLP * point), digits);
      if (UseSlAtr) SL = NormalizeDouble(OrderOpenPrice() + AtrVal, digits);
   }//if (OrderType() == OP_BUY)
   
   bool result = OrderModify(OrderTicket(),OrderOpenPrice(), SL, OrderTakeProfit(), OrderExpiration(),CLR_NONE);
   if (!result)
   {
      int err=GetLastError();
      Alert(OrderSymbol(), " SL insertion failed with error(",err,"): ",ErrorDescription(err));
      Print(OrderSymbol(), " SL insertion failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (!result)
   
}// End void InsertStopLoss()

void InsertTakeProfit()
{
   if (OrderType() != OP_BUY && OrderType() != OP_SELL) return;
   
   if (OrderTakeProfit() != 0 || (MissingTakeProfitPips == 0 && !UseSlAtr) ) return; //Nothing to do

   //There is the option for the user to use Atr to calculate the stop
   if (UseTpAtr) double AtrVal = iATR(OrderSymbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
   
   // Buy trade
   if (OrderType() == OP_BUY)
   {
      double TP = NormalizeDouble(ask + (MissingTakeProfitPips * point),digits);
      if (UseSlAtr) TP = NormalizeDouble(OrderOpenPrice() + AtrVal, digits);
   }//if (OrderType() == OP_BUY)
   
   
   // Sell trade
   if (OrderType() == OP_SELL)
   {
      TP = NormalizeDouble(bid - (MissingTakeProfitPips * point), digits);
      if (UseSlAtr) TP = NormalizeDouble(OrderOpenPrice() - AtrVal, digits);
   }//if (OrderType() == OP_BUY)
   
   bool result = OrderModify(OrderTicket(),OrderOpenPrice(), OrderStopLoss(), TP, OrderExpiration(),CLR_NONE);
   if (!result)
   {
      int err=GetLastError();
      Alert(OrderSymbol(), " TP insertion failed with error(",err,"): ",ErrorDescription(err));
      Print(OrderSymbol(), " TP insertion failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)
   
}// End void InsertTakeProfit()

void HiddenStopLoss()
{
   //Called from ManageTrade if HideStopLossEnabled = true


   //Should the order close because the stop has been passed?
   //Buy trade
   if (OrderType() == OP_BUY)
   {
      double sl = NormalizeDouble(OrderOpenPrice() - (HiddenStopLossPips * point), digits);
      if (bid <= sl)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (bid <= sl)      
   }//if (OrderType() == OP_BUY)
   
   //Sell trade
   if (OrderType() == OP_SELL)
   {
      sl = NormalizeDouble(OrderOpenPrice() + (HiddenStopLossPips * point), digits);
      if (ask >= sl)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (ask >= sl)   
   }//if (OrderType() == OP_SELL)
   

}//End void HiddenStopLoss()

void HiddenTakeProfit()
{
   //Called from ManageTrade if HideStopLossEnabled = true


   //Should the order close because the stop has been passed?
   //Buy trade
   if (OrderType() == OP_BUY)
   {
      double tp = NormalizeDouble(OrderOpenPrice() + (HiddenTakeProfitPips * point), digits);
      if (bid >= tp)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (ask >= tp)      
   }//if (OrderType() == OP_BUY)
   
   //Sell trade
   if (OrderType() == OP_SELL)
   {
      tp = NormalizeDouble(OrderOpenPrice() - (HiddenTakeProfitPips * point), digits);
      if (ask <= tp)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (bid <= tp)   
   }//if (OrderType() == OP_SELL)
   

}//End void HiddenTakeProfit()


void ManageTrade()
{
     
   // Call the working subroutines one by one. 

   //Cut down 5 digit order modify calls for 5 digit crims, if required
   static int NoOfTicks = 9;
   int ndigits = MarketInfo(Symbol(), MODE_DIGITS);
   if (DoNotOverload5DigitCriminals && ( ndigits == 3 || ndigits == 5) )
   {
      NoOfTicks++;
   }//if (DoNotOverload5DigitCriminals && ( digits == 3 || digits == 5) )
   
   if (!DoNotOverload5DigitCriminals || ndigits == 2 || ndigits == 4)
   {
      NoOfTicks = 10;
   }//if (!DoNotOverload5DigitCriminals || digits == 2 || digits == 4)
   
   
   // Global variable to pick up on failed part-closes
   if (GlobalVariablesTotal()>0) GlobalVariablesExist=true;
   if (GlobalVariablesExist && GlobalVariablesTotal()>0) TryPartCloseAgain();
   if (GlobalVariablesExist && GlobalVariablesTotal()==0) GlobalVariablesExist=false;
   
   if (NoOfTicks >= 10)
   {
      NoOfTicks = 0;//Reset the counter
      
      // Hidden stop loss
      if (HideStopLossEnabled) HiddenStopLoss();
   
      // Hidden take profit
      if (HideTakeProfitEnabled) HiddenTakeProfit();
   
      // Tighten the stop loss
      if (UseTigheningStop) TightenStopLoss();
      
      // Breakeven
      if(BreakEven) BreakEvenStopLoss();
   
      // JumpingStop
      if(JumpingStop) JumpingStopLoss();
   
      // TrailingStop
      if(TrailingStop) TrailingStopLoss();

      // Trailing stop loss that moves as soon as the market moves in the direction of the trade.
      if (InstantTrailingStop) InstantTrailingStopLoss();
   }//if (NoOfTicks = 10)
   
   // Hedge trade
   if (HedgeEnabled)
   {
       string tn = DoubleToStr(OrderTicket(),0);
       if (!GlobalVariableCheck(tn) ) GlobalVariableSet(tn, HedgeAtLossPips);       
       HedgeTrade();
   }//if (HedgeEnabled)
   
   // Add missing Stop Loss
   if (AddMissingStopLoss) InsertStopLoss();
   
   // Add missing Take Profit
   if (AddMissingTakeProfit) InsertTakeProfit();
   
} // End of ManageTrade()


void TryPartCloseAgain()
   {
      // Called if GlobalVariablesExist is set to true and global variables exist.
      // Attempts to part-close where a previous attempt failed
      
      string name;
      int index;
      int TicketNumber;
      for (int cc=0; cc < GlobalVariablesTotal(); cc++)
      {
         name = GlobalVariableName(cc);// Extract gv name
         index = StringFind(name,"GlobalVariableTicketNo",0);// Is it relevent to this function?
         if (index>-1)// If so, then retry the part-close
         {
            TicketNumber = GlobalVariableGet(name);
            //Make sure trade was not closed previously
            if (OrderSelect(TicketNumber, SELECT_BY_TICKET) && OrderCloseTime() == 0)
            {
               bool PartCloseSuccess = PartCloseTradeFunction();
               if (PartCloseSuccess)
               {
                  GlobalVariableDel(name);
                  cc--;
               }//if (PartCloseSuccess)
            }//if (OrderSelect(), TicketNumber, SELECT_BY_POS)
            else
            {
               GlobalVariableDel(name);
               cc--;
            }
         }//if (index>-1)
      }//for (int cc=0; cc < GlobalVariablesTotal(); cc++)
   }//void TryPartCloseAgain()


void main()
{
   //############## ADDED BY CACUS
   suffix = StringSubstr(Symbol(),6,4);
   int qty=PairsQty();
   
   
   int i = 0;int j = 0;
   for (int k = 0; k < qty; k ++)
   {
      i = StringFind(String, ",",j);
      if (i > -1)
      {
         ManagePair[k] = StringSubstr(String, j,i-j);
         ManagePair[k] = StringTrimLeft(ManagePair[k]);
         ManagePair[k] = StringTrimRight(ManagePair[k]);
         ManagePair[k] = StringConcatenate(ManagePair[k], suffix);
         j = i+1;         
      }
   }
   /*Print("PairsQty: ",qty); // Just to check....
   for (int s=1;s<=qty;s++){
   Print("Pair ",s,": ", ManagePair[s-1]);
   }
      */
   //############## ADDED BY CACUS   
    
   //At the start of each new hour, delete orphaned hedge global variables   
   if (OldHourlyBars != iBars(Symbol(), PERIOD_H1) )
   {
      if (GlobalVariablesTotal() > 0) DeleteOrphanHedgeGVs();
      OldHourlyBars = iBars(Symbol(), PERIOD_D1);
   }//if (OldHourlyBars != iBars(Symbol(), PERIOD_H1) )
   
   
   // Stop if there is nothing to do
   if (OrdersTotal()==0)
   {
      if (ShowComments) Comment("No trades to manage. I am bored witless.");
      return(0);
   }
   
   
   MonitorTrades(); // Stop loss adjusting, part closure etc
   
   
   

}//end void main()

//=============================================================================
//                           O_R_CheckForHistory()
//
//  This function is to work around a very annoying and dangerous bug in MT4:
//      immediately after you send a trade, the trade may NOT show up in the
//      order history, even though it exists according to ticket number.
//      As a result, EA's which count history to check for trade entries
//      may give many multiple entries, possibly blowing your account!
//
//  This function will take a ticket number and loop until
//  it is seen in the history.
//
//  RETURN VALUE:
//     TRUE if successful, FALSE otherwise
//
//
//  FEATURES:
//     * Re-trying under some error conditions, sleeping a random
//       time defined by an exponential probability distribution.
//
//     * Displays various error messages on the log for debugging.
//
//  ORIGINAL AUTHOR AND DATE:
//     Matt Kennel, 2010
//
//=============================================================================
bool O_R_CheckForHistory(int ticket)
{
   //My thanks to Matt for this code. He also has the undying gratitude of all users of my trading robots
   
   int lastTicket = OrderTicket();

   int cnt = 0;
   int err = GetLastError(); // so we clear the global variable.
   err = 0;
   bool exit_loop = false;
   bool success=false;

   while (!exit_loop) {
      /* loop through open trades */
      int total=OrdersTotal();
      for(int c = 0; c < total; c++) {
         if(OrderSelect(c,SELECT_BY_POS,MODE_TRADES) == true) {
            if (OrderTicket() == ticket) {
               success = true;
               exit_loop = true;
            }
         }
      }
      if (cnt > 3) {
         /* look through history too, as order may have opened and closed immediately */
         total=OrdersHistoryTotal();
         for(c = 0; c < total; c++) {
            if(OrderSelect(c,SELECT_BY_POS,MODE_HISTORY) == true) {
               if (OrderTicket() == ticket) {
                  success = true;
                  exit_loop = true;
               }
            }
         }
      }

      cnt = cnt+1;
      if (cnt > O_R_Setting_max_retries) {
         exit_loop = true;
      }
      if (!(success || exit_loop)) {
         Print("Did not find #"+ticket+" in history, sleeping, then doing retry #"+cnt);
         O_R_Sleep(O_R_Setting_sleep_time, O_R_Setting_sleep_max);
      }
   }
   // Select back the prior ticket num in case caller was using it.
   if (lastTicket >= 0) {
      OrderSelect(lastTicket, SELECT_BY_TICKET, MODE_TRADES);
   }
   if (!success) {
      Print("Never found #"+ticket+" in history! crap!");
   }
   return(success);
}//End bool O_R_CheckForHistory(int ticket)

//=============================================================================
//                              O_R_Sleep()
//
//  This sleeps a random amount of time defined by an exponential
//  probability distribution. The mean time, in Seconds is given
//  in 'mean_time'.
//  This returns immediately if we are backtesting
//  and does not sleep.
//
//=============================================================================
void O_R_Sleep(double mean_time, double max_time)
{
   if (IsTesting()) {
      return;   // return immediately if backtesting.
   }

   double p = (MathRand()+1) / 32768.0;
   double t = -MathLog(p)*mean_time;
   t = MathMin(t,max_time);
   int ms = t*1000;
   if (ms < 10) {
      ms=10;
   }
   Sleep(ms);
}//End void O_R_Sleep(double mean_time, double max_time)

bool DoesTradeExist()
{
   
   //TicketNo = -1;
   
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      
      if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
      {
         //TicketNo = OrderTicket();
         return(true);         
      }//if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
   }//for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)

   return(false);

}//End bool DoesTradeExist()

bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
{
   
   
   int slippage = 10;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYSTOP) col = Green;
   
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);

   if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, CLR_NONE);
   
   
   //Is a 2 stage criminal
   if (CriminalIsECN)
   {
      bool result;
      int err;
      ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, CLR_NONE);
      if (ticket > 0)
      {
	     
	     if (take > 0 && stop > 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)			  
        }//if (take > 0 && stop > 0)
      
	     if (take != 0 && stop == 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)			  
        }//if (take == 0 && stop != 0)

        if (take == 0 && stop != 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)			  
        }//if (take == 0 && stop != 0)

      }//if (ticket > 0)
        
      
      
   }//if (CriminalIsECN)
   
   //Error trapping for both
   if (ticket < 0)
   {
      string stype;
      if (type == OP_BUY) stype = "OP_BUY";
      if (type == OP_SELL) stype = "OP_SELL";
      if (type == OP_BUYLIMIT) stype = "OP_BUYLIMIT";
      if (type == OP_SELLLIMIT) stype = "OP_SELLLIMIT";
      if (type == OP_BUYSTOP) stype = "OP_BUYSTOP";
      if (type == OP_SELLSTOP) stype = "OP_SELLSTOP";
      err=GetLastError();
      Alert(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
      Print(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)  
   
   
   //TicketNo = ticket;
   //Make sure the trade has appeared in the platform's history to avoid duplicate trades
   O_R_CheckForHistory(ticket); 
   
   //Got this far, so trade send succeeded
   return(true);
   
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)

int CountTradeLevels()
{
   BuyOpen = 0;
   SellOpen = 0;
   TotalLotsOpen = 0;
   
   if (OrdersTotal() == 0) return;
   
   for (int cc = 0; cc <= OrdersTotal(); cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == 0)
      {
         if (OrderType() == OP_BUY) BuyOpen++;
         if (OrderType() == OP_SELL) SellOpen++;
         TotalLotsOpen+= OrderLots();
      }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == 0)
      
   }//for (int cc = 0; cc <= OrdersTotal(); cc++)
   

}//int CountTradeLevels()

bool CheckTradingTimes()
{
   int hour = TimeHour(TimeLocal() );
   
   if (end_hourm < start_hourm)
	{
		end_hourm += 24;
	}
	

	if (end_houre < start_houre)
	{
		end_houre += 24;
	}
	
	bool ok2Trade = true;
	
	ok2Trade = (hour >= start_hourm && hour <= end_hourm) || (hour >= start_houre && hour <= end_houre);

	// adjust for past-end-of-day cases
	// eg in AUS, USDJPY trades 09-17 and 22-06
	// so, the above check failed, check if it is because of this condition
	if (!ok2Trade && hour < 12)
	{
 		hour += 24;
		ok2Trade = (hour >= start_hourm && hour <= end_hourm) || (hour >= start_houre && hour <= end_houre);		
		// so, if the trading hours are 11pm - 6am and the time is between  midnight to 11am, (say, 5am)
		// the above code will result in comparing 5+24 to see if it is between 23 (11pm) and 30(6+24), which it is...
	}


   // check for end of day by looking at *both* end-hours

   if (hour >= MathMax(end_hourm, end_houre))
   {      
      ok2Trade = false;
   }//if (hour >= MathMax(end_hourm, end_houre))

   return(ok2Trade);

}//bool CheckTradingTimes()

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start() 
{

//----


if (Bars != ThisBarTrade ) {
   ThisBarTrade = Bars;  // ensure only one trade opportunity per bar
   RefreshRates();

   EvaluateCloseThis();
   if (ClosingThis) return(0);
   
 //----  

   if (!IsDemo() )
   {
      Alert("R&R is not enabled for live trading");
      return;
   }//if (IsDemo() )
   
   
   CountTradeLevels();
   
   //mptm
	//The always on code is provided by gspe. Many thanks, Guiseppe
	if (AlwaysOn == true) 
	{
		while (IsExpertEnabled())	// Check if expert advisors are enabled for running
		{							// This is an infinite loop so the expert doesn't wait for ticks
			main();
			Sleep(delay);
			WindowRedraw();
		}
	} 
	else 
	{
		main(); 
	}
			 
	
   //Calculate available equity
   if (AccountMargin() > 0)
   {
      MarginLevelPercent = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2);
      if (MarginLevelPercent < FkMinimumMarginPercent)
      {      
         return;
      }//if (MarginLevelPercent < FkMinimumMarginPercent)
   }//if (OrdersTotal() > 0)
   
			 
	if (DoesTradeExist() )
   {
      return;
   }//if (DoesTradeExist() )
   
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //Trading times
   bool TradeTimeOk = CheckTradingTimes();
   if (!TradeTimeOk)
   {
      Comment("Outside trading hours\nstart_hourm-end_hourm: ", start_hourm, "-",end_hourm, "\nstart_houre-end_houre: ", start_houre, "-",end_houre);
      return;
   }//if (hour < start_hourm)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   
   //R&R
   double take = 0;
   bool result = false;
   while (!result)
   {
      RefreshRates();
      if (TakeProfit > 0) take = NormalizeDouble(Ask + (TakeProfit * Point), Digits);
      result = SendSingleTrade(OP_BUY, TradeComment, Lot, Ask, 0, take);   
   }//while (!result)
   
   result = false;
   while (!result)
   {
      if (TakeProfit > 0) take = NormalizeDouble(Bid - (TakeProfit * Point), Digits);
      RefreshRates();
      result = SendSingleTrade(OP_SELL, TradeComment, Lot, Bid, 0, take);   
   }//while (!result)

			 
	return(0);   
}//End int start() 
}