//+-------------------------------------------------------------------+
//|                   Generic auto trading robot by Steve Hopwood.mq4 |
//|                                  Copyright © 2009, Steve Hopwood  |
//|                              http://www.hopwood3.freeserve.co.uk  |
//+-------------------------------------------------------------------+
#property copyright "Copyright © 2009, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
#define  up ": market is trending up"
#define  down ": market is trending down"
#define  buy "Buy"
#define  sell "Sell"
#define  none "None"
#define  ranging ": market is ranging and so there will be no trading"
#define  confused "Confused, and so cannot trade"
#define  trending "Trending"
#define  opentrade "There is a trade open"
#define  stopped "Trading is stopped"
#define  retraceup " Up"
#define  retracedown " Down"
#define  retracenone " None"


/*


FUNCTIONS LIST
int init()
int start()

----Trading----

void LookForTradingOpportunities()
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
bool DoesTradeExist()
bool CloseTrade(int ticket)
void LookForTradeClosure()
bool CheckTradingTimes()

----Retrace----
bool RetraceLongTrend()
bool RetraceShortTrend()



----Matt's Order Reliable library code
bool O_R_CheckForHistory(int ticket) Cheers Matt, You are a star.
void O_R_Sleep(double mean_time, double max_time)

----Indicator readings----
void ReadIndicatorValues()
double GetRsi(int tf, int period, int ap, int shift)
void GetRetraceDirection()



----Trade management module----
int CountTradeLevels()
bool CheckTradingTimes()
double GetMaxLotsAllowed()
void EvaluatePosition()


void HedgeTrade()
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 DeleteOrphanHedgeGVs()
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()

*/

extern string  gen="----General inputs----";
extern double  Lot=0.1;
extern int     TakeProfit=0;
extern int     StopLoss=0;
extern int     MagicNumber=0;
extern string  TradeComment="";
extern bool    CriminalIsECN=false;
extern int     FkMinimumMarginPercent=1500;
extern string  rm="----Retrace measurements----";
extern int     RetraceCandles=3;
extern int     MinTriggerCandlePipsMovement=10;
extern string  rsiin="----Rsi inputs----";
extern int     RsiTf=1440;
extern int     RsiPeriod=20;
extern string  rsap="Applied price: 0=Close; 1=Open; 2=High";
extern string  rsap1="3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     RsiAppliedPrice=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;

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=false;
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----";
extern bool    HedgeEnabled=true;
extern int     HedgeAtLossPips=100;
extern double  HedgeLotsPercent=200;
extern int     HedgingIncrementPips=0;
extern int     HedgeTradeStopLoss=0;
extern int     HedgeTradeTakeProfit=0;
extern bool    CloseAtBreakEven=true;
extern bool    HedgingTheHedgeIsAllowed=true;
//extern double  HedgeTheHedgeLotsPercent=200;
//extern int     HedgeTheHedgeAtLossPips=10;
extern double  CashProfitPerBreakEvenPip=1;
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;


extern string  mis="----Odds and ends----";
extern bool    ShowManagementAlerts=true;
extern int     DisplayGapSize=30;

//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 */

//Trading variables
int            TicketNo, OpenTrades;

//Rsi
double         RsiVal;

//Trend
string         trend, retracedirection;

//Misc
string         Gap, ScreenMessage;
int            OldBars;
string         PipDescription=" pips";
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;
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            BuyOpen, SellOpen;//For calculating trade levels

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
double         TotalOfBuyLots, TotalOfSellLots;//Calculated by EvaluatePosition() and used in freezing

void DisplayUserFeedback()
{
   
   if (IsTesting() && !IsVisualMode()) return;

   ScreenMessage = "";
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), NL );
         
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);      
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Take profit: ", TakeProfit, PipDescription,  NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Stop loss: ", StopLoss, PipDescription,  NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number: ", MagicNumber, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade comment: ", TradeComment, NL);
   if (CriminalIsECN) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = true", NL);
   else ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = false", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), NL, NL );
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trading hours", NL);
   if (start_hourm == 0 && end_hourm == 12 && start_houre && end_houre == 24) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "            24H trading", NL);
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "            start_hourm: ", DoubleToStr(start_hourm, 2), 
                      ": end_hourm: ", DoubleToStr(end_hourm, 2), NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "            start_houre: ", DoubleToStr(start_houre, 2), 
                      ": end_houre: ", DoubleToStr(end_houre, 2), NL);
                      
   }//else
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "RetraceCandles: ", RetraceCandles, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MinTriggerCandlePipsMovement: ", MinTriggerCandlePipsMovement, PipDescription, NL);
   
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Rsi: ", RsiVal, trend, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Candle retrace direction:", retracedirection, NL);
   
   
   

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   
      
   Comment(ScreenMessage);


}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----

   //Adapt to x digit criminals
   int 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;   
   
   if (multiplier > 1) PipDescription = " points";
   
   TakeProfit*= multiplier;
   StopLoss*= multiplier;
   MinTriggerCandlePipsMovement*= 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;
   

   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   

   if (TradeComment == "") TradeComment = " ";
   OldBars = Bars;
   ReadIndicatorValues();//For initial display in case user has turned of constant re-display
   DisplayUserFeedback();
   
   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
//----
   return(0);
}



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, col);
   
   
   //Is a 2 stage criminal
   if (CriminalIsECN)
   {
      bool result;
      int err;
      ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col);
      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)

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()



void LookForTradingOpportunities()
{


   RefreshRates();
   double take, stop, price;
   int type;
   bool SendTrade;

   //Long 
   if (trend == up && retracedirection == retracedown && Ask > Open[0] && Ask - Open[0] >= (MinTriggerCandlePipsMovement * Point) )
   {
      if (TakeProfit > 0) take = NormalizeDouble(Ask + (TakeProfit * Point), Digits);
      if (StopLoss > 0) stop = NormalizeDouble(Ask - (StopLoss * Point), Digits);
      type = OP_BUY;
      price = Ask;
      SendTrade = true;
   }//if (trend == up && Ask > Open[0] && Ask - Open[0] >= (MinTriggerCandlePipsMovement * Point) )
   

   //Short
   if (trend == down && retracedirection == retraceup  && Bid < Open[0] && Open[0] - Bid >= (MinTriggerCandlePipsMovement * Point) )
   {
      if (TakeProfit > 0) take = NormalizeDouble(Bid - (TakeProfit * Point), Digits);
      if (StopLoss > 0) stop = NormalizeDouble(Bid + (StopLoss * Point), Digits);
      type = OP_SELL;
      price = Bid;
      SendTrade = true;      
   }//if (trend == down && Bid < Open[0] && Open[0] - Bid >= (MinTriggerCandlePipsMovement * Point) )
   

   if (SendTrade)
   {
      bool result = SendSingleTrade(type, TradeComment, Lot, price, stop, take);
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {
   
   }//if (result)
   
   //Actions when trade send fails
   if (SendTrade && !result)
   {
   
   }//if (!result)
   
   

}//void LookForTradingOpportunities()

bool CloseTrade(int ticket)
{   
   while(IsTradeContextBusy()) Sleep(100);
   bool result = OrderClose(ticket, OrderLots(), OrderClosePrice(), 1000, CLR_NONE);

   //Actions when trade send succeeds
   if (result)
   {
      return(true);
   }//if (result)
   
   //Actions when trade send fails
   if (!result)
   {
      return(false);
   }//if (!result)
   

}//End bool CloseTrade(ticket)

////////////////////////////////////////////////////////////////////////////////////////////////
//Indicator module

double GetRsi(int tf, int period, int ap, int shift)
{
   return(iRSI(NULL, tf, period, ap, shift) );
}//End double GetRsi(int tf, int period, int ap, int shift)

void GetRetraceDirection()
{
   //Determines if a retrace has taken place
   
   retracedirection = retracedown;
   for (int cc = 1; cc < RetraceCandles; cc++)
   {
      if (Low[cc] >= Low[cc + 1] ) retracedirection = retracenone;
   }//for (int cc == 1; cc <= RetraceCandles; cc++)

   if (retracedirection == retracedown) return;

   retracedirection = retraceup;
   for (cc = 1; cc < RetraceCandles; cc++)
   {
      if (High[cc] <= High[cc + 1] ) retracedirection = retracenone;
   }//for (int cc == 1; cc <= RetraceCandles; cc++)
   if (retracedirection == retraceup) return;
   

   //Got this far, so no measurable retrace
   retracedirection = none;

}//void GetRetraceDirection()


void ReadIndicatorValues()
{

   RsiVal = GetRsi(RsiTf, RsiPeriod, RsiAppliedPrice, 0);
   
   trend = ranging;
   if (RsiVal > 55) trend = up;
   if (RsiVal < 45) trend = down;
   
   
   GetRetraceDirection();
   
}//void ReadIndicatorValues()

//End Indicator module
////////////////////////////////////////////////////////////////////////////////////////////////

void LookForTradeClosure()
{
   //Close the trade if the new candle opens inside the bands
   
   if (!OrderSelect(TicketNo, SELECT_BY_TICKET) ) return;
   
   bool CloseTrade;
   
   if (OrderType() == OP_BUY)
   {

   }//if (OrderType() == OP_BUY)
   
   
   if (OrderType() == OP_SELL)
   {

   }//if (OrderType() == OP_SELL)
   
   if (CloseTrade)
   {
      bool result = CloseTrade(TicketNo);
      //Actions when trade send succeeds
      if (result)
      {
   
      }//if (result)
   
      //Actions when trade send fails
      if (!result)
      {
   
      }//if (!result)
   

   }//if (CloseTrade)
   
   
}//void LookForTradeClosure()


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()


//=============================================================================
//                           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)

void MonitorTrades()
{

   bool ManageTrade; // tell the program when there is a trade to manage
   
   double spread = MarketInfo(Symbol(), MODE_SPREAD);
   
   string ScreenMessage = NL + NL;
   
   if (OrderSelect(TicketNo, SELECT_BY_TICKET) )
   {
      
      ManageTrade=false;
      // Set up bid and ask so the program can use them to calculate jumping stops, be's etc
      bid = MarketInfo(Symbol(), MODE_BID);           
      ask = MarketInfo(Symbol(), MODE_ASK);
      point = MarketInfo(Symbol(), MODE_POINT);
      digits = MarketInfo(Symbol(), MODE_DIGITS);
      
                                         
      ManageTrade(); // The subroutine that calls the other working subroutines
      
   } // Close if (OrderSymbol()==Symbol())
      
   
   
   
   
} // 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()


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;
   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)
   {
      takeprofit = 0;
      stoploss = 0;
      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);
         //Max lot size allowed check. If reached, freeze the position
         double LotToSend = TotalOfSellLots - TotalOfBuyLots;
         bool SendSuccess = false;
         
         
         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 (ticket>0)      

   }

if (OrderType()==OP_SELL)
   {
      takeprofit = 0;
      stoploss = 0;
      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);
         //Max lot size allowed check. If reached, freeze the position
         EvaluatePosition();
         LotToSend = TotalOfBuyLots - TotalOfSellLots;
         SendSuccess = false;
         
         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 EvaluatePosition()
{
   //Can hold any evaluation tools we need
   TotalOfBuyLots = 0;
   TotalOfSellLots = 0;
   OpenTrades = 0;
   
   int cc;
   
   //Trading frozen check
   for (cc = OrdersTotal() - 1; cc>= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
      OpenTrades++;
      if (OrderType() == OP_BUY) TotalOfBuyLots+= OrderLots();
      if (OrderType() == OP_SELL) TotalOfSellLots+= OrderLots();      
   }//for (cc = OrdersTotal() - 1); cc>= 0; cc--)
   
   
}//void EvaluatePosition()


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()
{
    
   //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) )
   
      
   MonitorTrades(); // Stop loss adjusting, part closure etc
   
   
   

}//end void main()



//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----

   static bool TradeExists;
   
   if (OrdersTotal() == 0)
   {
      TicketNo = -1;
   }//if (OrdersTotal() == 0)

   if (OldBars != Bars)
   {
      ReadIndicatorValues();
      OldBars = Bars;
   }//if (OldBars != Bars)
   
   
      
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Find open trades
   if (OrdersTotal() > 0)
   {
      TradeExists = DoesTradeExist();
      if (TradeExists )
      {
         main();
         LookForTradeClosure();
      }//if (TradeExists)
   }//if (OrdersTotal() > 0)

   ///////////////////////////////////////////////////////////////////////////////////////////////
   
   
 
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //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)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   ///////////////////////////////////////////////////////////////////////////////////////////////         
   //Trading
   if (TicketNo == -1 && trend != ranging && retracedirection != retracenone)
   {
      LookForTradingOpportunities();
   }//if (TicketNo == -1)
   ///////////////////////////////////////////////////////////////////////////////////////////////      

   DisplayUserFeedback();
   
//----
   return(0);
}
//+------------------------------------------------------------------+